feat: rename the collaboration primary key to collaboration_id - #110
Conversation
8912b7a to
62c2f53
Compare
Matches the column-prefix convention core applies to its own tables and the definition in WordPress/wordpress-develop#11256, leaving the update log structurally identical to the one core proposes. Renaming it needed an upgrade path first. Activation hooks do not fire on a plugin update, so a schema change reachable only from sync_storage_install_site() lands on new installs and no existing one; sync_storage_db_version has been written since 0.1.0 and never read back. sync_storage_upgrade_table() now runs on plugins_loaded and does the read. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
62c2f53 to
e3f0b9c
Compare
🛝 WordPress PlaygroundsBuilt from 9f9f1d5
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #110 +/- ##
============================================
- Coverage 73.49% 71.09% -2.41%
- Complexity 0 52 +52
============================================
Files 11 11
Lines 332 384 +52
============================================
+ Hits 244 273 +29
- Misses 88 111 +23
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
🟡 Changes recommended
Critical migration paths can record version 2 without successfully applying the schema rename.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Renames the collaboration primary key to collaboration_id and adds schema migration support for existing installations.
Changes:
- Updates the schema and queries for the renamed key.
- Adds versioned migration logic and tests.
- Updates documentation and static-analysis configuration.
File summaries
| File | Review |
|---|---|
tests/test-upgrade.php |
Adds migration tests. Moderate (1 vote): The test does not independently verify preservation of the AUTO_INCREMENT counter above MAX(id). |
tests/test-sync-storage-provider.php |
Updates test queries for the renamed column. No issues identified. |
tests/test-cleanup.php |
Uses the canonical schema setup helper. No issues identified. |
sync-storage.php |
Increments the database schema version. No issues identified. |
README.md |
Documents the renamed key and migration behavior. No issues identified. |
phpstan/bootstrap.php |
Synchronizes the PHPStan schema version. No issues identified. |
lib/store/schema.php |
Defines and migrates the renamed column. Critical (1 vote): Failed renames can still persist version 2. Moderate (2 votes): Newer installed versions can be downgraded. Moderate (2 votes): Concurrent renames are unsafe. Moderate (2 votes): The table existence check does not escape SQL LIKE wildcards. Nit (1 vote): The core-compatibility claim should be narrowed because the remaining schema is not row-compatible. |
lib/store/class-sync-storage-store.php |
Updates queries while preserving the public cursor shape. No issues identified. |
lib/install.php |
Registers automatic upgrades. Critical (1 vote): Activation can bypass the upgrader and incorrectly record version 2 against the old schema. |
Review details
Suppressed comments (1)
lib/store/schema.php:42
- The referenced core proposal is not row-compatible with this schema: it requires
client_id,user_id, anddate_gmt, and uses a non-nulltype, while this table stores nullabletypeplustimestamp. The rename aligns the key name, but it does not by itself make these rows readable by that implementation, so the compatibility claim should be removed or narrowed.
* WordPress/wordpress-develop#11256. With the table name and
* $wpdb->collaboration, that leaves a site's rows readable by a core
* implementation.
- Files reviewed: 9/9 changed files
- Comments generated: 6
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Renames the e2e cost mu-plugin to sync-cost-counter and adds handler and InnoDB counters alongside the query count: a query that reads one row and one that scans a growing room count the same otherwise. The new assertion checks writes stay flat as room size grows, controlling for INSERT vs. the ON DUPLICATE KEY UPDATE branch, which move MySQL's handler counters on their own. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
The migration has unresolved failure, concurrency, version-handling, and table-detection issues, with incomplete test assertions.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (5)
lib/store/schema.php:91
- A stored schema version from a newer plugin release (for example after a rollback) also enters this upgrade path because the check requires equality.
sync_storage_create_table()can then reconcile the table against an older definition and overwrite the option with2, so a later re-upgrade may rerun migrations against an already-newer schema. Treat versions greater than the code's version as a no-op too.
if ( WP_SYNC_STORAGE_DB_VERSION === $installed ) {
return;
}
lib/store/schema.php:147
- The ALTER result is ignored, and the caller subsequently invokes
sync_storage_create_table(), which unconditionally writes the current DB version. If the rename fails (for example due to a lock timeout or missing ALTER privilege), the oldidschema is therefore marked as version 2 and every later request skips the migration while store queries usecollaboration_id. Propagate failure or verify the final column exists before recording the new version; only log the rename after that verification succeeds.
$wpdb->query(
"ALTER TABLE {$wpdb->collaboration}
CHANGE `id` `collaboration_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT"
);
lib/store/schema.php:130
SHOW TABLES LIKEtreats_and%in the WordPress table prefix as wildcards. If the collaboration table is absent but another table matches that pattern, this check incorrectly proceeds and the followingSHOW COLUMNSemits the missing-table error this branch is intended to avoid. Escape the table name as a LIKE literal.
if ( ! $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->collaboration ) ) ) {
lib/store/schema.php:137
- This check is not atomic with the ALTER below. Two first requests can both observe
id; after one renames it, the other's queued ALTER fails with “Unknown column 'id'” rather than becoming the no-op described above. Serialize the migration or handle an ALTER failure by re-reading the columns and accepting it only whencollaboration_idis present.
// Two requests racing here produce one ALTER and one no-op, rather than an
// unknown column error on the second.
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
if ( ! $wpdb->get_var( "SHOW COLUMNS FROM {$wpdb->collaboration} LIKE 'id'" ) ) {
tests/test-upgrade.php:145
- This test does not exercise preservation of the AUTO_INCREMENT counter: with one retained row, even a reset counter advances to
MAX(id) + 1, so the assertion still passes. Set the table's next AUTO_INCREMENT value above the current maximum before upgrading, then assert that the next append receives that exact value.
$last = (int) $wpdb->insert_id;
sync_storage_upgrade_table();
$this->assertGreaterThan(
$last,
Sync_Storage_Store::append( 'widget/sidebar:main', 'second' )
- Files reviewed: 13/13 changed files
- Comments generated: 1
- Review effort level: Balanced
Copilot's review of this PR found two ways the db_version option could be set to 2 without collaboration_id actually existing: activation calling sync_storage_create_table() directly instead of the guarded upgrade path (so an update-while-deactivated site skips the rename dbDelta can't express), and the version being written unconditionally regardless of whether the ALTER or dbDelta succeeded. Both are now checked before the version is persisted. Also from that review: the version check is now >= instead of ===, the SHOW TABLES check escapes the table prefix, a losing request in a concurrent-migration race no longer logs a false success, the autoincrement test empties the table first so it can't pass against a reset counter, and the relay e2e test checks write-side handler counters alongside query count. Closes #116, #117, #118, #119, #120, #122. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Renames
wp_collaboration.idtocollaboration_id, matching core's column-prefix convention and the table definition in wordpress-develop#11256. This was the last structural difference between this plugin's update log and core's, and closes the remaining sync-storage item on WordPress/presence-api#444.The rename needed an upgrade path first. Activation hooks do not fire on a plugin update, so a schema change reachable only from
sync_storage_install_site()would have reached new installs and no existing one;sync_storage_db_versionhas been written since 0.1.0 and never read back.sync_storage_upgrade_table()onplugins_loadedis that read, and since dbDelta cannot express a rename, the ALTER is issued directly ahead of it.Verified against a live wp-env site holding a v1 table: 388 rows and
MAX(id)577 both preserved, all three indexes carried to the new column name, the next insert continued at 578, and the 12 editor e2e tests pass against the migrated table. Nine new PHPUnit tests build a frozen v1 table and migrate it.