首页 > 解决方案 > Guava 中的条件记忆

问题描述

我知道如何记忆单个对象。但是,我只想在满足某些条件的情况下进行记忆。我正在调用一项服务,该服务有时会返回不成功的响应。如果服务响应成功,我只想记住它。

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();
    }
  }

但是,在这个解决方案中,如果缓存为空并且服务返回不成功的响应,它将立即再次调用。

标签: javacachingguavamemoization

解决方案


您可以在服务类或任何其他合适的地方创建一个方法callUntilSuccess(这里我假设它在您的服务中)。您还可以在此方法中定义最大尝试次数,之后它将返回 null,因此您可以避免无限期地调用您的服务(此建议未在下面提供的代码中实现,但这样做很容易)。由于 Guava 方法需要一个供应商,您甚至可以使用此逻辑创建一个 lambda 并将其直接传递给该memoizeWithExpiration方法。

public MyResponse callUntilSuccess() {

    MyResponse response = myService.call();
    while (!response.isSuccessful()) {
        response = myService.call();
    }
    return response;
}   

然后以这种方式进行记忆:

private void createCache() {
    this.cache = Suppliers
         .memoizeWithExpiration(myService::callUntilSuccess, timeout,
                TimeUnit.MINUTES);
}   

推荐阅读