我需要与Project Reactor异步生成唯一的代码。
方法签名如下:
public Mono<String> generateCode()
所以流程应该是这样的:
我当前的解决方案是像这样递归调用generateCode:
Mono<String> generateCode() {
String code = generateCodeValue();
return emailConfirmationRepository
.findByCode(code)
.flatMap(codeOpt -> codeOpt.map(c -> generateCode()).orElseGet(() -> Mono.just(code)));
}
但是我不喜欢这样,因为每个调用都会创建自己的堆栈,这可能导致StackOverflowError。
我知道应该有大量的调用,这很可能不会发生,但是仍然,我需要一个没有递归的解决方案,像一个普通的while循环,但是需要异步代码。
如何使用电抗器实现这一目标?
答案 0 :(得分:1)
但是请注意,该重试将重试您的所有步骤。因此,如果您有更复杂的代码,例如:
Mono<String> generateCode() {
return Mono.fromCallable(() -> generateCodeValue())
.flatMap(code -> doSomeExpensiveOperation1())
.flatMap(code -> doSomeDangerousOperation2())
.flatMap(code -> emailConfirmationRepository
.findByCode(code)
.flatMap(codeOpt -> codeOpt
.map(c -> Mono.<String>error(new CodeAlreadyExistsException()))
.orElseGet(() -> Mono.just(code))))
.retry(5);
}
class CodeAlreadyExistsException extends RuntimeException {}
然后将再次重复执行“ findByCode”之前的所有步骤,包括doSomeExpensiveOperation1和doSomeDangerousOperation2。
答案 1 :(得分:1)
要重试它,直到无限期满足某些条件,您应该:
Mono<String> generateCode() {
return Mono.fromCallable(() -> generateCodeValue())
.flatMap(code -> emailConfirmationRepository
.findByCode(code)
.flatMap(codeOpt -> codeOpt
.map(c -> Mono.<String>error(new CodeAlreadyExistsException()))
.orElseGet(() -> Mono.just(code))))
.retry(CodeAlreadyExistsException.class::isInstance)
}
class CodeAlreadyExistsException extends RuntimeException {}
感谢@ alexander-pankin。
答案 2 :(得分:0)
当给定代码存在时,您可以返回错误Mono
,并使用retry
运算符。
Mono<String> generateCode() {
return Mono.fromCallable(() -> generateCodeValue())
.flatMap(code -> emailConfirmationRepository
.findByCode(code)
.flatMap(codeOpt -> codeOpt
.map(c -> Mono.<String>error(new CodeAlreadyExistsException()))
.orElseGet(() -> Mono.just(code))))
.retry(5);
}
class CodeAlreadyExistsException extends RuntimeException {}