【发布时间】:2020-02-04 18:04:55
【问题描述】:
我知道如何memoize a single object。但是,我只想在满足某些条件时才记住。我正在调用一项服务,该服务有时会返回不成功的响应。如果服务响应成功,我只想记住它。
MyResponse myResponse = myService.call()
boolean success = myResponse.isSuccessful();
我的缓存是这样创建的:
private Supplier<MyResponse> cache;
private void createCache() {
this.cache = Suppliers
.memoizeWithExpiration(myService::call, timeout,
TimeUnit.MINUTES);
}
问题: 只有在使用传递给memoizeWithExpiration方法的供应商成功的情况下,是否可以以某种方式缓存响应?
我发现这样做的唯一解决方法是,在检索值时,首先调用cache.get(),检查存储在缓存中的对象是否成功,如果不是,再次调用createCache()清除它然后再次获得价值。这样,如果后续的服务调用返回一个有效的对象,它就会被存储,如果没有,每个后续的调用都会清除缓存并再次调用该服务。
public MyResponse getResponse() {
MyResponse myResponse = cache.get();
if (myResponse.isSuccess()) {
return myResponse;
} else {
createCache();
return cache.get();
}
}
但是,在这个解决方案中,如果缓存是空的并且服务返回不成功的响应,它会立即被再次调用。
【问题讨论】:
-
您在看错地方 IMO。您需要将
getResponse()中的逻辑更改为在所有情况下都不使用cache.get(),因为如果您成功不有条件地缓存它,这将无法返回结果。 IE。在您的else分支中,您调用myService::call,然后有条件地创建缓存。没有缓存? -> 调用服务,成功了吗? -> 缓存,否则返回错误,不缓存。 -
你是对的,但我不知道是否可以调用服务,然后选择缓存响应而不再次调用服务——这就是我在这里要问的。
memoizeWithExpiration方法的全部意义在于服务调用隐藏在缓存的get方法下。因此,我可以将值放入缓存的唯一方法是调用get方法,该方法调用下面的服务。如果您知道如何使用 Guava 实现这一点,请写一个答案,我很乐意接受。 -
此时您偏离了 Guava 的假设。 memoization 代码很简单,因此您可以复制它并使用您的其他用例进行扩展。
标签: java caching guava memoization