Skip to content

chore: 3.1.2 remove the claim protocol - #239

Merged
abnegate merged 8 commits into
mainfrom
qlt-fix/mg-cleanup
Oct 14, 2026
Merged

abnegate merged 8 commits into
mainfrom
qlt-fix/mg-cleanup

Conversation

@abnegate

Copy link
Copy Markdown
Member

What

Patch release 3.1.2: removes the migration claim protocol that 3.0.0–3.1.1 added for appwrite's V26 claim, returning the Appwrite destination to the 2.x status-only lifecycle on the database 8 API.

  • Provisioning ownership fencing removed: ProvisioningOwner, the owner / getRecoverableOwner / provisioningLease destination parameters, and the CLI flags --migration-id, --migration-attempt-id, --recover-* and --help. An incomplete (provisioning / failed) database is recovered by the next run at once, under any OnDuplicate.
  • Abort mechanism removed: Exception\Aborted, the Transfer latch, Destination::markAborted() and the 52 pasted catch (Aborted) blocks.
  • Finalization back in run(): Exception\Finalization is gone; a plain run() marks provisioned databases ready and sweeps orphans, as in 2.1.0.
  • Requires utopia-php/database ^8.1.2 (namespaced Attribute\Update / Relationship\Update); minimum-stability: stable.

Concurrency contract (breaking): without the fence, callers must serialise migrations per destination project. Details and every removed API are in CHANGELOG ## 3.1.2.

Tests

Fail-first: incomplete databases recovered immediately (under every duplicate policy), run() alone marks databases ready. Unit suite, PHPStan level 3 and Pint pass locally.

🤖 Generated with Claude Code

abnegate and others added 8 commits October 14, 2026 17:55
The ownership fence existed only to serve Appwrite's V26 migration claim
protocol, which is being removed everywhere. Without that caller nothing
can attest a terminal owner, so the fence only refused work: an ownerless
`provisioning` or `failed` database waited out a 24-hour lease before any
retry could recover it.

The destination returns to the 2.x status-only lifecycle on the 8.x API:
an incomplete database is overwritten and its backing collection
recreated on the next run, and status flips are plain updates again. The
non-fencing fixes made since 2.x stay (recovery under OnDuplicate::Fail,
marking a database failed when its reload misses), as does the
finalization in success(), which is removed separately.

Breaking: ProvisioningOwner, the owner, getRecoverableOwner and
provisioningLease constructor arguments, DEFAULT_PROVISIONING_LEASE and
the CLI's --migration-id, --migration-attempt-id, --recover-* and --help
options are gone. ProvisioningOwnerTest and the e2e
AppwriteDatabaseConcurrencyTest covered only the fence and are deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n() again

The claim protocol is gone, so nothing needs a caller to persist a claim
between the transfer and its terminal side effects. Deferring
finalization to success() only left every consumer that kept run() as
its last call with databases stuck in provisioning, and the reporting
added to catch that (cleanUp() and rerun errors, Exception\Finalization)
existed only to paper over the split. run() flips provisioned databases
to ready and then sweeps overwrite orphans, exactly as 2.x did, and
success(), error() and cleanUp() are plain hooks again.

Exception\Aborted served only appwrite's Superseded, which is being
deleted; the library never threw it. The Transfer latch,
Destination::markAborted() and the 52 pasted catch-and-rethrow blocks in
the sources go with it, so a callback exception is handled by each
source as in 2.x.

Kept from the 3.x line: a failed ready flip is recorded with addError()
and the sweep still runs after it. The column/index test helper now runs
one transfer with columns before indexes, since a split run would sweep
the index between the two halves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…licate policy

3.1.2 forces an overwrite of any provisioning or failed database whatever
OnDuplicate or the timestamps say, but the recovery test ran only under
Fail. It now runs under Fail, Skip and Overwrite with an older and a newer
source, and checks the source name lands, so a policy that skipped an
incomplete database would fail.

The run-completion tests caught their own fail() because
AssertionFailedError is a RuntimeException, so a run that did not throw
surfaced as a confusing message mismatch. They now catch only the
interruption the callback throws and the database exception the sweep
raises.

testRunAloneMarksProvisionedDatabasesReady duplicated
AppwriteRunCompletionTest::testRunMarksItsDatabasesReady, which also
asserts the run recorded no errors; the latter keeps its failure messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
registerFilters() writes the global Database filter registry, and
utopia-php/database 8 has no public way to read or restore it: addFilter()
only adds, and the per-handle Registry codecs never see the document or
database the subquery filters need. Running the test in a separate process
keeps the CLI filters out of the other tests without reflecting on the
library's static state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mantics

Without the ownership fence the destination cannot tell an abandoned
incomplete database from one another run is still provisioning, so it
treats both as abandoned and forces an overwrite under any OnDuplicate.
Callers have to serialise migrations per destination project, and the
notes have to say so.

"Back on the 2.x lifecycle" was wrong for recovery: 2.1.0 skipped a
matching provisioning database and never recovered under Fail. The sweep
also now throws on the first failing table instead of collecting every
failure into Finalization, the removed CLI constructor and getHelp() were
unlisted, and the 3.0.0 section still read as unreleased although 3.0.0
through 3.1.1 are tagged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8.1.2 is released and moves AttributeUpdate and RelationshipUpdate into
the Attribute and Relationship namespaces with no alias, so the
destination's imports follow them. Aliased as AttributeUpdate and
RelationshipUpdate because both classes are now named Update.

The constraint is stable now, so minimum-stability goes back to stable
and prefer-stable and the stale 3.0.x branch aliases are dropped. Only
utopia-php/database moves in the lock; its requirements are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The resource group labels and the comments that restate the next line
add nothing the constants and names do not already say.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Consumers on 8.0 or 8.1.1 must upgrade the database library alongside
3.1.2, so the requirement leads the breaking changes as it did for 3.0.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abnegate
abnegate merged commit c3c6c5a into main Oct 14, 2026
3 checks passed
@abnegate
abnegate deleted the qlt-fix/mg-cleanup branch October 14, 2026 07:43
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.

1 participant