一旦我必须开始进行多个外部呼叫,我总是会陷入反应式思维方式。现在,我的任务是使用Reactor和Webflux实现以下方案。
到目前为止,我只是一个有关如何使用缓存的示例:
public static Mono<ServerResponse> doRequest(
Function<Mono<Token>, Mono<ClientResponse>> clientRequest,
Function<Mono<ClientResponse>, Mono<ServerResponse>> errorHandler
) {
Token token = null;
return token.getToken()
.transform(clientRequest)
.flatMap(clientResponse -> {
if (clientResponse.statusCode().value() == 403) {
// HOW WOULD I INVALIDATE ANYTHING HERE? Or where should i do it?
return Mono.error(new TokenExpired("Token expired"));
}
return Mono.just(clientResponse);
})
.transform(errorHandler)
.retryWhen(companion -> {
return companion.zipWith(Flux.range(1,4),
(error, index) -> {
if (index < 4 && (error instanceof TokenExpired)) {
return index;
} else {
throw Exceptions.propagate(error);
}
});
});
}
我看过addons缓存,但是由于仅基于时间,因此无法理解如何手动使缓存无效?同样,在使用Caffeine缓存时,在多线程环境中,invalidate的行为是不确定的。我觉得我的用例是标准的,但无法找到任何执行此操作的模式。
我遇到的两个问题是: 确保缓存的更新仅发生一次且没有阻塞。 如何以非阻塞方式使缓存中的条目无效。
真正沉迷于如何以反应性方式解决问题,公认的答案不一定是Reactor,它可以是任何反应性库,显示解决问题所需的思想。
答案 0 :(得分:1)
当计算失败或为空时,咖啡因将丢弃一个条目,并将其传播给调用方。对于AsyncCache
,它将立即存储将来,并且whenComplete
回调将在必要时进行错误处理。由于咖啡因可与CompleteableFuture
一起使用,因此您可以使用Reactor的单/未来转换器。
AsyncCache<Token, ServerResponse> responseCache = Caffeine.newBuilder().buildAsync();
public static Mono<ServerResponse> doRequest(
Function<Mono<Token>, Mono<ClientResponse>> clientRequest,
Function<Mono<ClientResponse>, Mono<ServerResponse>> errorHandler) {
Token token = // ...
Mono<ServerResponse> result = Mono.fromFuture(() -> token.getToken()
.transform(t -> cache.get(t, (token, executor) -> {
Mono<ServerResponse> response = clientRequest.apply(token);
return (response.statusCode().value() == HttpServletResponse.SC_FORBIDDEN)
? Mono.error(new TokenExpired("Token expired")).toFuture()
: Mono.just(clientResponse).toFuture();
})));
return result.transform(errorHandler).retryWhen(...);
}
cache.get(key, func)
仅在不存在映射时才插入将来(未清除的过期或收集的条目将被视为不存在)。这仅在将来将其返回到缓存的持续时间内阻塞,如果将来所有工作都被打包,那么这应该是便宜的。其他任何请求都将等待key-> future映射建立并在相同的将来返回,直到该映射被删除(失败或驱逐)为止。
基于此习惯用法,有可能将AsyncCache
的通用适配器编写到Reactor。