Is there a way to cache the response from a call if the inputs are the same? For example, if the fileName is the same, I don't want to make the request out with my webClient again since it takes a while for the response.
Flux.fromIterable(files).flatMap(
file -> {
Mono<String> extension = getExtension(file.getName());
});
public Mono<String> getExtension(String fileName) {
return webClient.get().uri(extensionUrl + "?file=" + fileName).retrieve()
.bodyToMono(String[].class)
.map(
extensions -> {
System.out.println("finished retrieving");
return extensions[0];
});
}
Reactor doesn't provide any caching layer, but you can use any existing library or a plain Map
for caching, then check for an existing value before making the call. And put one on doOnNext
.
Caching an original Mono
itself may not work because it depends on actual implementation and in many cases a new subscription to it will cause a new request (but see below).
So the simplest implementation would be:
private Map<String, String> cache = new ConcurrentHashMap();
public Mono<String> getExtension(String fileName) {
String existing = cache.get(fileName);
if (existing != null) {
return Mono.just(existing);
}
return webClient.get().uri(extensionUrl + "?file=" + fileName).retrieve()
.bodyToMono(String[].class)
.map(....)
.doOnNext(value -> cache.put(fileName, value));
}
If you want to avoid duplicate in-flight requests as well, then it makes sense to cache the Mono
. But in this case I would suggest to ether use it with .cache()
, or even use a Sinks.One
as an intermediary.
The simplified code would look like:
private Map<String, Mono<String>> cache = new ConcurrentHashMap();
public Mono<String> getExtension(String fileName) {
Mono<String> existing = cache.get(fileName);
if (existing != null) {
return existing;
}
Mono<String> requested = webClient.get().uri(extensionUrl + "?file=" + fileName).retrieve()
.bodyToMono(String[].class)
.map(....)
// you probably don't want to keep failed requests in cache
.doOnError(t -> cache.remove(fileName))
.cache();
cache.put(fileName, requested);
return requested;
}