Таким образом, мое приложение будет вызывать ниже дорогой HTTP-сервис несколько раз (одновременно несколькими потоками с одинаковыми, а также разными идентификаторами для каждого запроса клиента к моему приложению).
Mono<Foo> response = myService.fetch(id);
Я хотел бы кэшироватьОтвет (в памяти) в течение нескольких часов, а затем только при следующем запросе клиента сделать только один вызов для обновления кэша.
Подход 1:
Mono<Foo> cachedResponse = Mono.empty();
public Mono<Foo> get(String id){
return cachedResponse.switchIfEmpty(Mono.defer(()->
{
cachedResponse = myService.fetch(id).cache(Duration.ofHours(4));
return cachedResponse;
}));
}
подходит ли следующий подход?В частности, поскольку несколько потоков могут вызывать метод get с одинаковым идентификатором.Кроме того, если кэш-память через 4 часа станет недействительной, сделает ли cachedResponse Mono пустым для правильной работы switchIfEmpty?
Подход 2: Я мог бы использовать какое-то решение для кэширования для хранения кеша в течение нескольких часов.,например,
Foo getFromCacheSolution(String id);
, а затем,
public Mono<Foo> get(String id){
Foo cachedFoo = getFromCacheSolution(id);
if(cachedFoo != null){
return Mono.just(cachedFoo);
}
else{
return myService.fetch(id).doOnNext(value->storeToCacheSolution(id, value)); //line 7
}
}
Проблема с этим решением состоит в том, что строка 7 будет вызываться несколько раз, что приведет к многочисленным вызовам дорогостоящей службы выборки (например, если 3 потокавведите метод get с идентификатором 123 и cachedFoo имеет значение null).Выполнение синхронизированного метода может не помочь, так как строка 7 завершится мгновенно.
Одним из решений может быть сохранение Mono в решении для кэширования вместо Foo (не уверен, что это хорошая идея или нет):
Mono<Foo> getFromCacheSolution(String id); //returns cached or empty Mono
, а затем
public Mono<Foo> get(String id){
return getFromCacheSolution(id).switchIfEmpty(Mono.defer(()->
{
cachedResponse = myService.fetch(id).doOnNext(value->storeToCacheSolution(id, value));
return cachedResponse;
}));
}
Любые рекомендации или лучшие альтернативы?