Skip to content
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

Performance improvements for disputes reminder task list #9906

Merged
merged 8 commits into from
Dec 17, 2024

Conversation

brucealdridge
Copy link
Contributor

@brucealdridge brucealdridge commented Dec 9, 2024

Fixes #9716

Changes proposed in this Pull Request

Performance improvements for the WC Admin Disputes Reminder Task.

Previously this feature could cause some errored accounts (and some non-erroring accounts) to make excessive calls to the Server's Disputes API. Due to the way that the API requests were cached, this only affected a small number of merchants.

We believe this occurred when the Account was Rejected or Suspended, the call to GET disputes would error preventing caching.

Improvements:

  • Task is only loaded when
    • logged-in user has manage_woocommerce permission
    • Account is not rejected or suspended
  • API requests are delayed until the WC task list is initialized.

Additional Context

pdjTHR-4rD-p2

Testing instructions

  1. Ensure your store has disputes expiring within 1 week.
  2. Visit WC Dashboard, and confirm the Task Item is visible

Additional Notes:

  • If your store does not have disputes expiring within one week, you can modify your server database and adjust the due date of disputes.
  • You may also need to clear the cache in your store - DELETE FROM wp_options WHERE option_name='wcpay_active_dispute_cache';
  • You can test an "errored" cache by altering the wcpay_active_dispute_cache option to end in "errored";b:1;} (ie. errored=true)
  • You can test an "expired" cache by altering the fetched value in wcpay_active_dispute_cache

  • 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

@botwoo
Copy link
Collaborator

botwoo commented Dec 9, 2024

Test the build

Option 1. Jetpack Beta

  • Install and activate Jetpack Beta.
  • Use this build by searching for PR number 9906 or branch name fix/9716-disputes-api-requests 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: c795c21
  • Build time: 2024-12-17 22:06:24 UTC

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

Copy link
Contributor

github-actions bot commented Dec 9, 2024

Size Change: 0 B

Total Size: 1.39 MB

ℹ️ View Unchanged
Filename Size
release/woocommerce-payments/assets/css/admin.css 1.37 kB
release/woocommerce-payments/assets/css/admin.rtl.css 1.37 kB
release/woocommerce-payments/assets/css/success.css 182 B
release/woocommerce-payments/assets/css/success.rtl.css 184 B
release/woocommerce-payments/dist/blocks-checkout-rtl.css 2.63 kB
release/woocommerce-payments/dist/blocks-checkout.css 2.63 kB
release/woocommerce-payments/dist/blocks-checkout.js 55.3 kB
release/woocommerce-payments/dist/cart-block.js 17 kB
release/woocommerce-payments/dist/cart.js 5.73 kB
release/woocommerce-payments/dist/checkout-rtl.css 932 B
release/woocommerce-payments/dist/checkout.css 931 B
release/woocommerce-payments/dist/checkout.js 33.4 kB
release/woocommerce-payments/dist/express-checkout-rtl.css 229 B
release/woocommerce-payments/dist/express-checkout.css 229 B
release/woocommerce-payments/dist/express-checkout.js 15.5 kB
release/woocommerce-payments/dist/frontend-tracks.js 854 B
release/woocommerce-payments/dist/index-rtl.css 52.6 kB
release/woocommerce-payments/dist/index.css 52.6 kB
release/woocommerce-payments/dist/index.js 302 kB
release/woocommerce-payments/dist/multi-currency-analytics.js 1.08 kB
release/woocommerce-payments/dist/multi-currency-rtl.css 4.46 kB
release/woocommerce-payments/dist/multi-currency-switcher-block.js 60.6 kB
release/woocommerce-payments/dist/multi-currency.css 4.46 kB
release/woocommerce-payments/dist/multi-currency.js 57.3 kB
release/woocommerce-payments/dist/order-rtl.css 730 B
release/woocommerce-payments/dist/order.css 730 B
release/woocommerce-payments/dist/order.js 42 kB
release/woocommerce-payments/dist/payment-gateways-rtl.css 1.32 kB
release/woocommerce-payments/dist/payment-gateways.css 1.32 kB
release/woocommerce-payments/dist/payment-gateways.js 38.4 kB
release/woocommerce-payments/dist/plugins-page-rtl.css 386 B
release/woocommerce-payments/dist/plugins-page.css 386 B
release/woocommerce-payments/dist/plugins-page.js 20.1 kB
release/woocommerce-payments/dist/product-details-rtl.css 433 B
release/woocommerce-payments/dist/product-details.css 436 B
release/woocommerce-payments/dist/product-details.js 12.3 kB
release/woocommerce-payments/dist/settings-rtl.css 11.6 kB
release/woocommerce-payments/dist/settings.css 11.5 kB
release/woocommerce-payments/dist/settings.js 224 kB
release/woocommerce-payments/dist/subscription-edit-page.js 703 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal-rtl.css 524 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.css 524 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.js 20.2 kB
release/woocommerce-payments/dist/subscription-product-onboarding-toast.js 730 B
release/woocommerce-payments/dist/subscriptions-empty-state-rtl.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.js 19.3 kB
release/woocommerce-payments/dist/tokenized-express-checkout-rtl.css 229 B
release/woocommerce-payments/dist/tokenized-express-checkout.css 229 B
release/woocommerce-payments/dist/tokenized-express-checkout.js 16.3 kB
release/woocommerce-payments/dist/tos-rtl.css 235 B
release/woocommerce-payments/dist/tos.css 235 B
release/woocommerce-payments/dist/tos.js 21.8 kB
release/woocommerce-payments/dist/woopay-direct-checkout.js 6.13 kB
release/woocommerce-payments/dist/woopay-express-button.js 24.8 kB
release/woocommerce-payments/dist/woopay-rtl.css 4.31 kB
release/woocommerce-payments/dist/woopay.css 4.28 kB
release/woocommerce-payments/dist/woopay.js 71 kB
release/woocommerce-payments/includes/subscriptions/assets/css/plugin-page.css 625 B
release/woocommerce-payments/includes/subscriptions/assets/js/plugin-page.js 814 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/i18n-loader.js 2.46 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/jetpack-script-data.js 767 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/i18n-loader.js 1.02 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/script-data.js 69 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/babel.config.js 163 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.css 2.47 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.js 14.2 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.rtl.css 2.47 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.css 10 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.js 28.4 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.rtl.css 10 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.js 280 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.rtl.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.css 625 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.js 333 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.rtl.css 626 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-users.js 424 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-ajax.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-callables.js 585 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.css 215 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.css 721 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.js 412 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-users.js 632 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/about.css 1.04 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-empty-state.css 294 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-order-statuses.css 408 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin.css 3.59 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/checkout.css 301 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/modal.css 746 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/view-subscription.css 574 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/wcs-upgrade.css 414 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin-pointers.js 543 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.78 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.min.js 3.84 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-coupon.js 545 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-subscription.js 2.52 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.js 22.2 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.min.js 11.7 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 507 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/payment-methods.js 358 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/single-product.js 428 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 782 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/modal.js 1.09 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/wcs-upgrade.js 1.26 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.css 391 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.js 3.04 kB

compressed-size-action

Copy link
Contributor

@marcinbot marcinbot left a comment

Choose a reason for hiding this comment

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

Left some suggestions, in line with the P2, while also keeping in mind that this work might end up not to be needed depending on product decision.

Also, we could remove the side effect from the WC_Payments_Task_Disputes constructor and have the render calls try to fetch on demand, now that we have in-memory caching.

$account_service = WC_Payments::get_account_service();
if ( ! $account_service || ! $account_service->is_stripe_account_valid() ) {
if ( ! $account_service || ! $account_service->is_stripe_account_valid() || $account_service->is_account_under_review() || $account_service->is_account_rejected() ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

is_account_under_review() and is_account_rejected also check is_stripe_connected

Copy link
Contributor

Choose a reason for hiding this comment

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

This could also be explained in a comment - i.e. define the preconditions in merchant/human terms :)

@brucealdridge brucealdridge marked this pull request as ready for review December 12, 2024 23:41
@brucealdridge brucealdridge requested a review from a team December 12, 2024 23:41
Copy link
Contributor

@marcinbot marcinbot left a comment

Choose a reason for hiding this comment

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

Looks good. A few questions below, of which only the one about try/catch is a blocker.

includes/class-wc-payments-tasks.php Outdated Show resolved Hide resolved
includes/admin/tasks/class-wc-payments-task-disputes.php Outdated Show resolved Hide resolved
includes/admin/tasks/class-wc-payments-task-disputes.php Outdated Show resolved Hide resolved
Copy link
Contributor

@haszari haszari left a comment

Choose a reason for hiding this comment

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

Did a quick review of the code, I haven't tested (feel free to ping me again – I'm happy to test as well if needed).

This is looking good, and has had pretty thorough review from @marcinbot also 🙌

My feedback is all minor, around naming and leaving breadcrumbs about how and why we optimised this. I'm worried that in future someone might refactor things and unintentionally impact performance!

The internal discussion pdjTHR-4rD-p2 should be considered alongside these changes.

@brucealdridge Can you add (or summarise/rewrite) the relevant details from that P2, so the PR is self contained?

Due to the way that the API requests were cached, this only affected a small number of merchants.

What conditions triggered the bug? That's essential info for the PR :)

When I read the final code (or the PR description) I don't see any clues about which specific code is slow (potentially under special-case conditions), and our new design to trigger that code much later. So my general feedback is to …

  • Rename any "slow" methods so it's clear that they are expensive. Some are already named fetch_ which is a good clue, but this clue would be useful further up too. For example WC_Payments_Task_Disputes::init() => WC_Payments_Task_Disputes::fetch_relevant_disputes(), I agree with Marcin feedback.
  • Add comments to slow/expensive methods that document the edge cases/bad performance cases we've seen. E.g. don't try to fetch disputes for rejected (etc) accounts.

Generally make it easy for readers of this code (or the PR) to understand the hard-won performance improvements you've implemented 🙌

@@ -1336,6 +1336,7 @@ public function add_transactions_notification_badge() {

/**
* Gets the number of disputes which need a response. ie have a 'needs_response' or 'warning_needs_response' status.
* Used to display a notification badge on the Payments > Disputes menu item.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice to add this breadcrumb. Maybe even could add a "see also" linking to the code that calls this? (if you think that would be helpful)

*
* @var array|null
*/
private $disputes_needing_response = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be good to clarify this a little more:

  • What is the type of the array? i.e. clarify that this is an array of dispute objects, not a count, or array of ids.
  • What's the lifetime of this, when is it relevant (and when might it be "stale")? Since it is a
    "snapshot", i.e. using a class member as a cache/temporary storage. I imagine this is per-request as is common in Woo/PHP web code, but it's good to be explicit.

includes/admin/tasks/class-wc-payments-task-disputes.php Outdated Show resolved Hide resolved
@@ -275,6 +284,10 @@ public function is_complete() {
* @return bool
*/
public function can_view() {
if ( null === $this->disputes_needing_response ) {
// init() is called on can_view as this is the first method called in the task lifecycle by WC.
Copy link
Contributor

Choose a reason for hiding this comment

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

If we rename init based on what it does – i.e. fetch stuff so we have the data we need – then this comment can be clearer.

@haszari
Copy link
Contributor

haszari commented Dec 16, 2024

Testing instructions
Ensure your store has disputes expiring within 1 week.
Visit WC Dashboard, and confirm the Task Item is visible

These test instructions are happy-path only, but this fix is for various edge cases. Should we be testing the bad performance edge case too? Please add reproduce steps for at least one of the bad-performance cases.

You can test an "errored" cache by altering the wcpay_active_dispute_cache option to end in "errored";b:1;} (ie. errored=true)
You can test an "expired" cache by altering the fetched value in wcpay_active_dispute_cache

Are these the scenarios that were causing the bug – would it be useful to test with e.g. a rejected WooPayments account (etc)? (Assuming we can fake this with local server)

@marcinbot
Copy link
Contributor

I approved this, but it looks like we'll need to fix the tests too. Once that's done, feel free to :shipit:

return;
}
include_once WCPAY_ABSPATH . 'includes/admin/tasks/class-wc-payments-task-disputes.php';
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for clarifying the details of the problem and how you've optimised it @brucealdridge ! 🚀

I think it's worth adding a comment in this function about why the include and task is deferred, i.e. leave breadcrumbs in the code about the performance problem.

@brucealdridge brucealdridge added this pull request to the merge queue Dec 17, 2024
Merged via the queue into develop with commit cf6d2c1 Dec 17, 2024
25 checks passed
@brucealdridge brucealdridge deleted the fix/9716-disputes-api-requests branch December 17, 2024 22:17
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.

High number of Dispute API requests when server returns error
4 participants