1

我有一种方法,在传统的命令式try-catch编码风格中是这样的:

void confirmCart(Checkout Order) {
    try {
        cartService.confirm(order.getCartId(), order.getCartHash());
    } catch (Exception ex1) {
        log.error("Confirm error: ", ex1);
        try {
            paymentService.cancel(order.getPaymentTransaction().getGatewayReference());
            throw ServiceException.wrap(ex1, CheckoutErrorCode.FAILED_CONFIRMING_CART);
        } catch (Exception ex2) {
            throw ServiceException.wrap(ex2, CheckoutErrorCode.FAILED_CANCELLING_PAYMENT);
        }
    }
}

要求是:

  • 工作时cartService.confirm(),不返回任何内容
  • 失败时进入catch部分,尝试paymentService.cancel()
  • 如果 2 失败,则抛出ex2
  • 如果 2 成功,则抛出ex1(因为confirm()无论如何都失败了)
  • 根据这里抛出的异常,控制器会做不同的事情

现在,在 Reactive 风格中,它就像:

    Mono<Void> confirmCart(CheckoutOrder order) {
        return cartService.confirm(order.getCartId(), order.getCartHash())
                .onErrorMap(throwable -> {
                    log.error("Failed confirming cart! cartId: '{}', cartHash: '{}'", order.getCartId(), order.getCartHash(), throwable);
                    return ServiceException.wrap(throwable, CheckoutErrorCode.FAILED_CONFIRMING_CART);
                })
                .onErrorResume(throwable -> {
                    log.trace("Cancelling payment with order id {}", order.getId().toString());
                    // when confirmation fails, 1. cancel payment and 2. throw original exception to notify controller -> exception handler
                    return paymentService.cancel(order.getPaymentTransaction().getGatewayReference())
                            .map(paymentCancellationResponse -> {
                                log.trace("payment cancellation response: {}, order id: {}", paymentCancellationResponse, order.getId().toString());
                                return paymentCancellationResponse;
                            }).then()
                            .onErrorMap(e -> {
                                log.error("payment payment cancellation failed. ", e);
                                return ServiceException.wrap(e, CheckoutErrorCode.FAILED_CANCELLING_PAYMENT);
                            });
                });
    }

但是,我花了很多时间与 Reactive 运算符一起玩,但找不到任何方法来重新抛出原始异常。上面的代码可以编译,但是失败时不会抛出第一个异常confirmCart()我猜是因为onErrorMap()onErrorResume()不能共存;后一个会很荣幸,也许吧?

我已经尝试过,onErrorMap因为此外,它应该是同步的:如果失败则confirmCart()应该等待。paymentService.cancel()

我在玩then()thenReturn()等等,但我可以让它编译,但它不会返回/重新抛出第一个确认异常。

return cartService.confirm(order.getCartId(), order.getCartHash())
        .onErrorResume(throwable -> {
            log.error("Failed confirming cart! cartId: '{}', cartHash: '{}'", order.getCartId(), order.getCartHash(), throwable);
            log.trace("Cancelling payment with order id {}", order.getId().toString());
            // when confirmation fails, 1. cancel payment and 2. redirect user to checkout page
            return paymentService.cancel(order.getPaymentTransaction().getGatewayReference())
                    .map(paymentCancellationResponse -> {
                        log.trace("payment cancellation response: {}, order id: {}", paymentCancellationResponse, order.getId().toString());
                        return paymentCancellationResponse;
                    }).thenReturn(
                        ServiceException.wrap(throwable, CheckoutErrorCode.FAILED_CONFIRMING_CART)
                    )
                    .onErrorMap(e -> {
                        log.error("payment payment cancellation failed. ", e);
                        return ServiceException.wrap(e, CheckoutErrorCode.FAILED_CANCELLING_PAYMENT);
                    }).then();
        });

在测试中,失败时我没有抛出异常cartService.confirm()

4

0 回答 0