如何使reactor.cache.CacheMono不要两次调用计算?

时间:2019-03-03 22:18:50

标签: spring caching spock project-reactor reactor

我正在尝试为自己的设置实施缓存机制,但我真的无法使其工作。

我已经实现了这样的存储库:

ListView.builder

我已经这样配置它:

SliverList(delegate: SliverChildBuilderDelegate((context, index) {
  return Container();
}));

我正在尝试对其进行测试:

@AllArgsConstructor
public class CachedSettingsRepository<E extends SettingsEntity> implements SettingsRepository<E> {

    private final String key;
    private final SettingsRepository<E> settingsRepository;
    private final Cache<String, Signal<? extends E>> cache;

    @Trace
    @Override
    public Mono<E> get() {
        return CacheMono.lookup(cache.asMap(), key)
                        .onCacheMissResume(settingsRepository::get);

    }

    @Trace
    @Override
    public Mono<Void> delete() {
        return settingsRepository.delete()
                                 .doOnNext(empty -> cache.invalidate(key));
    }

    @Trace
    @Override
    public Mono<E> cas(Function<Mono<E>, Publisher<E>> function) {
        return settingsRepository.cas(function)
                                 .doOnNext(result -> cache.invalidate(key));
    }

}

我希望它会在第一次尝试时调用我的paymentSettingsRepository,然后在第二次尝试时返回缓存,但是测试始终失败。

1 个答案:

答案 0 :(得分:0)

这种行为的原因在于CacheMono实现和测试的特定性。这是CacheMono的代码:

public static <KEY, VALUE> MonoCacheBuilderMapMiss<VALUE> lookup(Map<KEY, ? super Signal<? extends VALUE>> cacheMap, KEY key) {
    return otherSupplier -> Mono.defer(() ->
            Mono.justOrEmpty(cacheMap.get(key))
                .switchIfEmpty(otherSupplier.get().materialize()
                                .doOnNext(value -> cacheMap.put(key, value)))
                .dematerialize()
    );
}

它仅在从缓存中获取之前使用defer调用,但是otherSupplier.get()没有被推迟,因此测试失败。

我想改变会很好     otherSupplier.get() 至     Mono.defer(() -> otherSupplier.get())