feat(2meet-data-optimizer): backfill writes made while the Hook Bus was off
- When an entity goes from disabled to dual_write / shadow_read, or the Hook Bus flag is switched on, a single WP-Cron event (tmdo_drift_resync, one per entity, 60 s later) runs drift-check --fix for the entities that keep native meta, so values written while flat was bypassed land in flat. aeav_only is never touched. - A full fix instead of the planned post_modified_gmt increment (decision 2026-09-27): meta-only writes such as WooCommerce's direct stock SQL do not bump post_modified. No wpdo_bridge_off_since. - The resync hook is cleared on deactivate / uninstall (literal name: uninstall.php does not load TMDO_Drift_Check). - Verify: DriftCheckTest resync cases (RED before); dev36 end to end with real WP-Cron: write while user disabled → miss 1 → bridge-mode user dual_write schedules tmdo_drift_resync [user] → run → drift 0. - PR: PR-074
This commit is contained in:
@@ -241,6 +241,71 @@ class DriftCheckTest extends TestCase {
|
||||
$this->assertSame( $flat, md5( wp_json_encode( $wpdb->get_results( 'SELECT * FROM `' . self::TABLE . '` ORDER BY id', ARRAY_A ) ) ) );
|
||||
}
|
||||
|
||||
// ── resync after writes bypassed flat (2.2 PR-074) ──────────────────────
|
||||
|
||||
public function test_turning_writes_on_schedules_a_fix_for_that_entity(): void {
|
||||
$this->assertSame( array( 'user' ), TMDO_Drift_Check::resync_after_mode_change( 'user', 'dual_write', 'disabled' ) );
|
||||
}
|
||||
|
||||
public function test_other_mode_changes_schedule_nothing(): void {
|
||||
$this->assertSame( array(), TMDO_Drift_Check::resync_after_mode_change( 'user', 'shadow_read', 'dual_write' ) );
|
||||
$this->assertSame( array(), TMDO_Drift_Check::resync_after_mode_change( 'user', 'aeav_only', 'shadow_read' ) );
|
||||
$this->assertSame( array(), TMDO_Drift_Check::resync_after_mode_change( 'user', 'disabled', 'dual_write' ) );
|
||||
}
|
||||
|
||||
public function test_turning_the_hook_bus_on_schedules_a_fix_for_entities_that_keep_native(): void {
|
||||
self::set_modes( array( 'post' => 'aeav_only', 'user' => 'dual_write', 'term' => 'shadow_read', 'comment' => 'disabled' ) );
|
||||
try {
|
||||
$on = TMDO_Drift_Check::resync_after_hook_bus_change( '0', '1' );
|
||||
$off = TMDO_Drift_Check::resync_after_hook_bus_change( '1', '0' );
|
||||
} finally {
|
||||
self::set_modes( null );
|
||||
}
|
||||
|
||||
$this->assertSame( array( 'user', 'term' ), $on );
|
||||
$this->assertSame( array(), $off );
|
||||
}
|
||||
|
||||
public function test_the_scheduled_fix_repairs_the_entity(): void {
|
||||
self::set_modes( array( 'post' => 'disabled', 'user' => 'dual_write', 'term' => 'disabled', 'comment' => 'disabled' ) );
|
||||
try {
|
||||
TMDO_Drift_Check::run_scheduled_fix( 'user' );
|
||||
} finally {
|
||||
self::set_modes( null );
|
||||
}
|
||||
|
||||
$status = get_option( TMDO_Drift_Check::OPTION )['user']['dc_grp'];
|
||||
$this->assertSame( 0, $status['miss'] + $status['diff'] + $status['extra'] );
|
||||
}
|
||||
|
||||
public function test_the_scheduled_fix_leaves_aeav_only_alone(): void {
|
||||
self::set_modes( array( 'post' => 'disabled', 'user' => 'aeav_only', 'term' => 'disabled', 'comment' => 'disabled' ) );
|
||||
try {
|
||||
TMDO_Drift_Check::run_scheduled_fix( 'user' );
|
||||
} finally {
|
||||
self::set_modes( null );
|
||||
}
|
||||
|
||||
$this->assertFalse( get_option( TMDO_Drift_Check::OPTION ) );
|
||||
$this->assertSame( 'B', $this->flat_row( 2 )['name'], 'flat untouched' );
|
||||
}
|
||||
|
||||
public function test_the_resync_triggers_are_hooked(): void {
|
||||
$source = (string) file_get_contents( WPDO_PLUGIN_DIR . 'includes/class-tmdo-core.php' );
|
||||
|
||||
foreach ( array(
|
||||
"add_action( 'wpdo_bridge_mode_changed', array( 'TMDO_Drift_Check', 'on_mode_changed' ), 10, 3 );",
|
||||
"add_action( 'update_option_' . TMDO_Hook_Bus_Bridge::OPTION, array( 'TMDO_Drift_Check', 'on_hook_bus_toggled' ), 10, 2 );",
|
||||
"add_action( 'add_option_' . TMDO_Hook_Bus_Bridge::OPTION, array( 'TMDO_Drift_Check', 'on_hook_bus_added' ), 10, 2 );",
|
||||
"add_action( TMDO_Drift_Check::RESYNC_HOOK, array( 'TMDO_Drift_Check', 'run_scheduled_fix' ) );",
|
||||
) as $line ) {
|
||||
$this->assertStringContainsString( $line, $source );
|
||||
}
|
||||
// Literal: uninstall.php does not load TMDO_Drift_Check.
|
||||
$installer = (string) file_get_contents( WPDO_PLUGIN_DIR . 'includes/class-tmdo-installer.php' );
|
||||
$this->assertSame( 2, substr_count( $installer, "'" . TMDO_Drift_Check::RESYNC_HOOK . "'" ), 'cleared on deactivate and uninstall' );
|
||||
}
|
||||
|
||||
public function test_the_daily_tick_runs_on_the_daily_health_check_hook(): void {
|
||||
$source = (string) file_get_contents( WPDO_PLUGIN_DIR . 'includes/class-tmdo-core.php' );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user