@tenetkit/pg 0.30.0 → 0.32.0
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/dist/postgres/run-schema.js +58 -16
- package/dist/postgres/schema.d.ts +4 -1
- package/dist/postgres/schema.js +30 -2
- package/package.json +2 -2
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { DateTime, Effect, Layer, Redacted } from "effect";
|
|
1
|
+
import { Cause, DateTime, Effect, Layer, Redacted } from "effect";
|
|
2
2
|
import { Migrator, SqlClient } from "effect/unstable/sql";
|
|
3
3
|
import { PgClient } from "@effect/sql-pg";
|
|
4
4
|
import { SchemaChecksumMismatch, SchemaDirty, SchemaMigrationFailed, SchemaUpgradeRequired, SchemaVersionUnsupported, } from "tenetkit/runtime/driver/sql/errors";
|
|
5
5
|
import { mapSqlError } from "tenetkit/runtime/driver/sql/sql-effect";
|
|
6
|
-
import { MIGRATIONS_TABLE, SCHEMA_META_TABLE, SCHEMA_STATEMENTS, SCHEMA_VERSION, schemaChecksum } from "./schema.js";
|
|
6
|
+
import { EXTERNAL_CHILD_STATEMENTS, MIGRATIONS_TABLE, SCHEMA_META_TABLE, SCHEMA_STATEMENTS, SCHEMA_VERSION, V7_SCHEMA_CHECKSUM, V7_SCHEMA_STATEMENTS, schemaChecksum, } from "./schema.js";
|
|
7
|
+
const migrationFailure = (source, fallback) => (error) => SchemaMigrationFailed.make({
|
|
8
|
+
source,
|
|
9
|
+
message: typeof error === "object" && error !== null && "message" in error ? String(error.message) : fallback,
|
|
10
|
+
});
|
|
7
11
|
const readMeta = (source) => mapSqlError(Effect.gen(function* () {
|
|
8
12
|
const sql = yield* SqlClient.SqlClient;
|
|
9
13
|
const exists = yield* sql `
|
|
@@ -25,22 +29,61 @@ const readMeta = (source) => mapSqlError(Effect.gen(function* () {
|
|
|
25
29
|
source,
|
|
26
30
|
message: "message" in error ? String(error.message) : "schema meta read failed",
|
|
27
31
|
})));
|
|
28
|
-
const
|
|
32
|
+
const verifyMigrationIdentity = (source, version) => Effect.gen(function* () {
|
|
29
33
|
const sql = yield* SqlClient.SqlClient;
|
|
30
|
-
|
|
34
|
+
const migrations = yield* sql `
|
|
35
|
+
SELECT migration_id, name FROM ${sql(MIGRATIONS_TABLE)} ORDER BY migration_id
|
|
36
|
+
`;
|
|
37
|
+
const expected = version === 7
|
|
38
|
+
? [[1, "baton_runtime"]]
|
|
39
|
+
: [
|
|
40
|
+
[1, "baton_runtime"],
|
|
41
|
+
[2, "external_child_placements"],
|
|
42
|
+
];
|
|
43
|
+
if (migrations.length !== expected.length ||
|
|
44
|
+
migrations.some((migration, index) => Number(migration.migration_id) !== expected[index]?.[0] || migration.name !== expected[index]?.[1])) {
|
|
45
|
+
return yield* SchemaMigrationFailed.make({ source, message: `version ${version} migration identity mismatch` });
|
|
46
|
+
}
|
|
47
|
+
}).pipe(Effect.mapError(migrationFailure(source, "migration identity read failed")));
|
|
48
|
+
const baselineMigration = Effect.gen(function* () {
|
|
49
|
+
const sql = yield* SqlClient.SqlClient;
|
|
50
|
+
for (const statement of V7_SCHEMA_STATEMENTS)
|
|
31
51
|
yield* sql.unsafe(statement);
|
|
32
52
|
const now = yield* DateTime.nowAsDate;
|
|
33
53
|
yield* sql `
|
|
34
54
|
INSERT INTO ${sql(SCHEMA_META_TABLE)} (id, version, checksum, dirty, applied_at)
|
|
35
|
-
VALUES (1,
|
|
55
|
+
VALUES (1, 7, ${V7_SCHEMA_CHECKSUM}, FALSE, ${now})
|
|
36
56
|
`;
|
|
37
57
|
});
|
|
58
|
+
const externalChildMigration = Effect.gen(function* () {
|
|
59
|
+
const sql = yield* SqlClient.SqlClient;
|
|
60
|
+
yield* sql `UPDATE ${sql(SCHEMA_META_TABLE)} SET dirty = TRUE WHERE id = 1`;
|
|
61
|
+
for (const statement of EXTERNAL_CHILD_STATEMENTS) {
|
|
62
|
+
yield* sql.unsafe(statement.replaceAll(" IF NOT EXISTS", ""));
|
|
63
|
+
}
|
|
64
|
+
const now = yield* DateTime.nowAsDate;
|
|
65
|
+
yield* sql `UPDATE ${sql(SCHEMA_META_TABLE)}
|
|
66
|
+
SET version = ${SCHEMA_VERSION}, checksum = ${schemaChecksum()}, dirty = FALSE, applied_at = ${now}
|
|
67
|
+
WHERE id = 1`;
|
|
68
|
+
});
|
|
69
|
+
const runMigrations = (source) => {
|
|
70
|
+
const migrate = Migrator.make({});
|
|
71
|
+
return migrate({
|
|
72
|
+
loader: Migrator.fromRecord({
|
|
73
|
+
"0001_baton_runtime": baselineMigration,
|
|
74
|
+
"0002_external_child_placements": externalChildMigration,
|
|
75
|
+
}),
|
|
76
|
+
table: MIGRATIONS_TABLE,
|
|
77
|
+
}).pipe(Effect.catchCause((cause) => Cause.hasInterrupts(cause)
|
|
78
|
+
? Effect.interrupt
|
|
79
|
+
: SchemaMigrationFailed.make({ source, message: Cause.pretty(cause) || "migration failed" })));
|
|
80
|
+
};
|
|
38
81
|
export const plan = (source) => Effect.map(readMeta(source), (meta) => ({
|
|
39
82
|
current: meta.version,
|
|
40
83
|
required: SCHEMA_VERSION,
|
|
41
84
|
checksum: schemaChecksum(),
|
|
42
|
-
statements: meta.present ? [] : SCHEMA_STATEMENTS,
|
|
43
|
-
upgradeRequired:
|
|
85
|
+
statements: meta.present ? (meta.version === 7 ? EXTERNAL_CHILD_STATEMENTS : []) : SCHEMA_STATEMENTS,
|
|
86
|
+
upgradeRequired: meta.version < SCHEMA_VERSION,
|
|
44
87
|
}));
|
|
45
88
|
export const check = (source) => Effect.gen(function* () {
|
|
46
89
|
const meta = yield* readMeta(source);
|
|
@@ -55,11 +98,17 @@ export const check = (source) => Effect.gen(function* () {
|
|
|
55
98
|
if (meta.version !== SCHEMA_VERSION || meta.checksum !== expected) {
|
|
56
99
|
return yield* SchemaChecksumMismatch.make({ source, expected, actual: meta.checksum });
|
|
57
100
|
}
|
|
101
|
+
yield* verifyMigrationIdentity(source, SCHEMA_VERSION);
|
|
58
102
|
});
|
|
59
103
|
export const apply = (source) => Effect.gen(function* () {
|
|
60
104
|
const meta = yield* readMeta(source);
|
|
61
|
-
if (meta.present)
|
|
105
|
+
if (meta.present) {
|
|
106
|
+
if (meta.dirty || meta.version !== 7 || meta.checksum !== V7_SCHEMA_CHECKSUM)
|
|
107
|
+
return yield* check(source);
|
|
108
|
+
yield* verifyMigrationIdentity(source, 7);
|
|
109
|
+
yield* runMigrations(source);
|
|
62
110
|
return yield* check(source);
|
|
111
|
+
}
|
|
63
112
|
const sql = yield* SqlClient.SqlClient;
|
|
64
113
|
const existing = yield* sql `
|
|
65
114
|
SELECT COUNT(*) AS present FROM information_schema.tables
|
|
@@ -71,14 +120,7 @@ export const apply = (source) => Effect.gen(function* () {
|
|
|
71
120
|
message: "cannot create the baseline over an existing TenetKit schema",
|
|
72
121
|
});
|
|
73
122
|
}
|
|
74
|
-
|
|
75
|
-
yield* runMigrations({
|
|
76
|
-
loader: Migrator.fromRecord({ "0001_baton_runtime": migrationEffect }),
|
|
77
|
-
table: MIGRATIONS_TABLE,
|
|
78
|
-
}).pipe(Effect.mapError((error) => SchemaMigrationFailed.make({
|
|
79
|
-
source,
|
|
80
|
-
message: "message" in error ? String(error.message) : "migration failed",
|
|
81
|
-
})));
|
|
123
|
+
yield* runMigrations(source);
|
|
82
124
|
yield* check(source).pipe(Effect.catchTag("tenetkit/runtime/SchemaUpgradeRequired", (error) => SchemaMigrationFailed.make({ source, message: `schema absent after apply: ${error.current}` })));
|
|
83
125
|
});
|
|
84
126
|
export const markDirty = (source) => mapSqlError(Effect.gen(function* () {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
export declare const SCHEMA_VERSION =
|
|
1
|
+
export declare const SCHEMA_VERSION = 8;
|
|
2
|
+
export declare const V7_SCHEMA_CHECKSUM = "4d86018b3453e9757e05694ce981fc486a15a00ebb36874b49821f6289e6d495";
|
|
2
3
|
export declare const SCHEMA_META_TABLE = "baton_schema_meta";
|
|
3
4
|
export declare const MIGRATIONS_TABLE = "baton_sql_migrations";
|
|
4
5
|
export declare const NOTIFY_CHANNEL = "baton_run_events";
|
|
6
|
+
export declare const V7_SCHEMA_STATEMENTS: ReadonlyArray<string>;
|
|
7
|
+
export declare const EXTERNAL_CHILD_STATEMENTS: ReadonlyArray<string>;
|
|
5
8
|
export declare const SCHEMA_STATEMENTS: ReadonlyArray<string>;
|
|
6
9
|
export declare const schemaChecksum: () => string;
|
package/dist/postgres/schema.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export const SCHEMA_VERSION =
|
|
1
|
+
export const SCHEMA_VERSION = 8;
|
|
2
|
+
export const V7_SCHEMA_CHECKSUM = "4d86018b3453e9757e05694ce981fc486a15a00ebb36874b49821f6289e6d495";
|
|
2
3
|
export const SCHEMA_META_TABLE = "baton_schema_meta";
|
|
3
4
|
export const MIGRATIONS_TABLE = "baton_sql_migrations";
|
|
4
5
|
export const NOTIFY_CHANNEL = "baton_run_events";
|
|
5
|
-
export const
|
|
6
|
+
export const V7_SCHEMA_STATEMENTS = [
|
|
6
7
|
`CREATE TABLE IF NOT EXISTS baton_schema_meta (
|
|
7
8
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
8
9
|
version INTEGER NOT NULL,
|
|
@@ -265,6 +266,33 @@ export const SCHEMA_STATEMENTS = [
|
|
|
265
266
|
`CREATE UNIQUE INDEX IF NOT EXISTS baton_session_entries_seq_idx ON baton_session_entries(session_id, seq)`,
|
|
266
267
|
`CREATE INDEX IF NOT EXISTS baton_session_entries_parent_idx ON baton_session_entries(session_id, parent_id)`,
|
|
267
268
|
];
|
|
269
|
+
export const EXTERNAL_CHILD_STATEMENTS = [
|
|
270
|
+
`CREATE TABLE IF NOT EXISTS baton_external_child_placements (
|
|
271
|
+
placement_id TEXT PRIMARY KEY,
|
|
272
|
+
parent_run_id TEXT NOT NULL REFERENCES baton_runs(run_id),
|
|
273
|
+
partition TEXT NOT NULL,
|
|
274
|
+
external_run_id TEXT NOT NULL,
|
|
275
|
+
invocation_id TEXT NOT NULL,
|
|
276
|
+
request_digest TEXT NOT NULL,
|
|
277
|
+
executable_digest TEXT NOT NULL,
|
|
278
|
+
wait_id TEXT,
|
|
279
|
+
suspension_identity TEXT,
|
|
280
|
+
acknowledged BOOLEAN NOT NULL DEFAULT FALSE,
|
|
281
|
+
cancel_requested BOOLEAN NOT NULL DEFAULT FALSE,
|
|
282
|
+
settlement_id TEXT,
|
|
283
|
+
outcome_json TEXT,
|
|
284
|
+
outcome_event_id TEXT,
|
|
285
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
286
|
+
settled_at TIMESTAMPTZ,
|
|
287
|
+
UNIQUE (partition, external_run_id),
|
|
288
|
+
UNIQUE (parent_run_id, invocation_id),
|
|
289
|
+
CHECK ((settlement_id IS NULL AND outcome_json IS NULL AND outcome_event_id IS NULL AND settled_at IS NULL)
|
|
290
|
+
OR (settlement_id IS NOT NULL AND outcome_json IS NOT NULL AND outcome_event_id IS NOT NULL AND settled_at IS NOT NULL))
|
|
291
|
+
)`,
|
|
292
|
+
`CREATE INDEX IF NOT EXISTS baton_external_child_placements_parent_idx
|
|
293
|
+
ON baton_external_child_placements(parent_run_id, settlement_id, created_at)`,
|
|
294
|
+
];
|
|
295
|
+
export const SCHEMA_STATEMENTS = [...V7_SCHEMA_STATEMENTS, ...EXTERNAL_CHILD_STATEMENTS];
|
|
268
296
|
export const schemaChecksum = () => {
|
|
269
297
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
270
298
|
hasher.update(SCHEMA_STATEMENTS.join("\n"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@effect/sql-pg": "4.0.0-rc.109",
|
|
40
|
-
"tenetkit": "0.
|
|
40
|
+
"tenetkit": "0.32.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@effect/vitest": "4.0.0-rc.109",
|