首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何打开Mono

如何打开Mono
EN

Stack Overflow用户
提问于 2019-11-21 11:50:12
回答 1查看 1.5K关注 0票数 2

我对网络流量很陌生,我正在尝试实现这个场景:

如果数据已经存在于redis缓存中,则

  • 客户端请求数据
  • ,然后返回缓存的数据
  • ,否则将查询数据

的远程服务。

我写了这段代码:

代码语言:javascript
复制
ReactiveRedisOperations<String, Foo> redisOps;

private Mono<Foo> getFoo(String k) {

    return this.redisOperations.opsForValue().get(k)
                .map(f -> this.logCache(k, f))
                .switchIfEmpty(this.queryRemoteService(k));
}

private void logCache(String k, Foo f) {
        this.logger.info("Foo # {} # {} present in cache. {}",
                k,
                null != f ? "" : "NOT",
                null != f ? "" : "Querying remote");
}

private Mono<Foo> queryRemoteService(String k) {

    this.logger.info("Querying remote service");

    // query code
}

它打印:

代码语言:javascript
复制
"Querying remote service"
"Foo # test_key # present in cache"

如何确保仅当缓存的数据不存在时才调用switchIfEmpty

编辑

因此,对于Michael的回答,我将代码重构如下:

代码语言:javascript
复制
private Mono<Foo> getFoo(String k) {

    this.logger.info("Trying to get cached {} data", k);

    this.logger.info(this.redisOps.hasKey(k).block() ? "PRESENT" : "NOT present");

    return this.redisOperations.opsForValue().get(k)
                .switchIfEmpty(this.queryRemoteService(k));
}

private Mono<Foo> queryRemoteService(String k) {

    this.logger.info("Querying remote service");

    // query code
}

现在我的输出是:

代码语言:javascript
复制
Trying to get cached test_key data
PRESENT
Querying provider

因此,似乎只执行了一次,但仍然无法避免执行switchIfEmpty。我确信redis包含了该密钥的数据

EN

回答 1

Stack Overflow用户

发布于 2019-11-21 12:17:57

这一行:

代码语言:javascript
复制
.map(f -> this.logCache(k, f))

...is相当奇怪,因为您没有将任何东西映射到任何东西,而是执行一个副作用(记录值。),在这里,doOnNext() (而不是map())将是一个更明智的选择。

不过,我离题了,这不是主要的问题。

如何确保仅当缓存的数据不存在时才调用switchIfEmpty

已经是这样了,但你的日志记录并没有像你想的那样。这里可能引起问题的关键概念是,null永远不能通过反应流传播。如果流是空的,如本例所示,则不会传播任何内容。

因此,在您的代码中,不会调用map() (如果使用的话也不会调用doOnNext() ),因此您的“存在缓存”行不会写入日志(因为没有要映射的值,也没有可以调用副作用的值)。因此,检查logCache()中的值是否为空是没有意义的--它永远不会是空的。

因此,在我看来,这里的日志输出必须是两个getFoo()调用的结果。

  • 第一个没有出现在缓存中,因此没有调用map(),没有调用switchIfEmpty()交换,并且打印了“查询远程服务”;在缓存中显示了
  • 第二个,所以打印了“在缓存中的礼物”行,没有调用switchIfEmpty(),因此没有打印“查询远程服务”。

要使您的日志记录有意义,您应该从logCache()中删除条件逻辑,并将“不在缓存中”行添加到queryRemoteService()方法中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58974349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档