Skip to content

feat: rename the collaboration primary key to collaboration_id - #110

Merged
josephfusco merged 3 commits into
mainfrom
fix/collaboration-primary-key
Sep 5, 2026
Merged

feat: rename the collaboration primary key to collaboration_id#110
josephfusco merged 3 commits into
mainfrom
fix/collaboration-primary-key

Conversation

@josephfusco

@josephfusco josephfusco commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Renames wp_collaboration.id to collaboration_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_version has been written since 0.1.0 and never read back. sync_storage_upgrade_table() on plugins_loaded is 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.

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>
@josephfusco
josephfusco force-pushed the fix/collaboration-primary-key branch from 62c2f53 to e3f0b9c Compare September 4, 2026 14:47
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

🛝 WordPress Playgrounds

Built from 9f9f1d5

Solo 5 collaborators 40 collaborators
Launch solo Launch with 5 collaborators Launch with 40 collaborators

@codecov

codecov Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 58.92857% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.09%. Comparing base (c122cfc) to head (9f9f1d5).

Files with missing lines Patch % Lines
lib/store/schema.php 55.76% 23 Missing ⚠️
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     
Flag Coverage Δ
multisite 71.09% <58.92%> (-2.41%) ⬇️
phpunit 66.14% <58.92%> (-1.64%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@josephfusco
josephfusco marked this pull request as ready for review September 4, 2026 14:57
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

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 props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: josephfusco <joefusco@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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, and date_gmt, and uses a non-null type, while this table stores nullable type plus timestamp. 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.

Comment thread lib/install.php
Comment thread lib/store/schema.php
Comment thread lib/store/schema.php Outdated
Comment thread lib/store/schema.php Outdated
Comment thread lib/store/schema.php Outdated
Comment thread tests/test-upgrade.php
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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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 with 2, 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 old id schema is therefore marked as version 2 and every later request skips the migration while store queries use collaboration_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 LIKE treats _ 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 following SHOW COLUMNS emits 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 when collaboration_id is 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

Comment thread tests/e2e/polling-cost.spec.ts
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>
github-actions Bot added a commit that referenced this pull request Sep 5, 2026
@josephfusco
josephfusco merged commit 1f76ff6 into main Sep 5, 2026
19 of 22 checks passed
@josephfusco
josephfusco deleted the fix/collaboration-primary-key branch September 5, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants