Невозможно загрузить значение только из Redis, даже если значение присутствует

Я использую Reactive Redis, где пытаюсь использовать Redis в качестве кеша для базы данных. Я проверяю, присутствует ли значение в кеше или нет? Если он присутствует, верните его, в противном случае запросите базу данных, если результат вернется; сохранить результат в кэше и вернуть его.

Однако даже если значение присутствует в Redis, он все равно все время запрашивает базу данных.

public Mono<User> getUser(String email) {
    return reactiveRedisOperation.opsForValue().get("tango").switchIfEmpty(
        // Always getting into this block (for breakpoint) :(
        queryDatabase().flatMap(it -> {
            reactiveRedisOperation.opsForValue().set("tango", it, Duration.ofSeconds(3600)).then(Mono.just(it)); 
        })
    );
}

private Mono<User> queryDatabase() {
    return Mono.just(new User(2L,"test","test","test","test","test",true,"test","test","test"));
}

Но вызов всегда попадает в базу данных, даже если значение присутствует в Redis. Что я здесь делаю не так?


person nicholasnet    schedule 05.03.2020    source источник
comment
Может быть, попробовать извлечь эту reactiveRedisOperations.opsForValue() в переменную и использовать в этих двух местах?   -  person lczapski    schedule 06.03.2020
comment
Можете ли вы показать мне пример, поскольку я использую здесь Mono.   -  person nicholasnet    schedule 06.03.2020


Ответы (1)


Основываясь на этом ответе, вы можете попробовать Mono.defer:

public Mono<User> getUser(String email) {
    return reactiveRedisOperation.opsForValue().get("tango").switchIfEmpty(Mono.defer(() -> {
        // Always getting into this block (for breakpoint) :(
        queryDatabase().flatMap(it -> {
            reactiveRedisOperation.opsForValue().set("tango", it, Duration.ofSeconds(3600)).then(Mono.just(it)); 
        })})
    );
}

ОБНОВИТЬ:

У меня нет большого опыта работы с Mono. Ответ, который я указал, объясняет это:

... вычисление уже было запущено в момент, когда мы начинаем составлять наши Mono типы. Чтобы предотвратить нежелательные вычисления, мы можем заключить наше будущее в отложенную оценку:

... попадает в ловушку ленивого поставщика и планируется к выполнению только тогда, когда он будет запрошен.

person lczapski    schedule 06.03.2020
comment
К сожалению, это тоже не сработало. Он все еще запрашивает БД, даже если значение присутствует в Redis. - person nicholasnet; 06.03.2020
comment
@nicholasnet Update: новый подход - person lczapski; 06.03.2020
comment
Я тоже пробовал это, и это не сработало. Но теперь я пробую ваш, и он работает. С тех пор, как я перепробовал так много вещей, я потерял это из виду. Но ваше данное решение работает ... так что я в порядке. Спасибо большое за помощь. Но из любопытства, зачем нам здесь Mono.defer()? - person nicholasnet; 06.03.2020
comment
@nicholasnet Я добавил обновление, но объяснение в ответе, который я указал - person lczapski; 06.03.2020
comment
да, я заметил это позже. Я прочитал ссылку, это было хорошо, большое спасибо за то, что поделились ею. - person nicholasnet; 06.03.2020