docs(8.0): consistency-model concept + snapshots guide — Db API replaces branching docs
This commit is contained in:
parent
e5feae4104
commit
cc8037db10
23 changed files with 1053 additions and 1871 deletions
|
|
@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue