Skip to content

Clear post cache after updating menu order for products. #34195

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

Merged
merged 1 commit into from
Aug 15, 2022

Conversation

barryhughes
Copy link
Member

When Advanced Post Caching is in effect, changes made to product menu order appear not to take effect because the cached results (for the posts query) are not invalidated.

Closes #31389.

How to test the changes in this Pull Request:

Please also refer to the linked issue which contains a good screencast and some solid testing instructions.

  1. Start by setting up an environment where you can replicate the problem described in the linked issue:
    • You can achieve this by testing on an Atomic site.
    • Or, to test locally, grab a copy of Advanced Post Cache as used on WP.com (internal conversation p1659562709451669/1659534670.204749-slack-C0E1AV8T0 contains a link where you can grab a copy) and set it up as a mu-plugin. You will also need persistent object caching (Redis/Memcached) to be in place.
  2. Navigate to Products ▸ Categories and pick a category associated with 1 or more products. Click on the link in the Count column.
  3. You should now find yourself looking at a list table of products belonging to that category. Open the Sorting view.
  4. Try reordering the products, then refresh the page. The change should persist.

Demo

Here's how things work without the fix (note how after reordering the products I click on Sorting to refresh the page, and the order reverts to how it was at the start of the video):

withoutfix.mov

And here is how things work with the fix. This time, on refreshing, the new order persists:

withfix.mov

FOR PR REVIEWER ONLY:

  • I have reviewed that everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities. I made sure Linting is not ignored or disabled.

@barryhughes barryhughes requested review from a team and jorgeatorres and removed request for a team August 4, 2022 21:56
@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Aug 4, 2022
@barryhughes
Copy link
Member Author

Some notes on performance... ✍🏽

Switching from $wpdb->update() to wp_update_post() also solves this, because that takes care of invalidating various caches, etc, but with a large catalog the performance impact is notable (and I assume that is why we chose to use direct queries in the first place). For that reason, I kept the $wpdb->update() approach.

Similarly, to keep things snappy, I opted only to call clean_post_cache() if the post row was actually changed (again, especially with a large catalog, the majority of rows will not be updated so calling it for each product seemed wasteful).

@github-actions
Copy link
Contributor

github-actions bot commented Aug 4, 2022

Test Results Summary

Commit SHA: c5001f2

Test 🧪Passed ✅Failed 🚨Broken 🚧Skipped ⏭️Unknown ❔Total 📊Duration ⏱️
API Tests11500201170m 43s
E2E Tests185001018617m 25s
To view the full API test report, click here.
To view the full E2E test report, click here.
To view all test reports, visit the WooCommerce Test Reports Dashboard.

@bazza
Copy link

bazza commented Aug 4, 2022

Using direct SQL and bypassing core APIs is always going to cause problems. You mentioned it's done for performance reasons, but did you compare the performance of the two after adding clean_post_cache() ? You also mentioned there is a "noticeable" difference, but do you have any specific data to share? Maybe Core WordPress needs to provide a better (i.e. more performant) API to update multiple posts in bulk? If so, that would be a good thing to propose to the Core team.

@barryhughes
Copy link
Member Author

barryhughes commented Aug 6, 2022

Thanks for the question, @bazza.

Switching from $wpdb->update() to wp_update_post() also solves this

I should start by acknowledging that, by itself, this is a very naive approach (because, if we literally just replace the existing $wpdb->update() calls with wp_update_post() calls then, with for example a catalog of 500 products, it ensures there will be updates to 500 rows whether or not the menu_order actually changes—because post_modified etc will still be bumped).

So, a better strategy would be to check if the menu order even needs to be modified before updating (ie, perform a check along the lines of get_post_field( 'menu_order', $id ) !== $new_menu_order, which is the approach I'll use from here).

Do you have any specific data to share?

Just from local testing (with a catalog of 500 products, and where re-ordering triggers an update to 4 rows, and where I perform 5 runs per test-case to get an average):

Strategy Caching Time spent (ms)
wp_update_post() Obj Cache + APC 1199
wp_update_post() None 980
$wpdb->update() Obj Cache + APC 101
$wpdb->update() None 116

Did you compare the performance of the two after adding clean_post_cache() ?

Yes, it was a wash. $wpdb->update() by itself averages out at virtually the same as when we follow-up with a call to clean_post_cache() (so long as we only do it when rows were modified). Hence, I included just one set of results in the table above.


From there:

  • We could be more thorough in our benchmarking, 5 runs on a catalog of the same size within my local dev env isn't conclusive. Though, I think it's a good enough indicator.
  • The current algorithm examines every product in the catalog; perhaps it could be optimized—but I don't know if that's worth focusing on right now, if we have a ready-to-go fix that works. Though we could follow-up later if required.

Copy link
Member

@jorgeatorres jorgeatorres left a comment

Choose a reason for hiding this comment

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

This looks good to me.

While I agree that ideally we would have access to some WP functions to performantly update the menu order in bulk, the approach here not only fixes the issue but does so with minimal impact, as opposed to changing the code to use wp_update_post().

Maybe we can add an issue to review some of these places where we've deviated from the "official" way of doing something for performance (or other) reasons and either re-work the code then or propose new APIs to upstream.

Note: I don't currently see any good reason not to merge this as-is, but will hold off on doing so for a few days, just in case we want to discuss further.

@jorgeatorres jorgeatorres self-assigned this Aug 9, 2022
@barryhughes
Copy link
Member Author

@bazza let me know if any other questions/concerns on this one.

@beaulebens
Copy link
Contributor

Maybe we can add an issue to review some of these places where we've deviated from the "official" way of doing something for performance (or other) reasons and either re-work the code then or propose new APIs to upstream.

Agreed -- can we please create an issue to review anywhere we're doing this sort of query, so that we can propose improvements to WordPress Core that would enable us to use official APIs vs direct queries?

@barryhughes barryhughes merged commit 7021d44 into trunk Aug 15, 2022
@barryhughes barryhughes deleted the fix/31389-menu-ordering branch August 15, 2022 14:28
@github-actions github-actions bot added this to the 6.9.0 milestone Aug 15, 2022
@github-actions
Copy link
Contributor

Hi @barryhughes, thanks for merging this pull request. Please take a look at these follow-up tasks you may need to perform:

  • Add the release: add testing instructions label

rcstr added a commit that referenced this pull request Aug 16, 2022
* trunk: (97 commits)
  [COT] Respect status flags `show_in_admin_(all|status)_list` in orders list table (#34290)
  Fix a bug crashing wp-env 5.1.0 in CI (#34274)
  Add unit tests for orders milestone note (#34295)
  Update "context" prop of task list click/view event (#34297)
  Update the cherry-pick workflow to not run for non-existent branches (#34325)
  Update CI to use wp-env for api, e2e and performance tests (#34311)
  Clear post cache after updating menu order for products. (#34195)
  Add `wc com disconnect` command (#33999)
  Fix review shipping option task title (#34294)
  Add Facebook Extension to Onboarding (#34303)
  Add Media Uploader component (#34181)
  Add SortableList component (#34237)
  Change to use fetch depth 0 (#34288)
  Add SplitDropdown component (#34180)
  Fix/forgotten template version (#34308)
  Fix/34271 unlimited results (#34289)
  Add product name and checkboxes for Product details (#34214)
  Prepare Packages for Release (#34299)
  dev: move guided tours into consolidated folder (#34279)
  Add flag to state it is in dev mode so tools are installed like phpun… (#34258)
  ...

 Conflicts:
	plugins/woocommerce/includes/admin/helper/class-wc-helper.php
	plugins/woocommerce/includes/cli/class-wc-cli-com-command.php
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: woocommerce Issues related to the WooCommerce Core plugin.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

WooCommerce Category Product sorting not working only on Atomic sites
4 participants