Commit 1720f5739ee for woocommerce
commit 1720f5739eedc6f60528abe605347abdf7000b21
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date: Wed Jul 29 10:11:56 2026 +0200
[Performance] Temporary deactivate product status counters (#67058)
Temporarily switch back from the persistent product counters API to the WordPress API (once we investigate where integer-status is coming from, introduce normalization/hardening, and re-enable).
diff --git a/plugins/woocommerce/changelog/fix-counters-relax-product-status-type-requirements b/plugins/woocommerce/changelog/fix-counters-relax-product-status-type-requirements
new file mode 100644
index 00000000000..900094bb051
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-counters-relax-product-status-type-requirements
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Temporary deactivate persistent product status counters and rollback to WordPress API usage.
diff --git a/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php b/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
index 35eb8117ba7..53a296e5d40 100644
--- a/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
+++ b/plugins/woocommerce/includes/admin/list-tables/class-wc-admin-list-table-products.php
@@ -60,7 +60,7 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), 10, 2 );
// Use hooks to prime various caches and improve products page performance.
- add_action( 'load-edit.php', array( $this, 'prime_status_counts_cache' ) );
+ // Until persistent counters reactivated, disable callback for load-edit.php action.
add_filter( 'the_posts', array( $this, 'prime_thumbnail_caches' ), 10, 2 );
$cogs_controller = wc_get_container()->get( CostOfGoodsSoldController::class );
diff --git a/plugins/woocommerce/src/Caches/ProductCountCacheService.php b/plugins/woocommerce/src/Caches/ProductCountCacheService.php
index 2b673dbd21b..a1df2cc3dc4 100644
--- a/plugins/woocommerce/src/Caches/ProductCountCacheService.php
+++ b/plugins/woocommerce/src/Caches/ProductCountCacheService.php
@@ -55,17 +55,13 @@ class ProductCountCacheService {
final public function init(): void {
$this->product_count_cache = new ProductCountCache();
- add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'schedule_background_actions' ) );
+ add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'unschedule_background_actions' ) );
add_action( self::BACKGROUND_EVENT_HOOK, array( $this, 'prime_cache_if_cold' ) );
if ( defined( 'WC_PLUGIN_BASENAME' ) ) {
add_action( 'deactivate_' . WC_PLUGIN_BASENAME, array( $this, 'unschedule_background_actions' ) );
}
- // transition_post_status owns all mid-lifecycle status changes; woocommerce_new_product corrects for creation-time
- // ephemeral transitions before the final status is committed; before_delete_post closes the lifecycle.
- add_action( 'woocommerce_new_product', array( $this, 'update_on_new_product' ), 10, 2 );
- add_action( 'transition_post_status', array( $this, 'update_on_product_status_changed' ), 10, 3 );
- add_action( 'before_delete_post', array( $this, 'update_on_product_deleted' ), 10, 2 );
+ // Until persistent counters reactivated, disable callbacks for woocommerce_new_product, transition_post_status, before_delete_post hooks.
}
/**
@@ -75,11 +71,7 @@ class ProductCountCacheService {
* @return void
*/
public function prime_cache_if_cold( string $product_type = 'product' ): void {
- // Cache warm-up is only effective when an object cache plugin is active, and the cache entry is missing.
- if ( wp_using_ext_object_cache() && null === $this->product_count_cache->get( $product_type ) ) {
- $this->product_count_cache->flush( $product_type );
- wc_get_container()->get( ProductUtil::class )->get_counts_for_type( $product_type );
- }
+ // Until persistent counters reactivated, this task is no-op.
}
/**
diff --git a/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php b/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php
index 8b4c4455798..1d9acc2a517 100644
--- a/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php
+++ b/plugins/woocommerce/src/Internal/Utilities/ProductUtil.php
@@ -144,7 +144,7 @@ class ProductUtil {
}
/**
- * Counts per-status number of products of a given post type.
+ * Counts per-status number of products.
*
* @since 11.0.0
*
@@ -152,18 +152,7 @@ class ProductUtil {
* @return array<string,int>
*/
public function get_counts_for_type( string $post_type ): array {
- $product_count_cache = wc_get_container()->get( ProductCountCache::class );
- $count_per_status = $product_count_cache->get( $post_type );
-
- if ( null === $count_per_status ) {
- $count_per_status = array_merge(
- array_fill_keys( array_keys( get_post_stati() ), 0 ),
- (array) wp_count_posts( $post_type )
- );
-
- $product_count_cache->set_multiple( $post_type, $count_per_status );
- }
-
- return array_map( 'intval', $count_per_status );
+ // Until persistent counters reactivated, switch back to WordPress API for accessing post status counters.
+ return array_map( 'intval', (array) wp_count_posts( $post_type ) );
}
}
diff --git a/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php b/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php
index 85aeb04d176..fb1bbbd1ee0 100644
--- a/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php
+++ b/plugins/woocommerce/tests/php/src/Caching/ProductCountCacheServiceTest.php
@@ -187,6 +187,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
* @testdox Source status count is decremented correctly when only the source slot is warm and the destination slot is cold.
*/
public function test_count_decremented_when_only_source_status_is_cached(): void {
+ $this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
$product = WC_Helper_Product::create_simple_product();
$product->set_status( ProductStatus::DRAFT );
$product->save();
@@ -211,6 +213,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
* @testdox Final status is not double-incremented when a plugin permanently changes product status during creation.
*/
public function test_count_not_double_incremented_on_new_product_with_mid_creation_status_change(): void {
+ $this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
// Warm all status slots and record the publish count before the test.
$this->product_util->get_counts_for_type( 'product' );
$publish_before = $this->product_cache->get( 'product', array( ProductStatus::PUBLISH ) )[ ProductStatus::PUBLISH ];
@@ -242,6 +246,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
* @testdox Source status count is not corrupted when a plugin permanently changes product status during creation.
*/
public function test_source_count_not_corrupted_on_new_product_with_mid_creation_status_change(): void {
+ $this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
// Warm all status slots and record both counts before the test.
$this->product_util->get_counts_for_type( 'product' );
$draft_before = $this->product_cache->get( 'product', array( ProductStatus::DRAFT ) )[ ProductStatus::DRAFT ];
@@ -285,6 +291,8 @@ final class ProductCountCacheServiceTest extends \WC_Unit_Test_Case {
* @testdox Cache is populated when it is cold and an external object cache is active.
*/
public function test_prime_cache_if_cold_when_cache_is_cold(): void {
+ $this->markTestSkipped( 'Until persistent counters reactivated, skip this test.' );
+
global $_wp_using_ext_object_cache;
$_before = $_wp_using_ext_object_cache;
$_wp_using_ext_object_cache = true; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited