feat(8.0): #18 coordinated migration LOCK — block-and-queue the 7.x→8.0 auto-upgrade
Replaces rc.8's no-freeze deference with an automatic, observable, coordinated
migration LOCK (David's reversal: "unknown/halfway states are more dangerous
than blocking"). While a native provider runs its one-time 7.x→8.0
rebuild-from-canonical (`isMigrating()===true`), brainy blocks/queues data-plane
reads AND writes so no operation ever touches a half-built index — closing the
three seam-map gaps (lost mid-rebuild writes, degraded reads, read-time rebuild).
Mechanism (one choke point):
- awaitMigrationLock() at ensureInitialized() covers all ~40 data-plane methods;
a non-migrating brain pays one boolean check. Polls isMigrating() at 250ms;
after migrationWaitTimeoutMs (default 30s) throws a retryable, exported
MigrationInProgressError. The timeout bounds the CALLER'S WAIT, not the
migration — the rebuild is unbounded and never interrupted.
- init() awaits the lock before VFS bootstrap + before serving ("not ready until
upgraded"); a rebuild past the budget surfaces MigrationInProgressError at init
(raise the budget, or run the offline migrator).
Observability (readiness-probe correct — never gated):
- getIndexStatus() gains `migrating` + `migration` (MigrationProgress); a probe
maps migrating→HTTP 503+Retry-After, not 500. health()/checkHealth() lock-exempt
(health() reports a `warn` migration check). stampBrainFormat()/close() are
ungated so cor can clear the lock — no deadlock.
- Optional provider migrationStatus() is relayed verbatim for a live %.
verifyGraphAdjacencyLive() honors the lock (no self-rebuild mid-migration); the
stamp is still withheld while any provider migrates (cor stamps after verify).
Adversarially verified: fixed a critical init/VFS-bootstrap deadlock, a mixed-
provider busy-spin (dropped the event-driven signal → pure poll), a not-yet-
initialized getIndexStatus crash, and once-per-window log/clock resets. 10 lock
tests (incl. the init-during-migration regression). Gates: typecheck 0, build 0,
test:unit 1753/1753.
This commit is contained in:
parent
ca9129a924
commit
67bbf69a5c
5 changed files with 534 additions and 31 deletions
|
|
@ -137,6 +137,11 @@ export { RevisionConflictError } from './transaction/RevisionConflictError.js'
|
|||
// transact/with() when a referenced entity or relation does not exist.
|
||||
export { EntityNotFoundError, RelationNotFoundError } from './errors/notFound.js'
|
||||
|
||||
// Base error + typed migration-lock error — thrown by any data-plane call while a
|
||||
// brain runs its one-time 7.x→8.0 upgrade; catch to answer HTTP 503 + Retry-After.
|
||||
export { BrainyError, MigrationInProgressError, GraphIndexNotReadyError } from './errors/brainyError.js'
|
||||
export type { BrainyErrorType } from './errors/brainyError.js'
|
||||
|
||||
// ============= 8.0 Db API — generational MVCC =============
|
||||
// Immutable database values: brain.now() / brain.transact() / brain.asOf() /
|
||||
// db.with() / db.persist() / Brainy.load(). See src/db/ for the record layer.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue