fix(2meet-data-optimizer): resync flat rows from native meta after each write

- dual_write / shadow_read no longer write flat in the update_/add_/
  delete_{type}_metadata pre-filters, before WP decides whether native
  changes at all. added_/updated_/deleted_{type}_meta (priority 1) call
  TMDO_Hook_Bus::sync_from_native(), which copies the entity's first native
  row (plain SQL, NULL when gone) into flat. Flat now follows native when WP
  skips (same value), refuses (non-matching prev_value, add $unique on an
  existing key) or deletes (also delete_all: touched IDs are collected from
  the meta IDs in delete_{type}_meta), and a flat value left stale by a
  direct SQL write heals on the next write.
- update_metadata_by_mid key changes: the old key is remembered in
  update_{type}_metadata_by_mid and re-synced too.
- wpdo_after_write / wpdo_after_delete fire from the sync with the same
  arguments; aeav_only keeps the pre-filter short-circuit unchanged.
- $internal_ops lock key includes the entity type (user 5 ≠ post 5).
- Live suite resync: 4 entities × 2 modes × 3 scenarios (old code: 16 of
  24 FAIL); integration: pre-filter leaves flat to the sync, delete_all
  re-syncs every touched user.
- Verify: live resync + shadow_write + serialized + zero_side_effect 33/33
  PASS; unit 687 OK, integration 485 OK, phpcs (phpcs.xml) 0, stan OK
- PR: PR-057
This commit is contained in:
2026-09-26 19:13:02 +08:00
parent 781f171770
commit 77e338f9c3
6 changed files with 470 additions and 31 deletions
+25
View File
@@ -113,6 +113,29 @@ final class TMDO_Live_Fixtures {
return (int) $id;
}
/**
* Create a throwaway comment (on a throwaway post of $post_type).
*
* @param string $post_type Post type of the parent post.
* @param string $comment_type Comment type.
*/
public static function comment( string $post_type, string $comment_type = 'comment' ): int {
$post_id = self::post( $post_type );
$id = wp_insert_comment(
array(
'comment_post_ID' => $post_id,
'comment_content' => 'tmdo-live',
'comment_type' => $comment_type,
'comment_approved' => 1,
)
);
if ( ! $id ) {
throw new TMDO_Live_Failure( 'fixture comment could not be created' );
}
self::$created[] = array( 'comment', (int) $id );
return (int) $id;
}
/**
* Native meta values for a key, read with SQL (no filters, no cache).
*
@@ -191,6 +214,8 @@ final class TMDO_Live_Fixtures {
wp_delete_term( $c[1], $c[2] );
} elseif ( 'post' === $c[0] ) {
wp_delete_post( $c[1], true );
} elseif ( 'comment' === $c[0] ) {
wp_delete_comment( $c[1], true );
}
}
self::$created = array();