将命令式条件语句(异常抛出)映射到 Reactive 进程

Mapping imperative conditional statements (with exception throwing) to Reactive process

我正在努力理解 Reactive 流程。我的理解是,在 MonoFlux 中操作数据时,必须保持类型一致性。但是,当该过程中出现问题时,必须抛出类似异常的东西,这会破坏类型一致性。

目前,我有一个获取验证令牌 ID 并对其进行处理的必要流程。在两个实例中,它抛出异常(InvalidTokenException404 响应;ExpiredTokenException410),最后修改并保存帐户,并删除令牌。我想将其转换为反应过程:

public AccountDto verifyAccountByToken (UUID tokenId) {
    VerifyToken vToken = verifyTokenRepository.findByToken(tokenId);
    if (vToken == null) {
        throw new InvalidTokenException();
    }
    if (vToken.isExpired()) {
        verifyTokenRepository.delete(vToken);
        throw new ExpiredTokenException();
    }
    Account account = vToken.getAccount();
    account.addRole(AccountRole.VERIFIED);
    account.deleteRole(AccountRole.UNVERIFIED);
    accountRepository.save(account);
    verifyTokenRepository.delete(vToken);
    return new AccountDto(account);
}

我相信以下对于数据处理过程基本上是正确的,但我该如何处理条件分支? – 我怎么说:做这个如果空? (我想我可以使用 .filter() 作为捕获过期案例的方法。)以及如何将其转换为错误类型?

public Mono<AccountDto> verifyAccountByToken (UUID tokenId) {
    return verifyTokenRepository.findByToken(tokenId)
            
            // the bits I can't figure out to deal with Invalid and Expired tokens;
            
            .flatMap(vToken -> {
                verifyTokenRepository.delete(vToken);
                return vToken.getAccount();
            })
            .flatMap(account -> {
                account.addRole(AccountRole.VERIFIED);
                account.deleteRole(AccountRole.UNVERIFIED);
                return accountRepository.save(account);
            })
            .map(account -> new AccountDto(account));
}

How do I say: do-this-if-empty?

有一个运算符:

 .switchIfEmpty(Mono.error(new InvalidTokenException()));

看看下面的评论:

public Mono<AccountDto> verifyAccountByToken(UUID tokenId) {
  return verifyTokenRepository.findByToken(tokenId) //Mono<VerifyToken> or Mono<Void>
          .switchIfEmpty(Mono.error(new InvalidTokenException())); //token does not exist, empty Mono is returned, switch to an error signal
          .flatMap(this::validateToken)
          .map(vToken -> vToken.getAccount())
          .flatMap(account -> {
                //token is valid...
                account.addRole(AccountRole.VERIFIED);
                account.deleteRole(AccountRole.UNVERIFIED);
                return accountRepository.save(account);
            })
          .map(account -> new AccountDto(account));
}

private Mono<VerifyToken> validateToken(VerifyToken vToken) {
    if (vToken.isExpired()) {
        //Token is expired... delete it and then signal an error
         return verifyTokenRepository.delete(vToken) 
                  .then(Mono.error(new ExpiredTokenException()));
    }
    return Mono.just(vToken);//token is valid...
}