Skip to content

RPP: Added error states #7739

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open

Conversation

zmaglica
Copy link
Contributor

@zmaglica zmaglica commented Nov 19, 2023

Fixes #7425

Changes proposed in this Pull Request

This PR introduces error states and their management. It ensures that all exceptions, including minor ones, are effectively handled. The core principle is to avoid returning exceptions from states. Instead, states should consistently return their designated state. This approach eliminates the need for exception handling in services utilizing these states or in the gateway, where they were previously handled.

Error states:

  • AbstractPaymentErrorState : Abstract error class that holds common or reusable logic for all error states
  • PaymentErrorState: Error state that is used when an error occurs on the buyer's side, which cannot be fixed through code.
  • PaymentRequestErrorState: Handles PaymentRequestException that can occur when context is populated from the request.
  • SystemErrorState: Equivalent of \Exception we have in PHP but used for our state machine. Look at this state as a default error state when an exception or any unwanted flow occurs, where we don't have a specific error state to transition.
  • WooPaymentsApiServerErrorState: Error state that is used when server API throws an exception. I used WooPayments prefix to make it more clearer that this is the error state for API server errors on WooCommerce Payments server.

Testing instructions

  • Make sure that all exceptions are handled by the error states. In other words, if an exception is triggered in state, the state needs to handle it and return error state. The only exception that can be handled without the error state is StateTransitionException which can occur outside state processing or within the catch block, where we transition from state to new error state.
  • All error states should extend the base or abstract error class.
  • Make sure that all error states have their logging and mark order as failed function configured property, and according to the business logic. What that means is that each error state can have disabled logging or disabled marking order as failed.

  • Run npm run changelog to add a changelog file, choose patch to leave it empty if the change is not significant. You can add multiple changelog files in one PR by running this command a few times.
  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Post merge

@zmaglica zmaglica requested a review from a team November 19, 2023 23:09
@botwoo
Copy link
Collaborator

botwoo commented Nov 19, 2023

Test the build

Option 1. Jetpack Beta

  • Install and activate Jetpack Beta.
  • Use this build by searching for PR number 7739 or branch name rpp-7425-handle-error-states in your-test.site/wp-admin/admin.php?page=jetpack-beta&plugin=woocommerce-payments

Option 2. Jurassic Ninja - available for logged-in A12s

🚀 Launch a JN site with this branch 🚀

ℹ️ Install this Tampermonkey script to get more options.


Build info:

  • Latest commit: 6468323
  • Build time: 2023-11-21 13:23:57 UTC

Note: the build is updated when a new commit is pushed to this PR.

Copy link
Contributor

github-actions bot commented Nov 19, 2023

Size Change: 0 B

Total Size: 1.44 MB

ℹ️ View Unchanged
Filename Size
release/woocommerce-payments/assets/css/admin.css 1.06 kB
release/woocommerce-payments/assets/css/success.css 158 B
release/woocommerce-payments/dist/blocks-checkout-rtl.css 1.8 kB
release/woocommerce-payments/dist/blocks-checkout.css 1.8 kB
release/woocommerce-payments/dist/blocks-checkout.js 75.3 kB
release/woocommerce-payments/dist/checkout-rtl.css 441 B
release/woocommerce-payments/dist/checkout.css 442 B
release/woocommerce-payments/dist/checkout.js 28.9 kB
release/woocommerce-payments/dist/index-rtl.css 36.8 kB
release/woocommerce-payments/dist/index.css 36.8 kB
release/woocommerce-payments/dist/index.js 285 kB
release/woocommerce-payments/dist/multi-currency-analytics.js 1.05 kB
release/woocommerce-payments/dist/multi-currency-rtl.css 3.4 kB
release/woocommerce-payments/dist/multi-currency-switcher-block.js 60.2 kB
release/woocommerce-payments/dist/multi-currency.css 3.4 kB
release/woocommerce-payments/dist/multi-currency.js 55.4 kB
release/woocommerce-payments/dist/order-rtl.css 676 B
release/woocommerce-payments/dist/order.css 679 B
release/woocommerce-payments/dist/order.js 41.4 kB
release/woocommerce-payments/dist/payment-gateways-rtl.css 1.31 kB
release/woocommerce-payments/dist/payment-gateways.css 1.31 kB
release/woocommerce-payments/dist/payment-gateways.js 39 kB
release/woocommerce-payments/dist/payment-request-rtl.css 153 B
release/woocommerce-payments/dist/payment-request.css 153 B
release/woocommerce-payments/dist/payment-request.js 13.1 kB
release/woocommerce-payments/dist/product-details.js 898 B
release/woocommerce-payments/dist/settings-rtl.css 10.3 kB
release/woocommerce-payments/dist/settings.css 10.3 kB
release/woocommerce-payments/dist/settings.js 233 kB
release/woocommerce-payments/dist/subscription-edit-page.js 669 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal-rtl.css 519 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.css 519 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.js 20.4 kB
release/woocommerce-payments/dist/subscription-product-onboarding-toast.js 693 B
release/woocommerce-payments/dist/subscriptions-empty-state-rtl.css 117 B
release/woocommerce-payments/dist/subscriptions-empty-state.css 117 B
release/woocommerce-payments/dist/subscriptions-empty-state.js 19.5 kB
release/woocommerce-payments/dist/tos-rtl.css 230 B
release/woocommerce-payments/dist/tos.css 231 B
release/woocommerce-payments/dist/tos.js 21.9 kB
release/woocommerce-payments/dist/upe_checkout-rtl.css 441 B
release/woocommerce-payments/dist/upe_checkout.css 442 B
release/woocommerce-payments/dist/upe_checkout.js 34.1 kB
release/woocommerce-payments/dist/upe_split_checkout-rtl.css 441 B
release/woocommerce-payments/dist/upe_split_checkout.css 442 B
release/woocommerce-payments/dist/upe_split_checkout.js 34.7 kB
release/woocommerce-payments/dist/upe_with_deferred_intent_creation_checkout.js 37.1 kB
release/woocommerce-payments/dist/upe-blocks-checkout-rtl.css 1.8 kB
release/woocommerce-payments/dist/upe-blocks-checkout.css 1.8 kB
release/woocommerce-payments/dist/upe-blocks-checkout.js 41 kB
release/woocommerce-payments/dist/upe-split-blocks-checkout-rtl.css 1.8 kB
release/woocommerce-payments/dist/upe-split-blocks-checkout.css 1.8 kB
release/woocommerce-payments/dist/upe-split-blocks-checkout.js 42.6 kB
release/woocommerce-payments/dist/woopay-express-button-rtl.css 153 B
release/woocommerce-payments/dist/woopay-express-button.css 153 B
release/woocommerce-payments/dist/woopay-express-button.js 52.1 kB
release/woocommerce-payments/dist/woopay-rtl.css 4.18 kB
release/woocommerce-payments/dist/woopay.css 4.19 kB
release/woocommerce-payments/dist/woopay.js 71.7 kB
release/woocommerce-payments/includes/subscriptions/assets/css/plugin-page.css 622 B
release/woocommerce-payments/includes/subscriptions/assets/js/plugin-page.js 812 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/i18n-loader.js 2.43 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/i18n-loader.js 1.01 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-ajax.js 522 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-callables.js 581 B
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/babel.config.js 160 B
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.css 2.32 kB
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.js 13.8 kB
release/woocommerce-payments/vendor/automattic/jetpack-identity-crisis/build/index.rtl.css 2.32 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/about.css 1.03 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-empty-state.css 291 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-order-statuses.css 403 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin.css 3.6 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/checkout.css 299 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/modal.css 742 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/view-subscription.css 572 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/wcs-upgrade.css 411 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin-pointers.js 544 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin.js 9.4 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.js 6.8 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.min.js 3.83 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-coupon.js 544 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-subscription.js 2.38 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.js 22.1 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.min.js 11.6 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/payment-method-restrictions.js 1.29 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/wcs-meta-boxes-order.js 502 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/payment-methods.js 355 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/single-product.js 429 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/view-subscription.js 1.38 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/wcs-cart.js 781 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/modal.js 1.1 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/wcs-upgrade.js 1.27 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.css 392 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.js 3.05 kB

compressed-size-action

*
* @return bool True if the error should be logged, otherwise false.
*/
protected function should_log_error(): bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't all errors be logged by default?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they need to, but I wasn't 100% certain, so I made it to false. We can easily set that all error states needs to be logged, by the default.

Copy link
Contributor

@jessy-p jessy-p left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under testing instructions, it would be nice to have a listing of the errors and maybe a one liner of the scenarios to test.

@zmaglica
Copy link
Contributor Author

Under testing instructions, it would be nice to have a listing of the errors and maybe a one liner of the scenarios to test.

I have updated the test instructions and added a small description to each error state.

@zmaglica zmaglica requested a review from a team November 21, 2023 12:13
Copy link
Contributor

@RadoslavGeorgiev RadoslavGeorgiev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not reviewed all the details regarding the PR, but I think we need a significant change in direction. Keep this line from the issue in mind:

The new payment process should handle exceptions at a more granular level, and switch to a failure state immediately.

The current implementation in the PR goes against granularity, as we're back to the same state as the current payment process, where all exceptions are caught in the same place.

A few notes:

  • StateTransitionExceptions were a placeholder for exceptions in specific scenarios. We didn't want to create too many separate exception classes, in case they needed to be replaced by this stream. However, all but the create_state()'s StateTransitionExceptions should be replaced by something else.
  • Please merge develop into the PR, there are some more exceptions after Dat merged some PRs.

Presently we're not storing the context anywhere, but keep this question in mind: If we were to store payments, how would we approach erroneous states when we need to retry those payments?

Comment on lines +40 to +45
/**
* Stores exception that is triggered before error state is created.
*
* @var \Exception
*/
private $exception;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like request classes, there is no need to define a property of the object: It's all stored within data. With that in mind, this one is not used, and can be removed.

*
* @param \Exception $exception Exception to store.
*/
public function set_exception( $exception ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not insisting on this, but I'd prefer to call those set_last_exception and get_last_exception, similarly to how there's a $wpdb->last_error.

Also, please add a proper type hint to the method:

Suggested change
public function set_exception( $exception ) {
public function set_exception( Exception $exception ) {

Similar,y get_(last_)exception() should return : ?Exception

Comment on lines +133 to +138
/**
* Payments are based on intents, and intents use customer objects for billing details.
*
* The customer is created/updated right before requesting the creation of
* a payment intent, and the two actions must be adjacent to each-other.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This docblock is completely out of place now.

return $next_state->complete_processing();
} catch ( Amount_Too_Small_Exception $e ) {
$this->minimum_amount_service->store_amount_from_exception( $e );
return $this->create_error_state( SystemErrorState::class, $e );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The amount being too small is not a system exception, it happens whenever the amount to pay is less than the required minimum. This is not an indication that there's something wrong with the system, just a payment error.


return $next_state->complete_processing();
return $next_state->complete_processing();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By positioning this line within the catch block of this state, we're essentially trying to handle all exceptions from the ProcessedState here as well. This goes against the idea of granularly handling exceptions.

Comment on lines +74 to +81
/**
* Determines whether an error should be logged.
*
* @return bool True if the error should be logged, otherwise false.
*/
protected function should_log_error(): bool {
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logging of the whole context is already built, and specific errors (ex. API errors) are logged already. I'd remove the logging functionality from erroneous states altogether.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RPP / Failures / Catch exceptions and generate erroneous states
4 participants