Skip to content

WPB-29581: migrate invitations to PostGreSQL - #5649

Open
blackheaven wants to merge 5 commits into
developfrom
gdifolco/WPB-29581-migration-postgres-invitations
Open

blackheaven wants to merge 5 commits into
developfrom
gdifolco/WPB-29581-migration-postgres-invitations

Conversation

@blackheaven

Copy link
Copy Markdown
Contributor

https://wearezeta.atlassian.net/browse/WPB-29581

Checklist

  • Add a new entry in an appropriate subdirectory of changelog.d
  • Read and follow the PR guidelines

@blackheaven
blackheaven requested review from a team as code owners October 23, 2026 13:31
@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Oct 23, 2026
@blackheaven
blackheaven force-pushed the gdifolco/WPB-29581-migration-postgres-invitations branch 2 times, most recently from 90ba02c to 9dbccef Compare October 23, 2026 13:59
@blackheaven
blackheaven added this pull request to stack #5665 October 26, 2026 17:35
@blackheaven
blackheaven force-pushed the gdifolco/WPB-29581-migration-postgres-invitations branch from 9dbccef to 8d5f523 Compare October 29, 2026 15:00

@akshaymankar akshaymankar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Partial review. I haven't looked deeper into queries and DB design yet.

Comment thread libs/wire-api/src/Wire/API/Team/Role.hs Resolved
@blackheaven
blackheaven force-pushed the gdifolco/WPB-29581-migration-postgres-invitations branch from a20a811 to 06cbb69 Compare November 4, 2026 11:29
@akshaymankar
akshaymankar self-requested a review November 5, 2026 09:18
@blackheaven
blackheaven force-pushed the gdifolco/WPB-29581-migration-postgres-invitations branch from 06cbb69 to b6b9790 Compare November 5, 2026 12:09
@blackheaven

Copy link
Copy Markdown
Contributor Author

Addressed the review asks, mirroring the connections migration (#5685):

  • No unlocked bulk copy: the copy loop now works per team (SELECT DISTINCT team scan). For each team it takes the exclusive per-team migration lock (withExclusiveMigrationLockAndTimeout, shared migrationOptions.timeout), re-reads the team's team_invitation and team_scim_pending_user_email rows from Cassandra inside the lock, upserts them into Postgres, and — only if every row copied without error — deletes the copied Cassandra partitions (including the denormalized team_invitation_info / team_invitation_email index rows) in the same locked section. A failed row leaves the team untouched and the loop retries the team on the next pass; the SELECT DISTINCT team re-scan is the crash recovery.
  • No unserialized writes: every mutation in migration-to-postgresql mode (insert, delete invitation, delete-all, SCIM pending-user insert/delete) is mirrored to both stores under the shared per-team lock, so nothing can resurrect a deleted invitation or land in Cassandra only after the copier cleared its partition.
  • Reads route through Postgres under a shared lock: each read takes the shared per-team lock, checks row presence in Postgres (filterMigrated), and serves the team from Postgres or Cassandra accordingly — the team is never read from a half-deleted Cassandra partition or a half-populated copy. Global email/code lookups consult both stores and dedupe.
  • Residual windows are accepted and documented in the Wire.InvitationStore.DualWrite haddock (mirroring-insert failure after partition clear; presence-based routing for a team whose copy is still retrying), same as the connections migration accepted.
  • Integration test updated (Test.Migration.Invitations): in the worker-on phase it now asserts the P1 team's Cassandra team_invitation partition is empty after migration and that the invitation is still served via the locked Postgres read-through.

No new config keys and no schema/bookkeeping-table change: lock acquisition itself is the progress barrier, same as #5685. History cleaned (mechanical fix commits folded, branch rebased onto current develop); make c for wire-subsystems/brig/background-worker, cabal build integration, test-suite builds and make hlint-check-pr all pass.

… delete copied Cassandra partitions, route dual-mode reads through Postgres
…on copy lock; index expires_at

- New MigrationLockable (TeamId, EmailAddress) instance: its advisory key is
  the team's "team_invitation" lock, so InsertPendingScimUser /
  DeletePendingScimUser dual-writes serialize against the copy loop's
  exclusive team lock and a deleted pending-SCIM row can no longer be
  resurrected by a stale re-copy.
- team_invitation_expires_at_idx: the daily expire-team-invitations
  pg_cron DELETE scans on expires_at; the table fills fast.
- Document why insertInvitationStatement may use ON CONFLICT DO UPDATE
  (all callers hold the team migration lock).
@blackheaven
blackheaven force-pushed the gdifolco/WPB-29581-migration-postgres-invitations branch from b46def7 to 54a6474 Compare November 13, 2026 12:07

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

easy-to-review ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants