fix(2meet-data-optimizer): close the gaps in deferred table upgrades found in the 2.3 review
- a deferred group whose stored definition matches again (reverted, or upgraded by another process) goes through end_deferral() instead of staying native for good (review F2) - the tmdo_ensure_group_indexes handler upgrades deferred tables itself: with ALTERNATE_WP_CRON the event runs after init in a visitor's request (F3) - a new group table created while the entity writes to flat stays native until the drift fix has filled it from native meta; an opted-in HivePress attribute no longer routes searches to an empty table (F6) - direct_read() returns native values for a deferred group (F10); the Hook Bus ignores deferral in aeav_only, as the router does - dbDelta failures: the definition is recorded only when every column exists (schema.upgrade_failed otherwise), so a failed ALTER is retried and the group is not released onto missing columns - test bootstrap: get_metadata() reads the real meta table - Verify: SchemaUpgradeDeferralTest (6), Hook Bus direct read, integration 587, unit 703, phpcs, stan - PR: PR-114 (2.3 acceptance correctness review)
This commit is contained in:
@@ -243,6 +243,7 @@ class HookBusIntegrationTest extends TestCase {
|
||||
WPDO_Hook_Bus::sync_from_native( 'user', 4, 'first_name', 'Dora', 'update' );
|
||||
|
||||
$this->assertNull( $this->read_flat_first_name( 4 ) );
|
||||
$this->assertSame( 'Dora', WPDO_Hook_Bus::direct_read( 'user', 4, 'first_name' ), 'direct reads return the native value' );
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
|
||||
@@ -139,4 +139,39 @@ class SchemaUpgradeDeferralTest extends TestCase {
|
||||
$this->assertTrue( TMDO_Schema_Manager::is_deferred( 'user', 'sd_later' ) );
|
||||
$this->assertTrue( TMDO_Schema_Manager::is_deferred( 'post', 'sd_core' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* The definition went back to the stored one (or another process upgraded
|
||||
* the table) while the group was deferred (correctness review F2).
|
||||
*/
|
||||
public function test_a_deferred_group_whose_definition_matches_again_is_resynced_then_released(): void {
|
||||
global $wpdb;
|
||||
$current = TMDO_Schema_Manager::calculate_schema_hash( WPDO_Entity_Registry::get_group_fields( 'user', 'sd_core' ) );
|
||||
$wpdb->update( $wpdb->prefix . 'wpdo_registry_meta', array( 'schema_hash' => $current ), array( 'entity_type' => 'user', 'group_name' => 'sd_core' ) );
|
||||
update_option( TMDO_Schema_Manager::DEFERRED_OPTION, array( 'user/sd_core' => 1 ) );
|
||||
|
||||
$this->assertTrue( $this->upgrade() );
|
||||
|
||||
$this->assertTrue( TMDO_Schema_Manager::is_deferred( 'user', 'sd_core' ), 'dual_write: native until the drift fix' );
|
||||
$this->assertContains( TMDO_Drift_Check::RESYNC_HOOK, $GLOBALS['_wp_scheduled_single'] );
|
||||
|
||||
self::set_user_mode( 'disabled' );
|
||||
$this->upgrade();
|
||||
$this->assertFalse( TMDO_Schema_Manager::is_deferred( 'user', 'sd_core' ), 'no flat writes: nothing to rebuild' );
|
||||
}
|
||||
|
||||
/**
|
||||
* The cron event upgrades deferred groups itself: with ALTERNATE_WP_CRON
|
||||
* it runs inside a visitor's request, after init (correctness review F3).
|
||||
*/
|
||||
public function test_the_cron_event_handles_deferred_groups(): void {
|
||||
global $wpdb;
|
||||
$current = TMDO_Schema_Manager::calculate_schema_hash( WPDO_Entity_Registry::get_group_fields( 'user', 'sd_core' ) );
|
||||
$wpdb->update( $wpdb->prefix . 'wpdo_registry_meta', array( 'schema_hash' => $current ), array( 'entity_type' => 'user', 'group_name' => 'sd_core' ) );
|
||||
update_option( TMDO_Schema_Manager::DEFERRED_OPTION, array( 'user/sd_core' => 1 ) );
|
||||
|
||||
TMDO_Schema_Manager::ensure_pending_indexes();
|
||||
|
||||
$this->assertContains( TMDO_Drift_Check::RESYNC_HOOK, $GLOBALS['_wp_scheduled_single'] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +299,19 @@ if ( ! function_exists( 'do_action_ref_array' ) ) {
|
||||
if ( ! function_exists( 'is_admin' ) ) { function is_admin(): bool { return ! empty( $GLOBALS['_wp_is_admin'] ); } }
|
||||
if ( ! function_exists( 'is_singular' ) ) { function is_singular( $t = '' ): bool { return false; } }
|
||||
if ( ! function_exists( 'wp_doing_ajax' ) ) { function wp_doing_ajax(): bool { return false; } }
|
||||
if ( ! function_exists( 'get_metadata' ) ) {
|
||||
// Like get_metadata(): the first stored value of a key (single), read from the real meta table.
|
||||
function get_metadata( string $type, $object_id, string $key = '', bool $single = false ) {
|
||||
global $wpdb;
|
||||
$table = $wpdb->{$type . 'meta'};
|
||||
$id = 'user' === $type ? 'umeta_id' : 'meta_id';
|
||||
$value = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM `{$table}` WHERE `{$type}_id` = %d AND meta_key = %s ORDER BY `{$id}` LIMIT 1", $object_id, $key ) );
|
||||
if ( $single ) {
|
||||
return null === $value ? '' : maybe_unserialize( $value );
|
||||
}
|
||||
return null === $value ? array() : array( maybe_unserialize( $value ) );
|
||||
}
|
||||
}
|
||||
if ( ! function_exists( 'wp_next_scheduled' ) ) { function wp_next_scheduled( string $hook ): int|false { return false; } }
|
||||
if ( ! function_exists( 'wp_schedule_event' ) ) { function wp_schedule_event( int $t, string $r, string $h ): bool { return true; } }
|
||||
if ( ! function_exists( 'wp_schedule_single_event' ) ) { function wp_schedule_single_event( int $ts, string $hook ): bool { $GLOBALS['_wp_scheduled_single'][] = $hook; return true; } }
|
||||
|
||||
Reference in New Issue
Block a user