docs(8.0): consistency-model concept + snapshots guide — Db API replaces branching docs

This commit is contained in:
David Snelling 2026-06-11 08:37:26 -07:00
parent e5feae4104
commit cc8037db10
23 changed files with 1053 additions and 1871 deletions

View file

@ -1,6 +1,6 @@
# Schema Migrations
Brainy includes a built-in migration system for transforming entity and verb metadata across storage versions. Migrations are pure functions that run once per storage instance, with automatic backup, resume support, and error tracking.
Brainy includes a built-in migration system for transforming entity and verb metadata across storage versions. Migrations are pure functions that run once per storage instance, with optional snapshot backup (`backupTo`), resume support, and error tracking.
---
@ -48,15 +48,13 @@ When `brain.init()` runs:
When `brain.migrate()` runs:
1. **Backup** — creates an instant COW branch (`pre-migration-7.17.0`) tagged with `system:backup` metadata. Rollback is possible by switching to this branch.
1. **Backup (optional)** — with `backupTo`, a hard-link snapshot of the current generation is persisted before any transform runs. Rollback is `brain.restore(backupPath, { confirm: true })`.
2. **Transform main branch** — iterates all nouns/verbs in paginated batches. For each entity, calls the `transform` function. If it returns a new object, saves it. If it returns `null`, skips. Vectors are never touched.
2. **Transform** — iterates all nouns/verbs in paginated batches. For each entity, calls the `transform` function. If it returns a new object, saves it. If it returns `null`, skips. Vectors are never touched.
3. **Transform other branches** — switches to each user branch, runs the same transforms. Inherited (already-migrated) entities return `null` and are skipped automatically.
3. **Save state** — records each completed migration ID so it never re-runs.
4. **Save state** — records each completed migration ID so it never re-runs.
5. **Rebuild indexes** — if any entities were modified, rebuilds the MetadataIndex.
4. **Rebuild indexes** — if any entities were modified, rebuilds the MetadataIndex.
---
@ -78,7 +76,7 @@ interface Migration {
- **Return a new object** to modify the entity's metadata.
- **Return `null`** to skip (no change needed).
- **Must be idempotent** — running the same transform twice on the same data should produce the same result (or return `null` the second time). This is required because branch iterations may re-encounter inherited entities.
- **Must be idempotent** — running the same transform twice on the same data should produce the same result (or return `null` the second time). This is required because interrupted runs resume and re-encounter already-migrated entities.
- **Must be pure** — no side effects, no async, no external state.
- Transforms only see metadata. Vectors, embeddings, and the `data` field stored inside metadata are available as properties on the metadata object.
@ -110,9 +108,9 @@ const preview = await brain.migrate({ dryRun: true })
// preview.sampleChanges — up to 5 before/after samples
// preview.estimatedTime — rough time estimate string
// Apply migrations
const result = await brain.migrate()
// result.backupBranch — name of COW backup branch, or null
// Apply migrations (optionally with a pre-migration snapshot)
const result = await brain.migrate({ backupTo: '/backups/pre-migration' })
// result.backupPath — snapshot path, or null when no backupTo was supplied
// result.migrationsApplied — array of migration IDs that ran
// result.entitiesProcessed — total entities scanned
// result.entitiesModified — entities actually changed
@ -164,20 +162,20 @@ const result = await brain.migrate({ maxErrors: 10000 })
## Backup and Rollback
Before modifying any data, `brain.migrate()` calls `brain.fork()` to create a COW snapshot. This is instant regardless of dataset size — it's a pointer copy, not a data copy.
The backup branch is named `pre-migration-{version}` and tagged with metadata:
- `type: 'system:backup'`
- `migrationVersion: '7.17.0'`
- `author: 'brainy-migration'`
To roll back, switch to the backup branch:
Pass `backupTo` and `brain.migrate()` persists a snapshot of the current generation **before any transform runs**. On filesystem storage the snapshot is a hard-link farm — created without copying entity data, and immune to later writes (see [Snapshots & Time Travel](./snapshots-and-time-travel.md)):
```typescript
await brain.checkout('pre-migration-7.17.0')
const result = await brain.migrate({ backupTo: '/backups/pre-migration-8.0' })
console.log(result.backupPath) // '/backups/pre-migration-8.0' (null when no backupTo)
```
Old backup branches from previous migrations are cleaned up automatically before each new migration run.
To roll back, restore the snapshot wholesale:
```typescript
await brain.restore('/backups/pre-migration-8.0', { confirm: true })
```
Without `backupTo`, no backup is taken — transforms are idempotent (they return `null` when already applied), but a pre-migration snapshot is the cheap insurance for anything destructive.
---