I store encryption keys in a Redis database. I want to implement a fallback mechanism to generate keys unless they are already present.
What confuses me with a solution I come up with is that I call subscribe
within an async context. My IDE pointed me this problem. So the question is how would you implement this fallback?
public Mono<String> getEncryptionKey(String entity) {
return reactiveRedisOperations.opsForValue()
.get("private")
.switchIfEmpty(
Mono.create(stringMonoSink -> {
try {
var privateKeyEncoded = ...
var publicKeyEncoded = ...
reactiveRedisOperations.opsForValue()
.multiSet(Map.of(
"private", privateKeyEncoded,
"public", publicKeyEncoded
))
.subscribe(success -> {
stringMonoSink.success(privateKeyEncoded);
});
} catch (Throwable e) {
stringMonoSink.error(e);
}
})
);
}
You can use Mono.defer(Supplier<? extends Mono<? extends T>> supplier)
. It takes a supplier for Mono, that will be called only if Mono subscribed. In your case it means key generation will be called only in case of switchIfEmpty
:
return reactiveRedisOperations.opsForValue()
.get("private")
.switchIfEmpty(Mono.defer(() -> {
var privateKeyEncoded = "...";
var publicKeyEncoded = "...";
return reactiveRedisOperations.opsForValue()
.multiSet(Map.of(
"private", privateKeyEncoded,
"public", publicKeyEncoded
))
.map(b -> {
if (b) return privateKeyEncoded;
else throw new RuntimeException();
});
})
);