@smithers-orchestrator/db 0.25.1 → 0.25.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/adapter.js +29 -0
- package/src/schema-migrations.js +22 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithers-orchestrator/db",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.3",
|
|
4
4
|
"description": "SQLite and Drizzle persistence adapter for Smithers workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"drizzle-zod": "^0.8.3",
|
|
31
31
|
"effect": "^3.21.1",
|
|
32
32
|
"zod": "^4.3.6",
|
|
33
|
-
"@smithers-orchestrator/errors": "0.25.
|
|
34
|
-
"@smithers-orchestrator/graph": "0.25.
|
|
35
|
-
"@smithers-orchestrator/observability": "0.25.
|
|
36
|
-
"@smithers-orchestrator/scheduler": "0.25.
|
|
33
|
+
"@smithers-orchestrator/errors": "0.25.3",
|
|
34
|
+
"@smithers-orchestrator/graph": "0.25.3",
|
|
35
|
+
"@smithers-orchestrator/observability": "0.25.3",
|
|
36
|
+
"@smithers-orchestrator/scheduler": "0.25.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@electric-sql/pglite": "0.5.1",
|
package/src/adapter.js
CHANGED
|
@@ -2556,6 +2556,35 @@ export class SmithersDb {
|
|
|
2556
2556
|
}));
|
|
2557
2557
|
}
|
|
2558
2558
|
/**
|
|
2559
|
+
* Delete durable snapshot rows for frames after `frameNo`. Snapshots are keyed
|
|
2560
|
+
* (run_id, frame_no) and are the hydration/fork source, so a rewind that
|
|
2561
|
+
* truncates frames must truncate the matching snapshots too — otherwise
|
|
2562
|
+
* fork/replay/loadLatestSnapshot can resurrect logically-discarded state.
|
|
2563
|
+
* @param {string} runId
|
|
2564
|
+
* @param {number} frameNo
|
|
2565
|
+
* @returns {RunnableEffect<void, SmithersError>}
|
|
2566
|
+
*/
|
|
2567
|
+
deleteSnapshotsAfter(runId, frameNo) {
|
|
2568
|
+
const self = this;
|
|
2569
|
+
return runnableEffect(Effect.gen(function* () {
|
|
2570
|
+
yield* self.write(`delete snapshots after ${frameNo}`, () => self.internalStorage.deleteWhere("_smithers_snapshots", "run_id = ? AND frame_no > ?", [runId, frameNo]));
|
|
2571
|
+
}));
|
|
2572
|
+
}
|
|
2573
|
+
/**
|
|
2574
|
+
* Delete VCS tag rows for frames after `frameNo`, keyed (run_id, frame_no).
|
|
2575
|
+
* A rewind truncates frames; the matching vcs-tags must go too or
|
|
2576
|
+
* rerunAtRevision/loadVcsTag can restore a discarded working-copy revision.
|
|
2577
|
+
* @param {string} runId
|
|
2578
|
+
* @param {number} frameNo
|
|
2579
|
+
* @returns {RunnableEffect<void, SmithersError>}
|
|
2580
|
+
*/
|
|
2581
|
+
deleteVcsTagsAfter(runId, frameNo) {
|
|
2582
|
+
const self = this;
|
|
2583
|
+
return runnableEffect(Effect.gen(function* () {
|
|
2584
|
+
yield* self.write(`delete vcs tags after ${frameNo}`, () => self.internalStorage.deleteWhere("_smithers_vcs_tags", "run_id = ? AND frame_no > ?", [runId, frameNo]));
|
|
2585
|
+
}));
|
|
2586
|
+
}
|
|
2587
|
+
/**
|
|
2559
2588
|
* @param {string} runId
|
|
2560
2589
|
* @param {number} limit
|
|
2561
2590
|
* @param {number} [afterFrameNo]
|
package/src/schema-migrations.js
CHANGED
|
@@ -75,6 +75,9 @@ const LEGACY_COLUMN_MIGRATIONS = [
|
|
|
75
75
|
name: "Add legacy run operational columns",
|
|
76
76
|
table: "_smithers_runs",
|
|
77
77
|
columns: [
|
|
78
|
+
["workflow_path", "workflow_path TEXT"],
|
|
79
|
+
["started_at_ms", "started_at_ms INTEGER"],
|
|
80
|
+
["finished_at_ms", "finished_at_ms INTEGER"],
|
|
78
81
|
["workflow_hash", "workflow_hash TEXT"],
|
|
79
82
|
["heartbeat_at_ms", "heartbeat_at_ms INTEGER"],
|
|
80
83
|
["runtime_owner_id", "runtime_owner_id TEXT"],
|
|
@@ -126,6 +129,12 @@ const LEGACY_COLUMN_MIGRATIONS = [
|
|
|
126
129
|
table: "_smithers_frames",
|
|
127
130
|
columns: [["encoding", "encoding TEXT NOT NULL DEFAULT 'full'"]],
|
|
128
131
|
},
|
|
132
|
+
{
|
|
133
|
+
id: "0007_event_timestamp_column",
|
|
134
|
+
name: "Add event timestamp column",
|
|
135
|
+
table: "_smithers_events",
|
|
136
|
+
columns: [["timestamp_ms", "timestamp_ms INTEGER NOT NULL DEFAULT 0"]],
|
|
137
|
+
},
|
|
129
138
|
];
|
|
130
139
|
|
|
131
140
|
const EXTRA_INDEX_STATEMENTS = [
|
|
@@ -516,6 +525,14 @@ function buildMigrations(context) {
|
|
|
516
525
|
return config.columns.every(([column]) => columns.has(column));
|
|
517
526
|
},
|
|
518
527
|
up: (sqlite) => {
|
|
528
|
+
// A column migration only adds columns to an existing table; the base
|
|
529
|
+
// 0001 migration owns table creation. If the table is absent (a store
|
|
530
|
+
// whose ledger recorded 0001 but predates this table), skip rather than
|
|
531
|
+
// throw "no such table" — mirrors how the index migrations skip indexes
|
|
532
|
+
// whose table is absent and let the create-table migration own it.
|
|
533
|
+
if (!tableExists(sqlite, config.table)) {
|
|
534
|
+
return { table: config.table, addedColumns: [], skipped: "missing_table" };
|
|
535
|
+
}
|
|
519
536
|
const addedColumns = [];
|
|
520
537
|
for (const [column, definition] of config.columns) {
|
|
521
538
|
if (addColumnIfMissing(sqlite, config.table, column, definition)) {
|
|
@@ -525,6 +542,9 @@ function buildMigrations(context) {
|
|
|
525
542
|
return { table: config.table, addedColumns };
|
|
526
543
|
},
|
|
527
544
|
upPostgres: async (pgConn) => {
|
|
545
|
+
if (!(await tableExistsPostgres(pgConn, config.table))) {
|
|
546
|
+
return { table: config.table, addedColumns: [], skipped: "missing_table" };
|
|
547
|
+
}
|
|
528
548
|
const addedColumns = [];
|
|
529
549
|
for (const [column, definition] of config.columns) {
|
|
530
550
|
if (await addColumnIfMissingPostgres(pgConn, config.table, column, definition)) {
|
|
@@ -810,7 +830,8 @@ export async function runSmithersSchemaMigrationsPostgres(pgConn, context) {
|
|
|
810
830
|
await pgConn.query({ text: translateDdl(POSTGRES, MIGRATION_TABLE_SQL) });
|
|
811
831
|
const applied = await loadAppliedMigrationIdsPostgres(pgConn);
|
|
812
832
|
for (const migration of buildMigrations(context)) {
|
|
813
|
-
|
|
833
|
+
const alreadyAppliedInLedger = applied.has(migration.id);
|
|
834
|
+
if (alreadyAppliedInLedger && migration.isAppliedPostgres && await migration.isAppliedPostgres(pgConn)) {
|
|
814
835
|
continue;
|
|
815
836
|
}
|
|
816
837
|
const details = await runPostgresMigrationSpan(migration, async () => {
|