Commit b5422fe135 for woocommerce

commit b5422fe135f0c853f8bf8ab3f1802e881fa83f1d
Author: Jorge A. Torres <jorge.torres@automattic.com>
Date:   Thu Dec 11 17:42:13 2025 +0000

    Revert "Fully read orders from the CPT datastore (including meta) for sync-on-read" (#62402)

diff --git a/plugins/woocommerce/changelog/revert-61293-fix-43126 b/plugins/woocommerce/changelog/revert-61293-fix-43126
new file mode 100644
index 0000000000..6db8e0cc9b
--- /dev/null
+++ b/plugins/woocommerce/changelog/revert-61293-fix-43126
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Revert to previous sync-on-read logic to prevent unnecessary writes when HPOS and compat mode are enabled.
diff --git a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
index f74c258b51..d0acc398eb 100644
--- a/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
+++ b/plugins/woocommerce/includes/data-stores/abstract-wc-order-data-store-cpt.php
@@ -8,7 +8,6 @@
 use Automattic\Jetpack\Constants;
 use Automattic\WooCommerce\Caches\OrderCache;
 use Automattic\WooCommerce\Enums\OrderStatus;
-use Automattic\WooCommerce\Internal\Utilities\PostMetaUtil;
 use Automattic\WooCommerce\Proxies\LegacyProxy;
 use Automattic\WooCommerce\Utilities\OrderUtil;

@@ -779,8 +778,23 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
 					}
 				}
 			}
-
-			PostMetaUtil::add_post_meta_safe( $order->get_id(), $meta_data->key, $meta_data->value, false );
+			if ( is_object( $meta_data->value ) && '__PHP_Incomplete_Class' === get_class( $meta_data->value ) ) {
+				$meta_value = maybe_serialize( $meta_data->value );
+				$result     = $wpdb->insert(
+					_get_meta_table( 'post' ),
+					array(
+						'post_id'    => $order->get_id(),
+						'meta_key'   => $meta_data->key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
+						'meta_value' => $meta_value, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
+					),
+					array( '%d', '%s', '%s' )
+				);
+				wp_cache_delete( $order->get_id(), 'post_meta' );
+				$logger = wc_get_container()->get( LegacyProxy::class )->call_function( 'wc_get_logger' );
+				$logger->warning( sprintf( 'encountered an order meta value of type __PHP_Incomplete_Class during `update_order_meta_from_object` in order with ID %d: "%s"', $order->get_id(), var_export( $meta_value, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
+			} else {
+				add_post_meta( $order->get_id(), $meta_data->key, $meta_data->value, false );
+			}
 		}

 		// Find remaining meta that was deleted from the order but still present in the associated post.
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index e1dbb1f5fa..f078f14461 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -99276,18 +99276,6 @@ parameters:
 			count: 1
 			path: src/Internal/Utilities/PluginInstaller.php

-		-
-			message: '#^Cannot call method warning\(\) on mixed\.$#'
-			identifier: method.nonObject
-			count: 3
-			path: src/Internal/Utilities/PostMetaUtil.php
-
-		-
-			message: '#^Parameter \#1 \$data of function maybe_serialize expects array\|object\|string, mixed given\.$#'
-			identifier: argument.type
-			count: 3
-			path: src/Internal/Utilities/PostMetaUtil.php
-
 		-
 			message: '#^Binary operation "\." between ''wc_child_has…''\|''wc_child_has_weight_''\|''wc_product_children_''\|''wc_related_''\|''wc_var_prices_'' and Automattic\\WooCommerce\\Internal\\Utilities\\WC_Product\|int results in an error\.$#'
 			identifier: binaryOp.invalid
diff --git a/plugins/woocommerce/src/Internal/DataStores/Orders/LegacyDataHandler.php b/plugins/woocommerce/src/Internal/DataStores/Orders/LegacyDataHandler.php
index c9cc817231..79eac797df 100644
--- a/plugins/woocommerce/src/Internal/DataStores/Orders/LegacyDataHandler.php
+++ b/plugins/woocommerce/src/Internal/DataStores/Orders/LegacyDataHandler.php
@@ -305,13 +305,30 @@ class LegacyDataHandler {
 		$order     = new $classname();
 		$order->set_id( $order_id );

+		// Switch datastore if necessary.
+		$update_data_store_func = function ( $data_store ) {
+			// Each order object contains a reference to its data store, but this reference is itself
+			// held inside of an instance of WC_Data_Store, so we create that first.
+			$data_store_wrapper = \WC_Data_Store::load( 'order' );
+
+			// Bind $data_store to our WC_Data_Store.
+			( function ( $data_store ) {
+				$this->current_class_name = get_class( $data_store );
+				$this->instance           = $data_store;
+			} )->call( $data_store_wrapper, $data_store );
+
+			// Finally, update the $order object with our WC_Data_Store( $data_store ) instance.
+			$this->data_store = $data_store_wrapper;
+		};
+		$update_data_store_func->call( $order, $data_store );
+
 		// Read order (without triggering sync) -- we create our own callback instead of using `__return_false` to
 		// prevent `remove_filter()` from removing it in cases where it was already hooked by 3rd party code.
 		$prevent_sync_on_read = fn() => false;

 		add_filter( 'woocommerce_hpos_enable_sync_on_read', $prevent_sync_on_read, 999 );
 		try {
-			$this->read_order_from_datastore( $order, $data_store );
+			$data_store->read( $order );
 		} finally {
 			remove_filter( 'woocommerce_hpos_enable_sync_on_read', $prevent_sync_on_read, 999 );
 		}
@@ -319,30 +336,6 @@ class LegacyDataHandler {
 		return $order;
 	}

-	/**
-	 * Reads an order from a datastore fully changing the instance of the datastore inside the order object.
-	 *
-	 * @since 10.4.0
-	 *
-	 * @param \WC_Abstract_Order &$order      The order object to read from the datastore.
-	 * @param object             &$data_store The datastore to read from.
-	 */
-	public function read_order_from_datastore( \WC_Abstract_Order &$order, &$data_store ) {
-		// Change the instance of the datastore inside the datastore object.
-		( function () use ( $data_store ) {
-			if ( $this->data_store instanceof \WC_Data_Store ) {
-				( function () use ( $data_store ) {
-					$this->current_class_name = get_class( $data_store );
-					$this->instance           = $data_store;
-				} )->call( $this->data_store );
-			} else {
-				$this->data_store = $data_store;
-			}
-		} )->call( $order );
-
-		$data_store->read( $order );
-	}
-
 	/**
 	 * Backfills an order from/to the CPT or HPOS datastore.
 	 *
diff --git a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
index 58808e496e..6e73c1e1c9 100644
--- a/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
+++ b/plugins/woocommerce/src/Internal/DataStores/Orders/OrdersTableDataStore.php
@@ -20,7 +20,6 @@ use WC_Abstract_Order;
 use WC_Data;
 use WC_Order;
 use Automattic\WooCommerce\Internal\Fulfillments\FulfillmentUtils;
-use Automattic\WooCommerce\Internal\Utilities\PostMetaUtil;

 defined( 'ABSPATH' ) || exit;

@@ -1541,8 +1540,6 @@ WHERE
 	 * @throws \Exception If no CPT data store is found for an order.
 	 */
 	private function get_post_orders_for_ids( array $orders ): array {
-		$legacy_handler = wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\LegacyDataHandler::class );
-
 		$order_ids = array_keys( $orders );
 		foreach ( $order_ids as $order_id ) {
 			// Exclude orders where the CPT version is a placeholder post.
@@ -1587,7 +1584,7 @@ WHERE

 				try {
 					$cpt_order->set_id( $order_id );
-					$legacy_handler->read_order_from_datastore( $cpt_order, $cpt_store );
+					$cpt_store->read( $cpt_order );
 					$cpt_orders[ $order_id ] = $cpt_order;
 				} catch ( Exception $e ) {
 					// If the post record has been deleted (for instance, by direct query) then an exception may be thrown.
@@ -1649,25 +1646,15 @@ WHERE
 	 *
 	 * Also provides an option to sync the metadata as well, since we are already computing the diff.
 	 *
-	 * @param \WC_Abstract_Order $order1 Order object read from COT.
-	 * @param \WC_Abstract_Order $order2 Order object read from posts.
+	 * @param \WC_Abstract_Order $order1 Order object read from posts.
+	 * @param \WC_Abstract_Order $order2 Order object read from COT.
 	 * @param bool               $sync   Whether to also sync the meta data.
 	 *
 	 * @return array Difference between post and COT meta data.
 	 */
 	private function get_diff_meta_data_between_orders( \WC_Abstract_Order &$order1, \WC_Abstract_Order $order2, $sync = false ): array {
-		$order1_meta = ArrayUtil::select( $order1->get_meta_data(), 'get_data', ArrayUtil::SELECT_BY_OBJECT_METHOD );
-		$order2_meta = ArrayUtil::select( $order2->get_meta_data(), 'get_data', ArrayUtil::SELECT_BY_OBJECT_METHOD );
-
-		// Canonicalize metadata by converting scalar to string for comparison purposes.
-		if ( ! $sync ) {
-			$maybe_convert_to_string = function ( &$m ) {
-				$m['value'] = is_scalar( $m['value'] ) ? (string) $m['value'] : $m['value'];
-			};
-			array_walk( $order1_meta, $maybe_convert_to_string );
-			array_walk( $order2_meta, $maybe_convert_to_string );
-		}
-
+		$order1_meta        = ArrayUtil::select( $order1->get_meta_data(), 'get_data', ArrayUtil::SELECT_BY_OBJECT_METHOD );
+		$order2_meta        = ArrayUtil::select( $order2->get_meta_data(), 'get_data', ArrayUtil::SELECT_BY_OBJECT_METHOD );
 		$order1_meta_by_key = ArrayUtil::select_as_assoc( $order1_meta, 'key', ArrayUtil::SELECT_BY_ARRAY_KEY );
 		$order2_meta_by_key = ArrayUtil::select_as_assoc( $order2_meta, 'key', ArrayUtil::SELECT_BY_ARRAY_KEY );

@@ -1687,7 +1674,7 @@ WHERE

 			$order2_values = ArrayUtil::select( $order2_meta_by_key[ $key ], 'value', ArrayUtil::SELECT_BY_ARRAY_KEY );
 			$new_diff      = ArrayUtil::deep_assoc_array_diff( $order1_values, $order2_values );
-			if ( ! empty( $new_diff ) ) {
+			if ( ! empty( $new_diff ) && $sync ) {
 				if ( count( $order2_values ) > 1 ) {
 					$sync && $order1->delete_meta_data( $key );
 					foreach ( $order2_values as $post_order_value ) {
@@ -3308,6 +3295,8 @@ CREATE TABLE $meta_table (
 	 * @return bool
 	 */
 	public function delete_meta( &$object, $meta ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.objectFound
+		global $wpdb;
+
 		if ( $this->should_backfill_post_record() && isset( $meta->id ) ) {
 			// Let's get the actual meta key before its deleted for backfilling. We cannot delete just by ID because meta IDs are different in HPOS and posts tables.
 			$db_meta = $this->data_store_meta->get_metadata_by_id( $meta->id );
@@ -3322,7 +3311,23 @@ CREATE TABLE $meta_table (

 		if ( ! $changes_applied && $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() && isset( $meta->key ) ) {
 			self::$backfilling_order_ids[] = $object->get_id();
-			PostMetaUtil::delete_post_meta_safe( $object->get_id(), $meta->key, $meta->value );
+			if ( is_object( $meta->value ) && '__PHP_Incomplete_Class' === get_class( $meta->value ) ) {
+				$meta_value = maybe_serialize( $meta->value );
+				$wpdb->delete(
+					_get_meta_table( 'post' ),
+					array(
+						'post_id'    => $object->get_id(),
+						'meta_key'   => $meta->key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
+						'meta_value' => $meta_value, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
+					),
+					array( '%d', '%s', '%s' )
+				);
+				wp_cache_delete( $object->get_id(), 'post_meta' );
+				$logger = wc_get_container()->get( LegacyProxy::class )->call_function( 'wc_get_logger' );
+				$logger->warning( sprintf( 'encountered an order meta value of type __PHP_Incomplete_Class during `delete_meta` in order with ID %d: "%s"', $object->get_id(), var_export( $meta_value, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
+			} else {
+				delete_post_meta( $object->get_id(), $meta->key, $meta->value );
+			}
 			self::$backfilling_order_ids = array_diff( self::$backfilling_order_ids, array( $object->get_id() ) );
 		}

@@ -3365,7 +3370,7 @@ CREATE TABLE $meta_table (

 		if ( ! $changes_applied && $object instanceof WC_Abstract_Order && $this->should_backfill_post_record() ) {
 			self::$backfilling_order_ids[] = $object->get_id();
-			PostMetaUtil::update_post_meta_safe( $object->get_id(), $meta->key, $meta->value );
+			update_post_meta( $object->get_id(), $meta->key, $meta->value );
 			self::$backfilling_order_ids = array_diff( self::$backfilling_order_ids, array( $object->get_id() ) );
 		}

diff --git a/plugins/woocommerce/src/Internal/Utilities/PostMetaUtil.php b/plugins/woocommerce/src/Internal/Utilities/PostMetaUtil.php
deleted file mode 100644
index bcead96f2f..0000000000
--- a/plugins/woocommerce/src/Internal/Utilities/PostMetaUtil.php
+++ /dev/null
@@ -1,133 +0,0 @@
-<?php
-declare( strict_types=1 );
-
-namespace Automattic\WooCommerce\Internal\Utilities;
-
-use Automattic\WooCommerce\Proxies\LegacyProxy;
-
-/**
- * A class of utilities for dealing with post meta.
- *
- * @since 10.4.0
- */
-class PostMetaUtil {
-
-	/**
-	 * Check if a value is an incomplete object.
-	 *
-	 * @param mixed $value The value to check.
-	 * @return bool TRUE if the value is an incomplete object, FALSE otherwise.
-	 */
-	private static function is_incomplete_object( $value ): bool {
-		return is_object( $value ) && '__PHP_Incomplete_Class' === get_class( $value );
-	}
-
-	/**
-	 * Add a post meta value safely, ensuring incomplete objects are handled gracefully.
-	 *
-	 * @param int    $post_id The post ID.
-	 * @param string $key     The meta key.
-	 * @param mixed  $value   The meta value.
-	 * @param bool   $unique  Whether the meta value should be unique.
-	 * @return bool
-	 */
-	public static function add_post_meta_safe( int $post_id, string $key, $value, bool $unique = false ): bool {
-		global $wpdb;
-
-		if ( ! self::is_incomplete_object( $value ) ) {
-			return (bool) add_post_meta( $post_id, $key, $value, $unique );
-		}
-
-		if ( $unique && metadata_exists( 'post', $post_id, $key ) ) {
-			return false;
-		}
-
-		$value  = maybe_serialize( $value );
-		$result = $wpdb->insert(
-			_get_meta_table( 'post' ),
-			array(
-				'post_id'    => $post_id,
-				'meta_key'   => $key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
-				'meta_value' => $value, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
-			),
-			array( '%d', '%s', '%s' )
-		);
-		wp_cache_delete( $post_id, 'post_meta' );
-
-		$logger = wc_get_container()->get( LegacyProxy::class )->call_function( 'wc_get_logger' );
-		$logger->warning( sprintf( 'encountered a post meta value of type __PHP_Incomplete_Class during `add_post_meta_safe` in post with ID %d and key %s: "%s"', $post_id, $key, var_export( $value, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
-
-		return (bool) $result;
-	}
-
-	/**
-	 * Delete a post meta value safely, ensuring incomplete objects are handled gracefully.
-	 *
-	 * @param int    $post_id The post ID.
-	 * @param string $key     The meta key.
-	 * @param mixed  $value   The meta value.
-	 * @return bool
-	 */
-	public static function delete_post_meta_safe( int $post_id, string $key, $value ): bool {
-		global $wpdb;
-
-		if ( ! self::is_incomplete_object( $value ) ) {
-			return delete_post_meta( $post_id, $key, $value );
-		}
-
-		$value = maybe_serialize( $value );
-
-		$result = $wpdb->delete(
-			_get_meta_table( 'post' ),
-			array(
-				'post_id'    => $post_id,
-				'meta_key'   => $key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
-				'meta_value' => $value, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
-			),
-			array( '%d', '%s', '%s' )
-		);
-		wp_cache_delete( $post_id, 'post_meta' );
-
-		$logger = wc_get_container()->get( LegacyProxy::class )->call_function( 'wc_get_logger' );
-		$logger->warning( sprintf( 'encountered a post meta value of type __PHP_Incomplete_Class during `delete_post_meta_safe` in post with ID %d and key %s: "%s"', $post_id, $key, var_export( $value, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
-
-		return (bool) $result;
-	}
-
-	/**
-	 * Update a post meta value safely, ensuring incomplete objects are handled gracefully.
-	 *
-	 * @param int    $post_id The post ID.
-	 * @param string $key     The meta key.
-	 * @param mixed  $value   The meta value.
-	 * @return bool
-	 */
-	public static function update_post_meta_safe( int $post_id, string $key, $value ): bool {
-		global $wpdb;
-
-		if ( ! self::is_incomplete_object( $value ) ) {
-			return (bool) update_post_meta( $post_id, $key, $value );
-		}
-
-		$value = maybe_serialize( $value );
-
-		$result = $wpdb->update(
-			_get_meta_table( 'post' ),
-			array(
-				'meta_value' => $value, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
-			),
-			array(
-				'post_id'  => $post_id,
-				'meta_key' => $key, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
-			),
-			array( '%s' ),
-			array( '%d', '%s' )
-		);
-		wp_cache_delete( $post_id, 'post_meta' );
-
-		$logger = wc_get_container()->get( LegacyProxy::class )->call_function( 'wc_get_logger' );
-		$logger->warning( sprintf( 'encountered a post meta value of type __PHP_Incomplete_Class during `update_post_meta_safe` in post with ID %d and key %s: "%s"', $post_id, $key, var_export( $value, true ) ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
-
-		return (bool) $result;
-	}
-}
diff --git a/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php b/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
index a951bac96e..cce4e759ff 100644
--- a/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
+++ b/plugins/woocommerce/tests/php/src/Internal/DataStores/Orders/OrdersTableDataStoreTests.php
@@ -3494,11 +3494,7 @@ class OrdersTableDataStoreTests extends \HposTestCase {
 		$this->assertEquals( 'Europe/Brussels', $meta_object_vars['timezone'] );

 		// Check that the log entry was created.
-		$serialized_meta_value = '"\'O:11:"geoiprecord":14:{s:12:"country_code";s:2:"BE";s:13:"country_code3";s:3:"BEL";s:12:"country_name";s:7:"Belgium";s:6:"region";s:3:"BRU";s:4:"city";s:8:"Brussels";s:11:"postal_code";s:4:"1000";s:8:"latitude";d:50.8333;s:9:"longitude";d:4.3333;s:9:"area_code";N;s:8:"dma_code";N;s:10:"metro_code";N;s:14:"continent_code";s:2:"EU";s:11:"region_name";s:16:"Brussels Capital";s:8:"timezone";s:15:"Europe/Brussels";}\'"';
-
-		$log_message = end( $fake_logger->warnings )['message'];
-		$this->assertStringContainsString( 'encountered a post meta value of type __PHP_Incomplete_Class during', $log_message );
-		$this->assertStringContainsString( $serialized_meta_value, $log_message );
+		$this->assertEquals( 'encountered an order meta value of type __PHP_Incomplete_Class during `update_order_meta_from_object` in order with ID ' . $order->get_id() . ': "\'O:11:"geoiprecord":14:{s:12:"country_code";s:2:"BE";s:13:"country_code3";s:3:"BEL";s:12:"country_name";s:7:"Belgium";s:6:"region";s:3:"BRU";s:4:"city";s:8:"Brussels";s:11:"postal_code";s:4:"1000";s:8:"latitude";d:50.8333;s:9:"longitude";d:4.3333;s:9:"area_code";N;s:8:"dma_code";N;s:10:"metro_code";N;s:14:"continent_code";s:2:"EU";s:11:"region_name";s:16:"Brussels Capital";s:8:"timezone";s:15:"Europe/Brussels";}\'"', end( $fake_logger->warnings )['message'] );

 		// Test deleting meta data containing an object of a non-existent class.
 		$meta_data = $this->sut->read_meta( $order );
@@ -3511,9 +3507,7 @@ class OrdersTableDataStoreTests extends \HposTestCase {
 		$this->assertEquals( '', get_post_meta( $order->get_id(), $meta_key, true ) );

 		// Check that the log entry was created.
-		$log_message = end( $fake_logger->warnings )['message'];
-		$this->assertStringContainsString( 'encountered a post meta value of type __PHP_Incomplete_Class during', $log_message );
-		$this->assertStringContainsString( $serialized_meta_value, $log_message );
+		$this->assertEquals( 'encountered an order meta value of type __PHP_Incomplete_Class during `delete_meta` in order with ID ' . $order->get_id() . ': "\'O:11:"geoiprecord":14:{s:12:"country_code";s:2:"BE";s:13:"country_code3";s:3:"BEL";s:12:"country_name";s:7:"Belgium";s:6:"region";s:3:"BRU";s:4:"city";s:8:"Brussels";s:11:"postal_code";s:4:"1000";s:8:"latitude";d:50.8333;s:9:"longitude";d:4.3333;s:9:"area_code";N;s:8:"dma_code";N;s:10:"metro_code";N;s:14:"continent_code";s:2:"EU";s:11:"region_name";s:16:"Brussels Capital";s:8:"timezone";s:15:"Europe/Brussels";}\'"', end( $fake_logger->warnings )['message'] );
 	}

 	/**
@@ -3880,26 +3874,6 @@ class OrdersTableDataStoreTests extends \HposTestCase {
 		$this->assertEquals( $wpdb->get_var( $query ), 2 ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- query has already been prepared.
 	}

-	/**
-	 * @testdox Sync-on-read should update metadata as well.
-	 */
-	public function test_sync_on_read_updates_metadata() {
-		$this->toggle_cot_feature_and_usage( true );
-		$this->enable_cot_sync();
-
-		$order = OrderHelper::create_order();
-		$order->add_meta_data( 'foo', 'bar' );
-		$order->save();
-
-		// Update the meta data on the post.
-		update_post_meta( $order->get_id(), 'foo', 'baz' );
-
-		$fresh_order = wc_get_order( $order->get_id() );
-
-		$this->assertEquals( 'baz', get_post_meta( $order->get_id(), 'foo', true ) );
-		$this->assertEquals( 'baz', $fresh_order->get_meta( 'foo', true, 'edit' ) );
-	}
-
 	/**
 	 * @testdox An order deleted from the posts table while sync was off is deleted from the orders table when sync runs.
 	 */