Revert "[COT] Add the orders cache" (#34992)

Revert "[COT] Add the orders cache (#34396)"

This reverts commit 3f155c9a63.
This commit is contained in:
Vedanshu Jain 2022-10-07 20:09:09 +05:30 committed by GitHub
parent 1eb02b4742
commit 0b5d7ab9ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 57 additions and 503 deletions

View File

@ -1,4 +0,0 @@
Significance: minor
Type: add
Add a cache for orders, to use when custom order tables are enabled

View File

@ -10,11 +10,9 @@
* @package WooCommerce\Classes
*/
use Automattic\WooCommerce\Caches\OrderCache;
use Automattic\WooCommerce\Proxies\LegacyProxy;
use Automattic\WooCommerce\Utilities\ArrayUtil;
use Automattic\WooCommerce\Utilities\NumberUtil;
use Automattic\WooCommerce\Utilities\OrderUtil;
defined( 'ABSPATH' ) || exit;
@ -205,11 +203,6 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$this->save_items();
if ( OrderUtil::orders_cache_usage_is_enabled() ) {
$order_cache = wc_get_container()->get( OrderCache::class );
$order_cache->update_if_cached( $this );
}
/**
* Trigger action after saving to the DB.
*

View File

@ -488,8 +488,6 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
$visibility_class[] = 'show_options_if_checked';
}
$must_disable = ArrayUtil::get_value_or_default( $value, 'disabled', false );
if ( ! isset( $value['checkboxgroup'] ) || 'start' === $value['checkboxgroup'] ) {
?>
<tr valign="top" class="<?php echo esc_attr( implode( ' ', $visibility_class ) ); ?>">
@ -512,7 +510,6 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
?>
<label for="<?php echo esc_attr( $value['id'] ); ?>">
<input
<?php echo $must_disable ? 'disabled' : ''; ?>
name="<?php echo esc_attr( $value['field_name'] ); ?>"
id="<?php echo esc_attr( $value['id'] ); ?>"
type="checkbox"

View File

@ -8,9 +8,6 @@
* @package WooCommerce\Classes
*/
use Automattic\WooCommerce\Caches\OrderCache;
use Automattic\WooCommerce\Utilities\OrderUtil;
defined( 'ABSPATH' ) || exit;
/**
@ -31,26 +28,13 @@ class WC_Order_Factory {
return false;
}
$use_orders_cache = OrderUtil::orders_cache_usage_is_enabled();
if ( $use_orders_cache ) {
$order_cache = wc_get_container()->get( OrderCache::class );
$order = $order_cache->get( $order_id );
if ( ! is_null( $order ) ) {
return $order;
}
}
$classname = self::get_class_name_for_order_id( $order_id );
if ( ! $classname ) {
return false;
}
try {
$order = new $classname( $order_id );
if ( $use_orders_cache && $order instanceof \WC_Abstract_Legacy_Order ) {
$order_cache->set( $order, $order_id );
}
return $order;
return new $classname( $order_id );
} catch ( Exception $e ) {
wc_caught_exception( $e, __FUNCTION__, array( $order_id ) );
return false;
@ -70,25 +54,8 @@ class WC_Order_Factory {
$result = array();
$order_ids = array_filter( array_map( array( __CLASS__, 'get_order_id' ), $order_ids ) );
$already_cached_orders = array();
$use_orders_cache = OrderUtil::orders_cache_usage_is_enabled();
if ( $use_orders_cache ) {
$uncached_order_ids = array();
$order_cache = wc_get_container()->get( OrderCache::class );
foreach ( $order_ids as $order_id ) {
$cached_order = $order_cache->get( absint( $order_id ) );
if ( is_null( $cached_order ) ) {
$uncached_order_ids[] = $order_id;
} else {
$already_cached_orders[] = $cached_order;
}
}
$order_ids = $uncached_order_ids;
}
// We separate order list by class, since their datastore might be different.
$order_list_by_class = array();
foreach ( $order_ids as $order_id ) {
$classname = self::get_class_name_for_order_id( $order_id );
if ( ! $classname && ! $skip_invalid ) {
@ -130,16 +97,9 @@ class WC_Order_Factory {
}
// restore the sort order.
$result = array_values( array_replace( array_flip( $order_ids ), $result ) );
$result = array_replace( array_flip( $order_ids ), $result );
if ( $use_orders_cache ) {
foreach ( $result as $order ) {
$order_cache->set( $order );
}
return array_merge( $already_cached_orders, $result );
} else {
return $result;
}
return array_values( $result );
}
/**

View File

@ -1,44 +0,0 @@
<?php
namespace Automattic\WooCommerce\Caches;
use Automattic\WooCommerce\Caching\ObjectCache;
/**
* A class to cache order objects.
*/
class OrderCache extends ObjectCache {
/**
* Get the identifier for the type of the cached objects.
*
* @return string
*/
public function get_object_type(): string {
return 'order';
}
/**
* Get the id of an object to be cached.
*
* @param array|object $object The object to be cached.
* @return int|string|null The id of the object, or null if it can't be determined.
*/
protected function get_object_id( $object ) {
return $object->get_id();
}
/**
* Validate an object before caching it.
*
* @param array|object $object The object to validate.
* @return string[]|null An array of error messages, or null if the object is valid.
*/
protected function validate( $object ): ?array {
if ( ! $object instanceof \WC_Abstract_Legacy_Order ) {
return array( 'The supplied order is not an instance of WC_Order, ' . gettype( $object ) );
}
return null;
}
}

View File

@ -1,121 +0,0 @@
<?php
namespace Automattic\WooCommerce\Caches;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
/**
* A class to control the usage of the orders cache.
*/
class OrderCacheController {
use AccessiblePrivateMethods;
const FEATURE_NAME = 'orders_cache';
/**
* The orders cache to use.
*
* @var OrderCache
*/
private $order_cache;
/**
* The orders cache to use.
*
* @var FeaturesController
*/
private $features_controller;
/**
* The backup value of the cache usage enable status, stored while the cache is temporarily disabled.
*
* @var null|bool
*/
private $orders_cache_usage_backup = null;
/**
* Creates a new instance of the class.
*/
public function __construct() {
self::add_action( FeaturesController::FEATURE_ENABLED_CHANGED_ACTION, array( $this, 'handle_feature_enable_changed' ), 10, 2 );
}
/**
* Class initialization, invoked by the DI container.
*
* @internal
* @param OrderCache $order_cache The order cache engine to use.
* @param FeaturesController $features_controller The features controller to use.
*/
final public function init( OrderCache $order_cache, FeaturesController $features_controller ) {
$this->order_cache = $order_cache;
$this->features_controller = $features_controller;
}
/**
* Handler for the feature enable changed action, when the orders cache is enabled or disabled it flushes it.
*
* @param string $feature_id The id of the feature whose enable status changed.
* @param bool $enabled Whether the feature has been enabled or disabled.
* @return void
*/
private function handle_feature_enable_changed( string $feature_id, bool $enabled ): void {
if ( self::FEATURE_NAME === $feature_id ) {
$this->order_cache->flush();
}
}
/**
* Set the value of the order cache usage setting.
*
* @param bool $enable True if the order cache should be used, false if not.
* @throws \Exception Attempt to enable the orders cache usage while it's temporarily disabled.
*/
public function set_orders_cache_usage( bool $enable ): void {
$this->features_controller->change_feature_enable( $enable );
$this->orders_cache_usage_backup = null;
}
/**
* Get the value of the order cache usage setting.
*
* @return bool True if order cache usage setting is currently enabled, false if not.
*/
public function orders_cache_usage_is_enabled(): bool {
return ! $this->orders_cache_usage_is_temporarly_disabled() && $this->features_controller->feature_is_enabled( self::FEATURE_NAME );
}
/**
* Temporarily disable the order cache if it's enabled.
*
* This is a purely in-memory operation: a variable is created with the value
* of the current enable status for the feature, and this variable
* is checked by orders_cache_usage_is_enabled. In the next request the
* feature will be again enabled or not depending on how the feature is set.
*/
public function temporarily_disable_orders_cache_usage(): void {
if ( $this->orders_cache_usage_is_temporarly_disabled() ) {
return;
}
$this->orders_cache_usage_backup = $this->orders_cache_usage_is_enabled();
}
/**
* Check if the order cache has been temporarily disabled.
*
* @return bool True if the order cache is currently temporarily disabled.
*/
public function orders_cache_usage_is_temporarly_disabled(): bool {
return null !== $this->orders_cache_usage_backup;
}
/**
* Restore the order cache usage that had been temporarily disabled.
*/
public function maybe_restore_orders_cache_usage(): void {
$this->orders_cache_usage_backup = null;
}
}

View File

@ -164,13 +164,13 @@ abstract class ObjectCache {
/**
* Add an object to the cache, or update an already cached object.
*
* @param object|array $object The object to be cached.
* @param int|string|null $id Id of the object to be cached, if null, get_object_id will be used to get it.
* @param object|array $object The object to be cached.
* @param int $expiration Expiration of the cached data in seconds from the current time, or DEFAULT_EXPIRATION to use the default value.
* @return bool True on success, false on error.
* @throws CacheException Invalid parameter, or null id was passed and get_object_id returns null too.
*/
public function set( $object, $id = null, int $expiration = self::DEFAULT_EXPIRATION ): bool {
public function set( $id = null, $object, int $expiration = self::DEFAULT_EXPIRATION ): bool {
if ( null === $object ) {
throw new CacheException( "Can't cache a null value", $this, $id );
}
@ -185,22 +185,20 @@ abstract class ObjectCache {
$this->verify_expiration_value( $expiration );
$errors = $this->validate( $object );
if ( ! is_null( $errors ) ) {
try {
$id = $this->get_id_from_object_if_null( $object, $id );
} catch ( \Throwable $ex ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
// Nothing else to do, we won't be able to add any significant object id to the CacheException and that's it.
}
if ( count( $errors ) === 1 ) {
throw new CacheException( 'Object validation/serialization failed: ' . $errors[0], $this, $id, $errors );
} elseif ( ! empty( $errors ) ) {
throw new CacheException( 'Object validation/serialization failed', $this, $id, $errors );
if ( null === $id ) {
$id = $this->get_object_id( $object );
if ( null === $id ) {
throw new CacheException( "Null id supplied and the cache class doesn't implement get_object_id", $this );
}
}
$id = $this->get_id_from_object_if_null( $object, $id );
$errors = $this->validate( $object );
if ( null !== $errors && 1 === count( $errors ) ) {
throw new CacheException( 'Object validation/serialization failed: ' . $errors[0], $this, $id, $errors );
} elseif ( ! empty( $errors ) ) {
throw new CacheException( 'Object validation/serialization failed', $this, $id, $errors );
}
$data = $this->serialize( $object );
/**
@ -215,49 +213,7 @@ abstract class ObjectCache {
$data = apply_filters( "woocommerce_after_serializing_{$this->object_type}_for_caching", $data, $object, $id );
$this->last_cached_data = $data;
return $this->get_cache_engine()->cache_object(
$this->get_cache_key_prefix() . $id,
$data,
self::DEFAULT_EXPIRATION === $expiration ? $this->default_expiration : $expiration
);
}
/**
* Update an object in the cache, but only if an object is already cached with the same id.
*
* @param object|array $object The new object that will replace the already cached one.
* @param int|string|null $id Id of the object to be cached, if null, get_object_id will be used to get it.
* @param int $expiration Expiration of the cached data in seconds from the current time, or DEFAULT_EXPIRATION to use the default value.
* @return bool True on success, false on error or if no object wiith the supplied id was cached.
* @throws CacheException Invalid parameter, or null id was passed and get_object_id returns null too.
*/
public function update_if_cached( $object, $id = null, int $expiration = self::DEFAULT_EXPIRATION ): bool {
$id = $this->get_id_from_object_if_null( $object, $id );
if ( ! $this->is_cached( $id ) ) {
return false;
}
return $this->set( $object, $id, $expiration );
}
/**
* Get the id from an object if the id itself is null.
*
* @param object|array $object The object to get the id from.
* @param int|string|null $id An object id or null.
* @return int|string|null Passed $id if it wasn't null, otherwise id obtained from $object using get_object_id.
* @throws CacheException Passed $id is null and get_object_id returned null too.
*/
private function get_id_from_object_if_null( $object, $id ) {
if ( null === $id ) {
$id = $this->get_object_id( $object );
if ( null === $id ) {
throw new CacheException( "Null id supplied and the cache class doesn't implement get_object_id", $this );
}
}
return $id;
return $this->get_cache_engine()->cache_object( $this->get_cache_key_prefix() . $id, $data, self::DEFAULT_EXPIRATION === $expiration ? $this->default_expiration : $expiration );
}
/**
@ -305,7 +261,7 @@ abstract class ObjectCache {
return null;
}
$this->set( $object, $id, $expiration );
$this->set( $id, $object, $expiration );
$data = $this->last_cached_data;
}

View File

@ -5,12 +5,9 @@
namespace Automattic\WooCommerce\Internal\DataStores\Orders;
use Automattic\WooCommerce\Caches\OrderCache;
use Automattic\WooCommerce\Caches\OrderCacheController;
use Automattic\WooCommerce\Internal\BatchProcessing\BatchProcessingController;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
use Automattic\WooCommerce\Utilities\OrderUtil;
defined( 'ABSPATH' ) || exit;
@ -84,20 +81,6 @@ class CustomOrdersTableController {
*/
private $features_controller;
/**
* The orders cache object to use.
*
* @var OrderCache
*/
private $order_cache;
/**
* The orders cache controller object to use.
*
* @var OrderCacheController
*/
private $order_cache_controller;
/**
* Class constructor.
*/
@ -119,8 +102,6 @@ class CustomOrdersTableController {
self::add_filter( DataSynchronizer::PENDING_SYNCHRONIZATION_FINISHED_ACTION, array( $this, 'process_sync_finished' ), 10, 0 );
self::add_action( 'woocommerce_update_options_advanced_custom_data_stores', array( $this, 'process_options_updated' ), 10, 0 );
self::add_action( 'woocommerce_after_register_post_type', array( $this, 'register_post_type_for_order_placeholders' ), 10, 0 );
self::add_action( 'woocommerce_delete_order', array( $this, 'after_order_deleted_or_trashed' ), 10, 1);
self::add_action( 'woocommerce_trash_order', array( $this, 'after_order_deleted_or_trashed' ), 10, 1);
}
/**
@ -132,24 +113,18 @@ class CustomOrdersTableController {
* @param OrdersTableRefundDataStore $refund_data_store The refund data store to use.
* @param BatchProcessingController $batch_processing_controller The batch processing controller to use.
* @param FeaturesController $features_controller The features controller instance to use.
* @param OrderCache $order_cache The order cache engine to use.
* @param OrderCacheController $order_cache_controller The order cache controller to use.
*/
final public function init(
OrdersTableDataStore $data_store,
DataSynchronizer $data_synchronizer,
OrdersTableRefundDataStore $refund_data_store,
BatchProcessingController $batch_processing_controller,
FeaturesController $features_controller,
OrderCache $order_cache,
OrderCacheController $order_cache_controller ) {
FeaturesController $features_controller ) {
$this->data_store = $data_store;
$this->data_synchronizer = $data_synchronizer;
$this->batch_processing_controller = $batch_processing_controller;
$this->refund_data_store = $refund_data_store;
$this->features_controller = $features_controller;
$this->order_cache = $order_cache;
$this->order_cache_controller = $order_cache_controller;
}
/**
@ -497,19 +472,12 @@ class CustomOrdersTableController {
* @throws \Exception Attempt to change the authoritative orders table while orders sync is pending.
*/
private function process_pre_update_option( $value, $option, $old_value ) {
if ( $option === DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION && $value !== $old_value ) {
$this->order_cache->flush();
if ( $option !== self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION || $value === $old_value || $old_value === false ) {
return $value;
}
if ( self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION !== $option || $value === $old_value || false === $old_value ) {
return $value;
}
$this->order_cache->flush();
/**
* TODO: Re-enable the following code once the COT to posts table sync is implemented (it's currently commented out to ease testing).
* Commenting out for better testability.
$sync_is_pending = 0 !== $this->data_synchronizer->get_current_orders_pending_sync_count();
if ( $sync_is_pending ) {
throw new \Exception( "The authoritative table for orders storage can't be changed while there are orders out of sync" );
@ -599,15 +567,4 @@ class CustomOrdersTableController {
)
);
}
/**
* Handle the order deleted/trashed hooks.
*
* @param int $order_id The id of the order deleted or trashed.
*/
private function after_order_deleted_or_trashed( int $order_id ): void {
if ( $this->features_controller->feature_is_enabled( OrderCacheController::FEATURE_NAME ) ) {
$this->order_cache->remove( $order_id );
}
}
}

View File

@ -5,8 +5,6 @@
namespace Automattic\WooCommerce\Internal\DataStores\Orders;
use Automattic\WooCommerce\Caches\OrderCache;
use Automattic\WooCommerce\Caches\OrderCacheController;
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
use Automattic\WooCommerce\Internal\BatchProcessing\BatchProcessorInterface;
use Automattic\WooCommerce\Internal\Utilities\DatabaseUtil;
@ -53,20 +51,6 @@ class DataSynchronizer implements BatchProcessorInterface {
*/
private $posts_to_cot_migrator;
/**
* The orders cache to use.
*
* @var OrderCache
*/
private $cache;
/**
* The orders cache controller to use.
*
* @var OrderCacheController
*/
private $cache_controller;
/**
* Class constructor.
*/
@ -101,21 +85,12 @@ class DataSynchronizer implements BatchProcessorInterface {
* @param OrdersTableDataStore $data_store The data store to use.
* @param DatabaseUtil $database_util The database util class to use.
* @param PostsToOrdersMigrationController $posts_to_cot_migrator The posts to COT migration class to use.
* @param OrderCache $cache The orders cache to use.
* @param OrderCacheController $cache_controller The orders cache controller to use.
*@internal
*/
final public function init(
OrdersTableDataStore $data_store,
DatabaseUtil $database_util,
PostsToOrdersMigrationController $posts_to_cot_migrator,
OrderCache $cache,
OrderCacheController $cache_controller ) {
final public function init( OrdersTableDataStore $data_store, DatabaseUtil $database_util, PostsToOrdersMigrationController $posts_to_cot_migrator ) {
$this->data_store = $data_store;
$this->database_util = $database_util;
$this->posts_to_cot_migrator = $posts_to_cot_migrator;
$this->cache = $cache;
$this->cache_controller = $cache_controller;
}
/**
@ -140,7 +115,6 @@ class DataSynchronizer implements BatchProcessorInterface {
* Delete the custom orders database tables.
*/
public function delete_database_tables() {
$this->cache->flush();
$table_names = $this->data_store->get_all_table_names();
foreach ( $table_names as $table_name ) {
@ -323,8 +297,6 @@ WHERE
* @param array $batch Batch details.
*/
public function process_batch( array $batch ) : void {
$this->cache_controller->temporarily_disable_orders_cache_usage();
if ( $this->custom_orders_table_is_authoritative() ) {
foreach ( $batch as $id ) {
$order = wc_get_order( $id );
@ -336,7 +308,6 @@ WHERE
}
if ( 0 === $this->get_total_pending_count() ) {
$this->cleanup_synchronization_state();
$this->cache_controller->maybe_restore_orders_cache_usage();
}
}

View File

@ -7,6 +7,7 @@ namespace Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders;
use Automattic\WooCommerce\DataBase\Migrations\CustomOrderTable\CLIRunner;
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
use Automattic\WooCommerce\Internal\DependencyManagement\AbstractServiceProvider;
/**
@ -24,6 +25,7 @@ class COTMigrationServiceProvider extends AbstractServiceProvider {
protected $provides = array(
PostsToOrdersMigrationController::class,
CLIRunner::class,
DataSynchronizer::class,
);
/**
@ -35,6 +37,5 @@ class COTMigrationServiceProvider extends AbstractServiceProvider {
*/
public function register() {
$this->share( PostsToOrdersMigrationController::class );
$this->share( CLIRunner::class );
}
}

View File

@ -6,9 +6,6 @@
namespace Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders;
use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Caches\OrderCache;
use Automattic\WooCommerce\Caches\OrderCacheController;
use Automattic\WooCommerce\Caching\TransientsEngine;
use Automattic\WooCommerce\DataBase\Migrations\CustomOrderTable\CLIRunner;
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
use Automattic\WooCommerce\Internal\BatchProcessing\BatchProcessingController;
@ -38,8 +35,6 @@ class OrdersDataStoreServiceProvider extends AbstractServiceProvider {
CLIRunner::class,
OrdersTableDataStoreMeta::class,
OrdersTableRefundDataStore::class,
OrderCache::class,
OrderCacheController::class,
);
/**
@ -49,18 +44,8 @@ class OrdersDataStoreServiceProvider extends AbstractServiceProvider {
$this->share( OrdersTableDataStoreMeta::class );
$this->share( OrdersTableDataStore::class )->addArguments( array( OrdersTableDataStoreMeta::class, DatabaseUtil::class ) );
$this->share( DataSynchronizer::class )->addArguments(
array(
OrdersTableDataStore::class,
DatabaseUtil::class,
PostsToOrdersMigrationController::class,
OrderCache::class,
OrderCacheController::class,
)
);
$this->share( DataSynchronizer::class )->addArguments( array( OrdersTableDataStore::class, DatabaseUtil::class, PostsToOrdersMigrationController::class ) );
$this->share( OrdersTableRefundDataStore::class )->addArguments( array( OrdersTableDataStoreMeta::class, DatabaseUtil::class ) );
$this->share( OrderCache::class )->addArgument( TransientsEngine::class );
$this->share( OrderCacheController::class )->addArguments( array( OrderCache::class, FeaturesController::class ) );
$this->share( CustomOrdersTableController::class )->addArguments(
array(
OrdersTableDataStore::class,
@ -68,8 +53,6 @@ class OrdersDataStoreServiceProvider extends AbstractServiceProvider {
OrdersTableRefundDataStore::class,
BatchProcessingController::class,
FeaturesController::class,
OrderCache::class,
OrderCacheController::class,
)
);
if ( Constants::is_defined( 'WP_CLI' ) && WP_CLI ) {

View File

@ -7,7 +7,6 @@ namespace Automattic\WooCommerce\Internal\Features;
use Automattic\WooCommerce\Internal\Admin\Analytics;
use Automattic\WooCommerce\Admin\Features\Navigation\Init;
use Automattic\WooCommerce\Caches\OrderCacheController;
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
use Automattic\WooCommerce\Proxies\LegacyProxy;
use Automattic\WooCommerce\Utilities\ArrayUtil;
@ -64,21 +63,16 @@ class FeaturesController {
'is_experimental' => false,
'enabled_by_default' => true,
),
'new_navigation' => array(
'new_navigation' => array(
'name' => __( 'Navigation', 'woocommerce' ),
'description' => __( 'Adds the new WooCommerce navigation experience to the dashboard', 'woocommerce' ),
'is_experimental' => false,
),
'custom_order_tables' => array(
'custom_order_tables' => array(
'name' => __( 'Custom order tables', 'woocommerce' ),
'description' => __( 'Enable the custom orders tables feature (still in development)', 'woocommerce' ),
'is_experimental' => true,
),
OrderCacheController::FEATURE_NAME => array(
'name' => __( 'Orders cache', 'woocommerce' ),
'description' => __( 'Enable the usage of a cache for shop orders', 'woocommerce' ),
'is_experimental' => true,
),
);
$this->init_features( $features );

View File

@ -5,10 +5,8 @@
namespace Automattic\WooCommerce\Utilities;
use Automattic\WooCommerce\Caches\OrderCacheController;
use Automattic\WooCommerce\Internal\Admin\Orders\PageController;
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\Utilities\COTMigrationUtil;
use WC_Order;
use WP_Post;
@ -37,15 +35,6 @@ final class OrderUtil {
return wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled();
}
/**
* Helper function to get whether the orders cache should be used or not.
*
* @return bool True if the orders cache should be used, false otherwise.
*/
public static function orders_cache_usage_is_enabled() : bool {
return wc_get_container()->get( OrderCacheController::class )->orders_cache_usage_is_enabled();
}
/**
* Checks if posts and order custom table sync is enabled and there are no pending orders.
*

View File

@ -230,9 +230,8 @@ class WC_REST_Orders_Controller_Tests extends WC_REST_Unit_Test_Case {
$order = new \WC_Order();
$order->set_status( 'completed' );
$order->save();
$order_id = $order->get_id();
$request = new \WP_REST_Request( 'DELETE', '/wc/v3/orders/' . $order_id );
$request = new \WP_REST_Request( 'DELETE', '/wc/v3/orders/' . $order->get_id() );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
@ -240,13 +239,13 @@ class WC_REST_Orders_Controller_Tests extends WC_REST_Unit_Test_Case {
// Check that the response includes order data from the order (before deletion).
$data = $response->get_data();
$this->assertArrayHasKey( 'id', $data );
$this->assertEquals( $data['id'], $order_id );
$this->assertEquals( $data['id'], $order->get_id() );
$this->assertEquals( 'completed', $data['status'] );
wp_cache_flush();
// Check the order was actually deleted.
$order = wc_get_order( $order_id );
$order = wc_get_order( $order->get_id() );
$this->assertEquals( 'trash', $order->get_status( 'edit' ) );
}

View File

@ -94,7 +94,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
$this->expectException( CacheException::class );
$this->expectExceptionMessage( "Can't cache a null value" );
$this->sut->set( null );
$this->sut->set( 'the_id', null );
}
/**
@ -104,7 +104,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
$this->expectException( CacheException::class );
$this->expectExceptionMessage( "Can't cache a non-object, non-array value" );
$this->sut->set( 1234 );
$this->sut->set( 'the_id', 1234 );
}
/**
@ -114,7 +114,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
$this->expectException( CacheException::class );
$this->expectExceptionMessage( "Object id must be an int, a string, or null for 'set'" );
$this->sut->set( array( 'foo' ), array( 1, 2 ) );
$this->sut->set( array( 1, 2 ), array( 'foo' ) );
}
/**
@ -130,7 +130,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
$this->expectException( CacheException::class );
$this->expectExceptionMessage( 'Invalid expiration value, must be ObjectCache::DEFAULT_EXPIRATION or a value between 1 and ObjectCache::MAX_EXPIRATION' );
$this->sut->set( array( 'foo' ), 'the_id', $expiration );
$this->sut->set( 'the_id', array( 'foo' ), $expiration );
}
/**
@ -139,7 +139,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
public function try_set_when_cache_engine_fails() {
$this->cache_engine->caching_succeeds = false;
$result = $this->sut->set( array( 'foo' ), 'the_id' );
$result = $this->sut->set( 'the_id', array( 'foo' ) );
$this->assertFalse( $result );
}
@ -148,7 +148,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
*/
public function test_set_new_object_with_id_caches_with_expected_key() {
$object = array( 'foo' );
$result = $this->sut->set( $object, 'the_id' );
$result = $this->sut->set( 'the_id', $object );
$this->assertTrue( $result );
@ -165,9 +165,9 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
*/
public function test_setting_two_objects_result_in_same_prefix() {
$object_1 = array( 'foo' );
$this->sut->set( $object_1, 'the_id_1' );
$this->sut->set( 'the_id_1', $object_1 );
$object_2 = array( 1, 2, 3, 4 );
$this->sut->set( $object_2, 9999 );
$this->sut->set( 9999, $object_2 );
$prefix = 'woocommerce_object_cache|the_type|random_1|';
@ -183,7 +183,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
* @testdox 'set' uses the default expiration value if no explicit value is passed.
*/
public function test_set_with_default_expiration() {
$this->sut->set( array( 'foo' ), 'the_id' );
$this->sut->set( 'the_id', array( 'foo' ) );
$this->assertEquals( $this->sut->get_default_expiration_value(), $this->cache_engine->last_expiration );
}
@ -191,7 +191,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
* @testdox 'set' uses the explicitly passed expiration value.
*/
public function test_set_with_explicit_expiration() {
$this->sut->set( array( 'foo' ), 'the_id', 1234 );
$this->sut->set( 'the_id', array( 'foo' ), 1234 );
$this->assertEquals( 1234, $this->cache_engine->last_expiration );
}
@ -202,7 +202,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
$this->expectException( CacheException::class );
$this->expectExceptionMessage( "Null id supplied and the cache class doesn't implement get_object_id" );
$this->sut->set( array( 'foo' ) );
$this->sut->set( null, array( 'foo' ) );
}
/**
@ -227,88 +227,11 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
// phpcs:enable Squiz.Commenting
$sut->set( array( 'id' => 1234 ) );
$sut->set( null, array( 'id' => 1234 ) );
$this->assertEquals( 'woocommerce_object_cache|the_type|random|1235', array_keys( $this->cache_engine->cache )[0] );
}
/**
* @testdox 'update_if_cached' does nothing if no object is cached with the passed (or obtained) id.
*
* @testWith [1234]
* [null]
*
* @param ?int $id Id to pass to update_if_cached.
*/
public function test_update_if_cached_does_nothing_for_not_cached_id( ?int $id ) {
// phpcs:disable Squiz.Commenting
$sut = new class() extends ObjectCache {
public function get_object_type(): string {
return 'the_type';
}
protected function get_object_id( $object ) {
return $object['id'];
}
};
// phpcs:enable Squiz.Commenting
$result = $sut->update_if_cached( array( 'id' => 1234 ), $id );
$this->assertFalse( $result );
$this->assertEmpty( $this->cache_engine->cache );
}
/**
* @testdox 'update_if_cached' updates an already cached object the same way as 'set'.
*
* @testWith [1234]
* [null]
*
* @param ?int $id Id to pass to update_if_cached.
*/
public function test_update_if_cached_updates_already_cached_object( ?int $id ) {
// phpcs:disable Squiz.Commenting
$sut = new class() extends ObjectCache {
public function get_object_type(): string {
return 'the_type';
}
protected function get_object_id( $object ) {
return $object['id'];
}
protected function get_random_string(): string {
return 'random';
}
};
// phpcs:enable Squiz.Commenting
$sut->set( array( 'id' => 1234 ), $id );
$this->assertEquals( 'woocommerce_object_cache|the_type|random|1234', array_keys( $this->cache_engine->cache )[0] );
$new_value = array(
'id' => 1234,
'foo' => 'bar',
);
$result = $sut->update_if_cached( $new_value, $id );
$this->assertTrue( $result );
$this->assertEquals( $this->cache_engine->cache['woocommerce_object_cache|the_type|random|1234'], array( 'data' => $new_value ) );
}
/**
* @testdox 'update_if_cached' throws an exception if no object id is passed and the class doesn't implement 'get_object_id'.
*/
public function test_update_if_cached_null_id_without_id_retrieval_implementation() {
$this->expectException( CacheException::class );
$this->expectExceptionMessage( "Null id supplied and the cache class doesn't implement get_object_id" );
$this->sut->update_if_cached( array( 'foo' ) );
}
/**
* @testdox 'set' caches the value returned by 'serialize'.
*/
@ -329,7 +252,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
// phpcs:enable Squiz.Commenting
$sut->set( $object, 1234 );
$sut->set( 1234, $object );
$cached = array_values( $this->cache_engine->cache )[0];
$expected = array( 'the_data' => $object );
@ -346,7 +269,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
*/
public function test_set_with_custom_serialization_that_returns_errors( int $errors_count ) {
$exception = null;
$errors = $errors_count === 1 ? array( 'Foo failed' ) : array( 'Foo failed', 'Bar failed' );
$errors = 1 === $errors_count ? array( 'Foo failed' ) : array( 'Foo failed', 'Bar failed' );
$object = array( 'foo' );
// phpcs:disable Squiz.Commenting
@ -370,13 +293,13 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
// phpcs:enable Squiz.Commenting
try {
$sut->set( $object, 1234 );
$sut->set( 1234, $object );
} catch ( CacheException $thrown ) {
$exception = $thrown;
}
$expected_message = 'Object validation/serialization failed';
if ( $errors_count === 1 ) {
if ( 1 === $errors_count ) {
$expected_message .= ': Foo failed';
}
$this->assertEquals( $expected_message, $exception->getMessage() );
@ -420,7 +343,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
*/
public function test_try_getting_previously_cached_object() {
$object = array( 'foo' );
$this->sut->set( $object, 'the_id' );
$this->sut->set( 'the_id', $object );
$result = $this->sut->get( 'the_id' );
$this->assertEquals( $object, $result );
@ -542,7 +465,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
// phpcs:enable Squiz.Commenting
$sut->set( array( 1, 2 ), 'the_id' );
$sut->set( 'the_id', array( 1, 2 ) );
$result = $sut->get( 'the_id' );
$expected = array( 1, 2, 3 );
@ -553,8 +476,8 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
* @testdox 'remove' removes a cached object and returns true, or returns false if there's no cached object under the passed id.
*/
public function test_remove() {
$this->sut->set( array( 'foo' ), 'the_id_1' );
$this->sut->set( array( 'bar' ), 'the_id_2' );
$this->sut->set( 'the_id_1', array( 'foo' ) );
$this->sut->set( 'the_id_2', array( 'bar' ) );
$result_1 = $this->sut->remove( 'the_id_1' );
$result_2 = $this->sut->remove( 'the_id_X' );
@ -570,12 +493,12 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
* @testdox 'flush' deletes the stored cache key prefix, effectively rendering the cached objects inaccessible.
*/
public function test_flush() {
$this->sut->set( array( 'foo' ), 'the_id' );
$this->sut->set( 'the_id', array( 'foo' ) );
$this->sut->flush();
$this->assertFalse( get_option( 'wp_object_cache_key_prefix_the_type' ) );
$this->sut->set( array( 'bar' ), 'the_id_2' );
$this->sut->set( 'the_id_2', array( 'bar' ) );
$expected_new_prefix = 'woocommerce_object_cache|the_type|random_2|';
$this->assertEquals( $expected_new_prefix, get_option( 'wp_object_cache_key_prefix_the_type' ) );
@ -611,7 +534,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
// phpcs:enable Squiz.Commenting
$object = array( 'foo' );
$sut->set( $object, 'the_id' );
$sut->set( 'the_id', $object );
$expected_cached = array( 'data' => $object );
$this->assertEquals( $expected_cached, array_values( $engine->cache )[0] );
@ -637,7 +560,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
);
$object = array( 'foo' );
$this->sut->set( $object, 'the_id' );
$this->sut->set( 'the_id', $object );
$expected_cached = array( 'data' => $object );
$this->assertEquals( $expected_cached, array_values( $engine->cache )[0] );
@ -667,7 +590,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
);
$object = array( 'fizz' );
$this->sut->set( $object, 'the_id' );
$this->sut->set( 'the_id', $object );
$expected_cached = array(
'data' => $object,
@ -703,7 +626,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
3
);
$this->sut->set( $original_object, 'the_id' );
$this->sut->set( 'the_id', $original_object );
$retrieved_object = $this->sut->get( 'the_id' );
$this->assertEquals( $replacement_object, $retrieved_object );
@ -735,7 +658,7 @@ class ObjectCacheTest extends \WC_Unit_Test_Case {
2
);
$this->sut->set( array( 'foo' ), 'the_id' );
$this->sut->set( 'the_id', array( 'foo' ) );
$this->sut->remove( $operation_succeeds ? 'the_id' : 'INVALID_ID' );
$this->assertEquals( $operation_succeeds ? 'the_id' : 'INVALID_ID', $id_passed_to_action );