Skip to content

feat(storage): add the pending drops quarantine ledger - #1064

Draft
aparajon wants to merge 1 commit into
mainfrom
armand/pending-drops-ledger-store
Draft

feat(storage): add the pending drops quarantine ledger#1064
aparajon wants to merge 1 commit into
mainfrom
armand/pending-drops-ledger-store

Conversation

@aparajon

Copy link
Copy Markdown
Collaborator

Adds a pending_drops table and its storage accessor, so a deployment has a durable record of the tables it quarantined and can tell its own earlier rename apart from a table that vanished for some other reason.

This PR has no consumer yet and should not merge ahead of one. It is the foundation for making a re-run of the DROP phase converge on the quarantine path: that fix needs the run_id recorded here as proof, because without it a resumed apply cannot distinguish a table it renamed itself from one another actor dropped. The equivalent fix on the direct path needs no ledger and ships in #1057.

Design notes worth knowing at review time:

  • The ledger is a derived index, never an authority. Reaping still reads the target, so a lost or absent row degrades discovery rather than correctness. Support is expressed by whether rows exist, not by config.
  • Rows are keyed on (target, environment). A target alone is not a server, because the endpoint lookup is scoped by environment. The endpoint itself is re-resolved per pass and never stored.
  • LatestForTable deliberately does not filter by run id. The caller compares it, which keeps "no record at all" distinguishable from "an earlier apply's copy" — those fail closed for different reasons.
  • Terminal rows are kept. Prune only touches rows that are no longer quarantined, so a reaped row stays as evidence until it ages out.
  • original_table is varchar(64), the real table-identifier limit; at 255 the origin index exceeded MySQL's 3072-byte key limit.

Tests live in the cross-dialect parity suite, so all 14 subtests run against both MySQL and PostgreSQL.

Authored by Claude Code (claude-opus-5).

Records the tables a deployment moved into an engine's pending-drops
quarantine, in that deployment's own storage. Discovery of servers holding
expired quarantines becomes an index lookup rather than a scan, so cleanup
cost scales with drops instead of with the number of registered databases,
and a deployment that never quarantines writes no rows and no-ops by
construction.

Rows also carry the run identifier that performed the move, which is what
lets an interrupted DROP phase tell its own completed rename apart from
drift or from an earlier apply's quarantined copy.

No caller yet: the quarantine path and the reaper are wired in follow-ups.
Copilot AI lite review requested due to automatic review settings August 17, 2026 04:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a durable “pending drops” quarantine ledger to storage so a deployment can record which tables it quarantined (including the apply run_id) and later distinguish “we renamed it earlier” from “it disappeared for some other reason.” This fits into SchemaBot’s storage layer and schema bootstrap/parity testing, providing the foundation for convergent re-runs of the DROP phase on the quarantine path.

Changes:

  • Introduces pending_drops storage model/types and a PendingDropStore interface, exposed via Storage.PendingDrops().
  • Implements the SQL-backed store (Record, LatestForTable, ListExpired, ListQuarantined, SetState, Prune) in the shared sqlstore.
  • Adds MySQL/Postgres schema DDL plus cross-dialect parity tests for the new store.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pkg/storage/types.go Adds PendingDrop and PendingDropState types for the quarantine ledger.
pkg/storage/storage.go Extends the public storage API with PendingDropStore and Storage.PendingDrops().
pkg/storage/internal/sqlstore/storage.go Wires the new pendingDropStore into the sqlstore Storage implementation.
pkg/storage/internal/sqlstore/pending_drops.go Implements the SQL store for pending-drops ledger operations.
pkg/schema/mysql/pending_drops.sql Adds MySQL DDL for the pending_drops table and indexes.
pkg/schema/postgres/pending_drops.sql Adds Postgres DDL for the pending_drops table and indexes.
pkg/storage/storagetest/storagetest.go Registers the new parity suite in the storage test harness.
pkg/storage/storagetest/pending_drops.go Adds cross-dialect behavioral tests for PendingDropStore.
pkg/api/handlers_test.go Updates the storage mock to satisfy the expanded storage.Storage interface.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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