@intentius/sql-yodeler 0.0.0-stage → 0.1.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/LICENSE +202 -0
- package/README.md +110 -2
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +14 -0
- package/dist/bin.js.map +1 -0
- package/dist/chant/apply.d.ts +51 -0
- package/dist/chant/apply.js +104 -0
- package/dist/chant/apply.js.map +1 -0
- package/dist/chant/build.d.ts +34 -0
- package/dist/chant/build.js +48 -0
- package/dist/chant/build.js.map +1 -0
- package/dist/chant/drift.d.ts +44 -0
- package/dist/chant/drift.js +91 -0
- package/dist/chant/drift.js.map +1 -0
- package/dist/chant/plan.d.ts +45 -0
- package/dist/chant/plan.js +61 -0
- package/dist/chant/plan.js.map +1 -0
- package/dist/chant/process.d.ts +41 -0
- package/dist/chant/process.js +87 -0
- package/dist/chant/process.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/command.d.ts +17 -0
- package/dist/command.js +13 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/apply.d.ts +3 -0
- package/dist/commands/apply.js +306 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/drift.d.ts +3 -0
- package/dist/commands/drift.js +38 -0
- package/dist/commands/drift.js.map +1 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +22 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +135 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/lint.d.ts +3 -0
- package/dist/commands/lint.js +193 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/new.d.ts +3 -0
- package/dist/commands/new.js +168 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.js +171 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/rebase.d.ts +3 -0
- package/dist/commands/rebase.js +167 -0
- package/dist/commands/rebase.js.map +1 -0
- package/dist/commands/repair.d.ts +3 -0
- package/dist/commands/repair.js +117 -0
- package/dist/commands/repair.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +54 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/define.d.ts +50 -0
- package/dist/config/define.js +20 -0
- package/dist/config/define.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.js +12 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load.d.ts +17 -0
- package/dist/config/load.js +102 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/settings.d.ts +40 -0
- package/dist/config/settings.js +88 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/env-args.d.ts +18 -0
- package/dist/env-args.js +62 -0
- package/dist/env-args.js.map +1 -0
- package/dist/history/client.d.ts +17 -0
- package/dist/history/client.js +19 -0
- package/dist/history/client.js.map +1 -0
- package/dist/history/ddl.d.ts +58 -0
- package/dist/history/ddl.js +100 -0
- package/dist/history/ddl.js.map +1 -0
- package/dist/history/index.d.ts +25 -0
- package/dist/history/index.js +26 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/lock.d.ts +100 -0
- package/dist/history/lock.js +224 -0
- package/dist/history/lock.js.map +1 -0
- package/dist/history/postgres/ddl.d.ts +22 -0
- package/dist/history/postgres/ddl.js +47 -0
- package/dist/history/postgres/ddl.js.map +1 -0
- package/dist/history/postgres/index.d.ts +12 -0
- package/dist/history/postgres/index.js +13 -0
- package/dist/history/postgres/index.js.map +1 -0
- package/dist/history/postgres/lock.d.ts +48 -0
- package/dist/history/postgres/lock.js +95 -0
- package/dist/history/postgres/lock.js.map +1 -0
- package/dist/history/postgres/store.d.ts +39 -0
- package/dist/history/postgres/store.js +68 -0
- package/dist/history/postgres/store.js.map +1 -0
- package/dist/history/rows.d.ts +96 -0
- package/dist/history/rows.js +73 -0
- package/dist/history/rows.js.map +1 -0
- package/dist/history/store.d.ts +72 -0
- package/dist/history/store.js +134 -0
- package/dist/history/store.js.map +1 -0
- package/dist/history/topology.d.ts +41 -0
- package/dist/history/topology.js +54 -0
- package/dist/history/topology.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/init/adopt.d.ts +70 -0
- package/dist/init/adopt.js +138 -0
- package/dist/init/adopt.js.map +1 -0
- package/dist/init/baseline.d.ts +61 -0
- package/dist/init/baseline.js +88 -0
- package/dist/init/baseline.js.map +1 -0
- package/dist/init/files.d.ts +23 -0
- package/dist/init/files.js +77 -0
- package/dist/init/files.js.map +1 -0
- package/dist/init/index.d.ts +16 -0
- package/dist/init/index.js +17 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/live.d.ts +28 -0
- package/dist/init/live.js +45 -0
- package/dist/init/live.js.map +1 -0
- package/dist/lint/check.d.ts +81 -0
- package/dist/lint/check.js +208 -0
- package/dist/lint/check.js.map +1 -0
- package/dist/lint/config.d.ts +21 -0
- package/dist/lint/config.js +43 -0
- package/dist/lint/config.js.map +1 -0
- package/dist/lint/index.d.ts +31 -0
- package/dist/lint/index.js +43 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/project-rules.d.ts +19 -0
- package/dist/lint/project-rules.js +32 -0
- package/dist/lint/project-rules.js.map +1 -0
- package/dist/lint/report.d.ts +7 -0
- package/dist/lint/report.js +48 -0
- package/dist/lint/report.js.map +1 -0
- package/dist/lint/rules.d.ts +53 -0
- package/dist/lint/rules.js +42 -0
- package/dist/lint/rules.js.map +1 -0
- package/dist/lint/silences.d.ts +49 -0
- package/dist/lint/silences.js +91 -0
- package/dist/lint/silences.js.map +1 -0
- package/dist/lint/statements.d.ts +38 -0
- package/dist/lint/statements.js +120 -0
- package/dist/lint/statements.js.map +1 -0
- package/dist/migrations/checksum.d.ts +56 -0
- package/dist/migrations/checksum.js +72 -0
- package/dist/migrations/checksum.js.map +1 -0
- package/dist/migrations/create.d.ts +73 -0
- package/dist/migrations/create.js +119 -0
- package/dist/migrations/create.js.map +1 -0
- package/dist/migrations/directory.d.ts +119 -0
- package/dist/migrations/directory.js +225 -0
- package/dist/migrations/directory.js.map +1 -0
- package/dist/migrations/document.d.ts +83 -0
- package/dist/migrations/document.js +82 -0
- package/dist/migrations/document.js.map +1 -0
- package/dist/migrations/index.d.ts +20 -0
- package/dist/migrations/index.js +21 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/pr/comment.d.ts +32 -0
- package/dist/pr/comment.js +99 -0
- package/dist/pr/comment.js.map +1 -0
- package/dist/pr/forge.d.ts +50 -0
- package/dist/pr/forge.js +105 -0
- package/dist/pr/forge.js.map +1 -0
- package/dist/pr/model.d.ts +91 -0
- package/dist/pr/model.js +113 -0
- package/dist/pr/model.js.map +1 -0
- package/dist/pr/render.d.ts +27 -0
- package/dist/pr/render.js +246 -0
- package/dist/pr/render.js.map +1 -0
- package/dist/project.d.ts +62 -0
- package/dist/project.js +92 -0
- package/dist/project.js.map +1 -0
- package/dist/rebase/index.d.ts +121 -0
- package/dist/rebase/index.js +390 -0
- package/dist/rebase/index.js.map +1 -0
- package/dist/rebase/repair.d.ts +41 -0
- package/dist/rebase/repair.js +68 -0
- package/dist/rebase/repair.js.map +1 -0
- package/dist/replay/clickhouse.d.ts +33 -0
- package/dist/replay/clickhouse.js +106 -0
- package/dist/replay/clickhouse.js.map +1 -0
- package/dist/replay/index.d.ts +36 -0
- package/dist/replay/index.js +54 -0
- package/dist/replay/index.js.map +1 -0
- package/dist/replay/postgres.d.ts +31 -0
- package/dist/replay/postgres.js +140 -0
- package/dist/replay/postgres.js.map +1 -0
- package/dist/replay/replay.d.ts +114 -0
- package/dist/replay/replay.js +98 -0
- package/dist/replay/replay.js.map +1 -0
- package/dist/replay/report.d.ts +18 -0
- package/dist/replay/report.js +72 -0
- package/dist/replay/report.js.map +1 -0
- package/dist/steps/backfill.d.ts +128 -0
- package/dist/steps/backfill.js +307 -0
- package/dist/steps/backfill.js.map +1 -0
- package/dist/steps/index.d.ts +52 -0
- package/dist/steps/index.js +52 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/kinds.d.ts +101 -0
- package/dist/steps/kinds.js +143 -0
- package/dist/steps/kinds.js.map +1 -0
- package/dist/steps/postgres-migration.d.ts +95 -0
- package/dist/steps/postgres-migration.js +149 -0
- package/dist/steps/postgres-migration.js.map +1 -0
- package/dist/steps/rebuild.d.ts +97 -0
- package/dist/steps/rebuild.js +162 -0
- package/dist/steps/rebuild.js.map +1 -0
- package/dist/steps/run.d.ts +45 -0
- package/dist/steps/run.js +72 -0
- package/dist/steps/run.js.map +1 -0
- package/dist/topology/render.d.ts +17 -0
- package/dist/topology/render.js +17 -0
- package/dist/topology/render.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/dist/versioned/approval.d.ts +35 -0
- package/dist/versioned/approval.js +53 -0
- package/dist/versioned/approval.js.map +1 -0
- package/dist/versioned/clickhouse.d.ts +24 -0
- package/dist/versioned/clickhouse.js +34 -0
- package/dist/versioned/clickhouse.js.map +1 -0
- package/dist/versioned/digest.d.ts +77 -0
- package/dist/versioned/digest.js +69 -0
- package/dist/versioned/digest.js.map +1 -0
- package/dist/versioned/driver.d.ts +41 -0
- package/dist/versioned/driver.js +13 -0
- package/dist/versioned/driver.js.map +1 -0
- package/dist/versioned/engine.d.ts +152 -0
- package/dist/versioned/engine.js +277 -0
- package/dist/versioned/engine.js.map +1 -0
- package/dist/versioned/explain.d.ts +123 -0
- package/dist/versioned/explain.js +289 -0
- package/dist/versioned/explain.js.map +1 -0
- package/dist/versioned/index.d.ts +37 -0
- package/dist/versioned/index.js +54 -0
- package/dist/versioned/index.js.map +1 -0
- package/dist/versioned/op.d.ts +62 -0
- package/dist/versioned/op.js +153 -0
- package/dist/versioned/op.js.map +1 -0
- package/dist/versioned/postgres/catalog.d.ts +33 -0
- package/dist/versioned/postgres/catalog.js +34 -0
- package/dist/versioned/postgres/catalog.js.map +1 -0
- package/dist/versioned/postgres/driver.d.ts +69 -0
- package/dist/versioned/postgres/driver.js +113 -0
- package/dist/versioned/postgres/driver.js.map +1 -0
- package/dist/versioned/postgres/executor.d.ts +104 -0
- package/dist/versioned/postgres/executor.js +172 -0
- package/dist/versioned/postgres/executor.js.map +1 -0
- package/dist/versioned/postgres/index.d.ts +11 -0
- package/dist/versioned/postgres/index.js +12 -0
- package/dist/versioned/postgres/index.js.map +1 -0
- package/dist/versioned/report.d.ts +22 -0
- package/dist/versioned/report.js +81 -0
- package/dist/versioned/report.js.map +1 -0
- package/dist/versioned/state.d.ts +108 -0
- package/dist/versioned/state.js +153 -0
- package/dist/versioned/state.js.map +1 -0
- package/package.json +51 -4
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sending one migration statement to Postgres, the way chant's applier does
|
|
3
|
+
* (`postgres/apply/apply.ts`), with the history row that says it succeeded.
|
|
4
|
+
*
|
|
5
|
+
* ## Timeouts and retries
|
|
6
|
+
*
|
|
7
|
+
* Every statement runs with its own `lock_timeout` (default 5 s, the
|
|
8
|
+
* profile's `lockTimeoutMs`) and `statement_timeout` (the profile's
|
|
9
|
+
* `statementTimeoutMs`, default 60 s, for a catalog change; `scanTimeoutMs`,
|
|
10
|
+
* default none, for one that reads or rewrites rows). A statement blocked
|
|
11
|
+
* behind another session's lock gives up when the lock timeout passes
|
|
12
|
+
* (SQLSTATE 55P03) instead of queueing every later query on the table
|
|
13
|
+
* behind it, and is tried again after a pause that doubles each time (250
|
|
14
|
+
* ms, 500 ms, ...), up to `retries` more times (default 5). Any other error
|
|
15
|
+
* fails it at once.
|
|
16
|
+
*
|
|
17
|
+
* ## Transactions
|
|
18
|
+
*
|
|
19
|
+
* A statement chant marks `transactional` runs in a transaction of its own:
|
|
20
|
+
*
|
|
21
|
+
* BEGIN; SET LOCAL lock_timeout ...; SET LOCAL statement_timeout ...;
|
|
22
|
+
* <statement>; INSERT INTO <history> (... 'succeeded' ...); COMMIT
|
|
23
|
+
*
|
|
24
|
+
* so the statement and its `succeeded` row commit together or not at all.
|
|
25
|
+
* A runner killed anywhere in it leaves either both or neither: a statement
|
|
26
|
+
* whose latest row is `started` did not commit, and is sent again safely.
|
|
27
|
+
*
|
|
28
|
+
* A statement that may not run in a transaction block (`CREATE INDEX
|
|
29
|
+
* CONCURRENTLY`, `DROP INDEX CONCURRENTLY`) or that chant keeps out of one
|
|
30
|
+
* (`ALTER TYPE ... ADD VALUE`, whose label cannot be used in the transaction
|
|
31
|
+
* that adds it) runs alone, with `SET` for the session first; its
|
|
32
|
+
* `succeeded` row is written right after it, in a transaction of its own.
|
|
33
|
+
* A runner killed between the two leaves the statement run and its latest
|
|
34
|
+
* row `started`, and the next run sends it again.
|
|
35
|
+
*
|
|
36
|
+
* ## A failed CONCURRENTLY build
|
|
37
|
+
*
|
|
38
|
+
* `CREATE INDEX CONCURRENTLY` that fails (a lock timeout, a duplicate on a
|
|
39
|
+
* unique index, a cancel) leaves the index behind, INVALID: it is in the
|
|
40
|
+
* catalog, is maintained on every write, and is never used, and the next
|
|
41
|
+
* `CREATE INDEX` of that name fails because it exists. So before every
|
|
42
|
+
* attempt, the first, a retry, or a resume in a later run, and after every
|
|
43
|
+
* failure, an INVALID index of that name is dropped (`DROP INDEX
|
|
44
|
+
* CONCURRENTLY IF EXISTS`), and only an INVALID one: a valid index of that
|
|
45
|
+
* name is never touched.
|
|
46
|
+
*/
|
|
47
|
+
import { YodelError } from "../../project.js";
|
|
48
|
+
import { pgIdent } from "../../history/postgres/index.js";
|
|
49
|
+
/** SQLSTATE lock_not_available: the lock timeout passed. */
|
|
50
|
+
export const LOCK_NOT_AVAILABLE = "55P03";
|
|
51
|
+
export const DEFAULT_PG_TIMEOUTS = { lockTimeoutMs: 5_000, statementTimeoutMs: 60_000, scanTimeoutMs: 0 };
|
|
52
|
+
export const DEFAULT_LOCK_RETRIES = 5;
|
|
53
|
+
export const DEFAULT_RETRY_BASE_MS = 250;
|
|
54
|
+
/** A statement failed; `error` is the server's message. */
|
|
55
|
+
export class PgStatementError extends YodelError {
|
|
56
|
+
error;
|
|
57
|
+
code;
|
|
58
|
+
attempts;
|
|
59
|
+
constructor(error, code, attempts) {
|
|
60
|
+
super(error, 1);
|
|
61
|
+
this.error = error;
|
|
62
|
+
this.code = code;
|
|
63
|
+
this.attempts = attempts;
|
|
64
|
+
this.name = "PgStatementError";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const sqlstate = (e) => e && typeof e === "object" && "code" in e && typeof e.code === "string" ? e.code : undefined;
|
|
68
|
+
const messageOf = (e) => (e instanceof Error ? e.message : String(e));
|
|
69
|
+
const ms = (n) => `'${String(Math.max(0, Math.floor(n)))}ms'`;
|
|
70
|
+
/** Whether a statement of `cls` reads or rewrites rows (chant's `scansRows`), so it runs with the scan timeout. */
|
|
71
|
+
export const scansRows = (cls) => cls === "rewrite" || cls === "validate" || cls === "concurrently";
|
|
72
|
+
const IDENT = String.raw `(?:"(?:[^"]|"")+"|[A-Za-z_][A-Za-z0-9_$]*)`;
|
|
73
|
+
const CONCURRENT_INDEX = new RegExp(String.raw `^\s*CREATE\s+(?:UNIQUE\s+)?INDEX\s+CONCURRENTLY\s+(?:IF\s+NOT\s+EXISTS\s+)?(${IDENT})\s+ON\s+(?:ONLY\s+)?(?:(${IDENT})\s*\.\s*)?${IDENT}`, "i");
|
|
74
|
+
const unquote = (id) => (id.startsWith('"') ? id.slice(1, -1).replace(/""/g, '"') : id.toLowerCase());
|
|
75
|
+
/** The index a `CREATE INDEX CONCURRENTLY` builds, `schema.name` quoted, when the statement names its table's schema. */
|
|
76
|
+
export function concurrentIndex(sql) {
|
|
77
|
+
const m = CONCURRENT_INDEX.exec(sql);
|
|
78
|
+
if (!m?.[1] || !m[2])
|
|
79
|
+
return undefined;
|
|
80
|
+
return `${pgIdent(unquote(m[2]))}.${pgIdent(unquote(m[1]))}`;
|
|
81
|
+
}
|
|
82
|
+
/** Drops `index` when it is there and INVALID. Returns whether it dropped it. */
|
|
83
|
+
export async function dropInvalidIndex(client, index, timeouts, log) {
|
|
84
|
+
const [row] = await client.query("SELECT NOT i.indisvalid AS invalid FROM pg_catalog.pg_index i WHERE i.indexrelid = pg_catalog.to_regclass($1)", [index]);
|
|
85
|
+
if (row?.invalid !== true)
|
|
86
|
+
return false;
|
|
87
|
+
log(` ${index} is INVALID, left by a CONCURRENTLY build that failed; dropping it before the build`);
|
|
88
|
+
await client.query(`SET lock_timeout = ${ms(timeouts.lockTimeoutMs)}`);
|
|
89
|
+
await client.query(`DROP INDEX CONCURRENTLY IF EXISTS ${index}`);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
const defaultSleep = (n) => new Promise((r) => setTimeout(r, n));
|
|
93
|
+
/** Runs one statement to success or failure; see the module comment. */
|
|
94
|
+
export async function runPgStatement(client, step, options) {
|
|
95
|
+
const { timeouts, log } = options;
|
|
96
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
97
|
+
const base = options.retryBaseMs ?? DEFAULT_RETRY_BASE_MS;
|
|
98
|
+
const statementTimeout = scansRows(step.class) ? timeouts.scanTimeoutMs : timeouts.statementTimeoutMs;
|
|
99
|
+
const index = step.transactional ? undefined : concurrentIndex(step.sql);
|
|
100
|
+
const droppedInvalid = [];
|
|
101
|
+
const lockWaits = [];
|
|
102
|
+
const note = () => {
|
|
103
|
+
const parts = [];
|
|
104
|
+
if (lockWaits.length > 0)
|
|
105
|
+
parts.push(`lock_timeout ${String(timeouts.lockTimeoutMs)}ms hit ${String(lockWaits.length)} time(s); succeeded on attempt ${String(lockWaits.length + 1)}`);
|
|
106
|
+
if (droppedInvalid.length > 0)
|
|
107
|
+
parts.push(`dropped INVALID index ${droppedInvalid.join(", ")} before building it again`);
|
|
108
|
+
return parts.join("; ");
|
|
109
|
+
};
|
|
110
|
+
const cleanIndex = async () => {
|
|
111
|
+
if (index === undefined)
|
|
112
|
+
return;
|
|
113
|
+
try {
|
|
114
|
+
if (await dropInvalidIndex(client, index, timeouts, log))
|
|
115
|
+
droppedInvalid.push(index);
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
log(` could not drop the INVALID index ${index}: ${messageOf(e)}; the next run tries again`);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
for (let attempt = 1;; attempt++) {
|
|
122
|
+
try {
|
|
123
|
+
if (step.transactional) {
|
|
124
|
+
await client.query("BEGIN");
|
|
125
|
+
try {
|
|
126
|
+
await client.query(`SET LOCAL lock_timeout = ${ms(timeouts.lockTimeoutMs)}`);
|
|
127
|
+
await client.query(`SET LOCAL statement_timeout = ${ms(statementTimeout)}`);
|
|
128
|
+
await client.query(step.sql);
|
|
129
|
+
await options.succeeded(note());
|
|
130
|
+
await client.query("COMMIT");
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
await client.query("ROLLBACK").catch(() => undefined);
|
|
134
|
+
throw e;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
await cleanIndex();
|
|
139
|
+
try {
|
|
140
|
+
await client.query(`SET lock_timeout = ${ms(timeouts.lockTimeoutMs)}`);
|
|
141
|
+
await client.query(`SET statement_timeout = ${ms(statementTimeout)}`);
|
|
142
|
+
await client.query(step.sql);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
await cleanIndex();
|
|
146
|
+
throw e;
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
await client.query("SET lock_timeout TO DEFAULT").catch(() => undefined);
|
|
150
|
+
await client.query("SET statement_timeout TO DEFAULT").catch(() => undefined);
|
|
151
|
+
}
|
|
152
|
+
await options.succeeded(note());
|
|
153
|
+
}
|
|
154
|
+
return { attempts: attempt, droppedInvalid, note: note() };
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
const code = sqlstate(e);
|
|
158
|
+
if (code === LOCK_NOT_AVAILABLE && attempt <= options.retries) {
|
|
159
|
+
lockWaits.push(attempt);
|
|
160
|
+
const wait = base * 2 ** (attempt - 1);
|
|
161
|
+
log(` lock_timeout ${String(timeouts.lockTimeoutMs)}ms: another session holds a lock this statement needs; trying again in ${String(wait)}ms (${String(attempt)}/${String(options.retries)})`);
|
|
162
|
+
await sleep(wait);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const message = messageOf(e);
|
|
166
|
+
throw new PgStatementError(code === LOCK_NOT_AVAILABLE
|
|
167
|
+
? `${message} (lock_timeout ${String(timeouts.lockTimeoutMs)}ms, tried ${String(attempt)} times: another session kept a lock this statement needs; SQLSTATE 55P03)`
|
|
168
|
+
: message, code, attempt);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/versioned/postgres/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The versioned path on Postgres (#13): the driver the engine runs, and its
|
|
3
|
+
* parts.
|
|
4
|
+
*
|
|
5
|
+
* openPostgres(project, env) the server, the history store, the driver
|
|
6
|
+
* runPgStatement(client, step) one statement under lock_timeout, retried, with its row
|
|
7
|
+
* readPgCatalog / pgCatalogFingerprint the live schema the plan digest covers
|
|
8
|
+
*/
|
|
9
|
+
export * from "./catalog.js";
|
|
10
|
+
export * from "./driver.js";
|
|
11
|
+
export * from "./executor.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The versioned path on Postgres (#13): the driver the engine runs, and its
|
|
3
|
+
* parts.
|
|
4
|
+
*
|
|
5
|
+
* openPostgres(project, env) the server, the history store, the driver
|
|
6
|
+
* runPgStatement(client, step) one statement under lock_timeout, retried, with its row
|
|
7
|
+
* readPgCatalog / pgCatalogFingerprint the live schema the plan digest covers
|
|
8
|
+
*/
|
|
9
|
+
export * from "./catalog.js";
|
|
10
|
+
export * from "./driver.js";
|
|
11
|
+
export * from "./executor.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/versioned/postgres/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** The versioned status as text and as JSON, for `yodel status` and `yodel apply --plan`. */
|
|
2
|
+
import type { SqlDialect } from "../project.js";
|
|
3
|
+
import { type HistoryLocation } from "../history/index.js";
|
|
4
|
+
import { type VersionedStatus } from "./state.js";
|
|
5
|
+
export interface StatusReport {
|
|
6
|
+
environment: string;
|
|
7
|
+
/** Postgres has no topology: its report leaves it out. Default ClickHouse. */
|
|
8
|
+
dialect?: SqlDialect | undefined;
|
|
9
|
+
location: HistoryLocation;
|
|
10
|
+
/** The topology statements are rendered for, and where it came from: `cluster:main (yodel.config.ts)`. Default: the history's. */
|
|
11
|
+
topology?: string | undefined;
|
|
12
|
+
status: VersionedStatus;
|
|
13
|
+
/** The digest `yodel apply` would ask approval for, when it would not refuse. */
|
|
14
|
+
digest?: string | undefined;
|
|
15
|
+
/** Why `yodel apply` would refuse, with its exit code. */
|
|
16
|
+
refusal?: {
|
|
17
|
+
exitCode: number;
|
|
18
|
+
message: string;
|
|
19
|
+
} | undefined;
|
|
20
|
+
}
|
|
21
|
+
export declare function statusJson(r: StatusReport): Record<string, unknown>;
|
|
22
|
+
export declare function renderStatus(r: StatusReport): string;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** The versioned status as text and as JSON, for `yodel status` and `yodel apply --plan`. */
|
|
2
|
+
import { describeTopology } from "../history/index.js";
|
|
3
|
+
import { describeStep } from "../steps/index.js";
|
|
4
|
+
import { outOfOrder, partWay } from "./state.js";
|
|
5
|
+
export function statusJson(r) {
|
|
6
|
+
const { status } = r;
|
|
7
|
+
return {
|
|
8
|
+
environment: r.environment,
|
|
9
|
+
...(r.dialect === "postgres"
|
|
10
|
+
? { history: { database: r.location.database } }
|
|
11
|
+
: { history: { database: r.location.database, topology: describeTopology(r.location.topology) }, topology: r.topology ?? describeTopology(r.location.topology) }),
|
|
12
|
+
applied: status.applied.map((a) => ({
|
|
13
|
+
id: a.id,
|
|
14
|
+
checksum: a.checksum,
|
|
15
|
+
appliedBy: a.appliedBy,
|
|
16
|
+
recordedAt: a.recordedAt,
|
|
17
|
+
planDigest: a.planDigest,
|
|
18
|
+
inDirectory: a.index !== undefined,
|
|
19
|
+
...(a.repairs ? { repairs: a.repairs.map((r) => ({ checksum: r.checksum, by: r.by, at: r.at, reason: r.reason })) } : {}),
|
|
20
|
+
})),
|
|
21
|
+
pending: status.pending.map((p) => ({
|
|
22
|
+
id: p.id,
|
|
23
|
+
checksum: p.checksum,
|
|
24
|
+
outOfOrder: p.outOfOrder,
|
|
25
|
+
partWay: p.partWay ?? null,
|
|
26
|
+
opSteps: p.opSteps.map(({ index, step }) => ({ index, kind: step.kind, object: step.object, name: step.name, ...(step.kind === "op" ? { op: step.op } : {}) })),
|
|
27
|
+
refusedSteps: p.refusedSteps.map(({ index, step, reason }) => ({ index, kind: step.kind, object: step.object, name: step.name, ...(step.kind === "op" ? { op: step.op } : {}), reason })),
|
|
28
|
+
})),
|
|
29
|
+
outOfOrder: outOfOrder(status).map((p) => p.id),
|
|
30
|
+
partWay: partWay(status).map((p) => ({ id: p.id, resumeAt: p.partWay?.resumeAt, failedStatement: p.partWay?.failedStatement ?? null })),
|
|
31
|
+
mismatches: status.mismatches,
|
|
32
|
+
...(r.digest ? { planDigest: r.digest } : {}),
|
|
33
|
+
...(r.refusal ? { refusal: r.refusal } : {}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function renderStatus(r) {
|
|
37
|
+
const { status } = r;
|
|
38
|
+
const topology = r.dialect === "postgres" ? "" : `, topology ${r.topology ?? describeTopology(r.location.topology)}`;
|
|
39
|
+
const lines = [`Migrations in ${r.environment} (history ${r.location.database}.history${topology})`, ""];
|
|
40
|
+
lines.push(status.applied.length === 0 ? "Applied: none" : `Applied (${String(status.applied.length)}):`);
|
|
41
|
+
for (const a of status.applied) {
|
|
42
|
+
lines.push(` ${a.id}${a.index === undefined ? " (not in the directory)" : ""} ${a.recordedAt} by ${a.appliedBy}`);
|
|
43
|
+
for (const r of a.repairs ?? [])
|
|
44
|
+
lines.push(` repaired ${r.at} by ${r.by}: ${r.reason}`);
|
|
45
|
+
}
|
|
46
|
+
lines.push("", status.pending.length === 0 ? "Pending: none" : `Pending (${String(status.pending.length)}):`);
|
|
47
|
+
for (const p of status.pending) {
|
|
48
|
+
const marks = [];
|
|
49
|
+
if (p.outOfOrder)
|
|
50
|
+
marks.push("out of order");
|
|
51
|
+
if (p.partWay) {
|
|
52
|
+
const pw = p.partWay;
|
|
53
|
+
marks.push(pw.status === "failed"
|
|
54
|
+
? `failed part way at statement ${String(pw.failedStatement ?? pw.resumeAt)}; resumes at statement ${String(pw.resumeAt)}`
|
|
55
|
+
: `stopped part way; resumes at statement ${String(pw.resumeAt)}`);
|
|
56
|
+
if (pw.edited)
|
|
57
|
+
marks.push("edited since; the statements that ran are unchanged");
|
|
58
|
+
}
|
|
59
|
+
if (p.opSteps.length > 0)
|
|
60
|
+
marks.push(p.opSteps.map(({ index, step }) => `step ${String(index)}: ${describeStep(step)}`).join(", "));
|
|
61
|
+
if (p.refusedSteps.length > 0)
|
|
62
|
+
marks.push(`${String(p.refusedSteps.length)} step(s) yodel apply does not run`);
|
|
63
|
+
lines.push(` ${p.id}${marks.length > 0 ? ` (${marks.join("; ")})` : ""}`);
|
|
64
|
+
if (p.partWay?.error)
|
|
65
|
+
lines.push(` error: ${p.partWay.error.split("\n")[0] ?? ""}`);
|
|
66
|
+
}
|
|
67
|
+
const late = outOfOrder(status);
|
|
68
|
+
if (late.length > 0)
|
|
69
|
+
lines.push("", `Out of order (${String(late.length)}): ${late.map((p) => p.id).join(", ")}; apply with --allow-out-of-order`);
|
|
70
|
+
if (status.mismatches.length > 0) {
|
|
71
|
+
lines.push("", `Checksum mismatches (${String(status.mismatches.length)}):`);
|
|
72
|
+
for (const m of status.mismatches)
|
|
73
|
+
lines.push(` ${m.message}`);
|
|
74
|
+
}
|
|
75
|
+
if (r.digest)
|
|
76
|
+
lines.push("", `Plan digest: ${r.digest}`);
|
|
77
|
+
if (r.refusal)
|
|
78
|
+
lines.push("", r.refusal.message);
|
|
79
|
+
return `${lines.join("\n")}\n`;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/versioned/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The migrations directory against the history: what is applied, pending,
|
|
3
|
+
* out of order, part way, or changed since it ran. Pure.
|
|
4
|
+
*
|
|
5
|
+
* ## Order, and "out of order"
|
|
6
|
+
*
|
|
7
|
+
* The order is the chain `readMigrations` returns: parent links from the
|
|
8
|
+
* first migration to the newest, never the ids' timestamps. A pending
|
|
9
|
+
* migration is out of order when the chain puts it before a migration the
|
|
10
|
+
* history records applied: it was merged (or rebased into place) after a
|
|
11
|
+
* migration that follows it had already run here. It is reported, refused
|
|
12
|
+
* unless the run passes `--allow-out-of-order`, and never skipped: with the
|
|
13
|
+
* flag it runs, in chain order with the other pending ones.
|
|
14
|
+
*
|
|
15
|
+
* ## Checksums
|
|
16
|
+
*
|
|
17
|
+
* Every applied migration's checksum in the history is compared with its
|
|
18
|
+
* files' checksum, recomputed, on every run; a mismatch refuses (`yodel
|
|
19
|
+
* repair`, #15, records an intended edit). A migration the history records
|
|
20
|
+
* applied that is gone from the directory refuses the same way. A
|
|
21
|
+
* migration that failed part way may be edited before it resumes (to fix
|
|
22
|
+
* the statement that failed), as long as every statement that already
|
|
23
|
+
* succeeded is unchanged: those are compared statement by statement.
|
|
24
|
+
*/
|
|
25
|
+
import type { MigrationStep } from "@intentius/chant-lexicon-sql/migration-statements";
|
|
26
|
+
import { type Migration } from "../migrations/index.js";
|
|
27
|
+
import { type HistoryState, type Repair } from "../history/index.js";
|
|
28
|
+
export interface AppliedMigration {
|
|
29
|
+
id: string;
|
|
30
|
+
checksum: string;
|
|
31
|
+
appliedBy: string;
|
|
32
|
+
/** When it was applied; a later repair does not change it. */
|
|
33
|
+
recordedAt: string;
|
|
34
|
+
planDigest: string;
|
|
35
|
+
/** Its position in the chain; `undefined` when the directory no longer has it. */
|
|
36
|
+
index: number | undefined;
|
|
37
|
+
/** `yodel repair` records since it was applied, oldest first. */
|
|
38
|
+
repairs?: Repair[] | undefined;
|
|
39
|
+
}
|
|
40
|
+
export interface PartWay {
|
|
41
|
+
/** The latest migration row's status: `failed` (a statement failed) or `started` (the runner stopped). */
|
|
42
|
+
status: "failed" | "started";
|
|
43
|
+
/** The index (in `steps`) of the first statement that has not succeeded: where it resumes. */
|
|
44
|
+
resumeAt: number;
|
|
45
|
+
/** The statement that failed, when one did. */
|
|
46
|
+
failedStatement: number | undefined;
|
|
47
|
+
error: string;
|
|
48
|
+
/** The indexes of the statements that succeeded and are never sent again. */
|
|
49
|
+
done: number[];
|
|
50
|
+
/** Its files changed since it ran part way (only statements not yet run). */
|
|
51
|
+
edited: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface PendingMigration {
|
|
54
|
+
id: string;
|
|
55
|
+
/** Its position in the chain. */
|
|
56
|
+
index: number;
|
|
57
|
+
/** The checksum of its files, recomputed. */
|
|
58
|
+
checksum: string;
|
|
59
|
+
/** Before a migration the history records applied. */
|
|
60
|
+
outOfOrder: boolean;
|
|
61
|
+
partWay: PartWay | undefined;
|
|
62
|
+
/** Its Op steps `apply` runs: a ClickHouse rebuild, a backfill (#12). */
|
|
63
|
+
opSteps: Array<{
|
|
64
|
+
index: number;
|
|
65
|
+
step: Exclude<MigrationStep, {
|
|
66
|
+
kind: "statement";
|
|
67
|
+
}>;
|
|
68
|
+
}>;
|
|
69
|
+
/** Its steps `apply` does not run (a manual step, an Op it does not run), each with why. Any of them refuses the run. */
|
|
70
|
+
refusedSteps: Array<{
|
|
71
|
+
index: number;
|
|
72
|
+
step: Exclude<MigrationStep, {
|
|
73
|
+
kind: "statement";
|
|
74
|
+
}>;
|
|
75
|
+
reason: string;
|
|
76
|
+
}>;
|
|
77
|
+
migration: Migration;
|
|
78
|
+
}
|
|
79
|
+
export type Mismatch = {
|
|
80
|
+
kind: "applied";
|
|
81
|
+
id: string;
|
|
82
|
+
recorded: string;
|
|
83
|
+
actual: string;
|
|
84
|
+
message: string;
|
|
85
|
+
} | {
|
|
86
|
+
kind: "part-way";
|
|
87
|
+
id: string;
|
|
88
|
+
statement: number;
|
|
89
|
+
message: string;
|
|
90
|
+
} | {
|
|
91
|
+
kind: "missing";
|
|
92
|
+
id: string;
|
|
93
|
+
recorded: string;
|
|
94
|
+
message: string;
|
|
95
|
+
};
|
|
96
|
+
export interface VersionedStatus {
|
|
97
|
+
/** In chain order; then any the directory no longer has, in the order they were applied. */
|
|
98
|
+
applied: AppliedMigration[];
|
|
99
|
+
/** In chain order. */
|
|
100
|
+
pending: PendingMigration[];
|
|
101
|
+
mismatches: Mismatch[];
|
|
102
|
+
}
|
|
103
|
+
export declare const outOfOrder: (s: VersionedStatus) => PendingMigration[];
|
|
104
|
+
export declare const partWay: (s: VersionedStatus) => PendingMigration[];
|
|
105
|
+
/** A migration's Op steps, split into the ones apply runs and the ones it refuses. A backfill step whose module is not among the migration's files is refused. */
|
|
106
|
+
export declare function classifySteps(m: Migration): Pick<PendingMigration, "opSteps" | "refusedSteps">;
|
|
107
|
+
/** Compares the chain with the history. */
|
|
108
|
+
export declare function compareHistory(ordered: readonly Migration[], state: HistoryState): VersionedStatus;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The migrations directory against the history: what is applied, pending,
|
|
3
|
+
* out of order, part way, or changed since it ran. Pure.
|
|
4
|
+
*
|
|
5
|
+
* ## Order, and "out of order"
|
|
6
|
+
*
|
|
7
|
+
* The order is the chain `readMigrations` returns: parent links from the
|
|
8
|
+
* first migration to the newest, never the ids' timestamps. A pending
|
|
9
|
+
* migration is out of order when the chain puts it before a migration the
|
|
10
|
+
* history records applied: it was merged (or rebased into place) after a
|
|
11
|
+
* migration that follows it had already run here. It is reported, refused
|
|
12
|
+
* unless the run passes `--allow-out-of-order`, and never skipped: with the
|
|
13
|
+
* flag it runs, in chain order with the other pending ones.
|
|
14
|
+
*
|
|
15
|
+
* ## Checksums
|
|
16
|
+
*
|
|
17
|
+
* Every applied migration's checksum in the history is compared with its
|
|
18
|
+
* files' checksum, recomputed, on every run; a mismatch refuses (`yodel
|
|
19
|
+
* repair`, #15, records an intended edit). A migration the history records
|
|
20
|
+
* applied that is gone from the directory refuses the same way. A
|
|
21
|
+
* migration that failed part way may be edited before it resumes (to fix
|
|
22
|
+
* the statement that failed), as long as every statement that already
|
|
23
|
+
* succeeded is unchanged: those are compared statement by statement.
|
|
24
|
+
*/
|
|
25
|
+
import { computeChecksum } from "../migrations/index.js";
|
|
26
|
+
import { isApplied, statementDone } from "../history/index.js";
|
|
27
|
+
import { planStep, stepSha } from "../steps/index.js";
|
|
28
|
+
export const outOfOrder = (s) => s.pending.filter((p) => p.outOfOrder);
|
|
29
|
+
export const partWay = (s) => s.pending.filter((p) => p.partWay !== undefined);
|
|
30
|
+
/** How to record an intended edit of migration `id`. */
|
|
31
|
+
const repair = (id) => `if the edit is intended, record it with yodel repair ${id} --reason ... <env>`;
|
|
32
|
+
function partWayOf(m, rec, actual) {
|
|
33
|
+
const done = [];
|
|
34
|
+
let resumeAt = m.document.steps.length;
|
|
35
|
+
let mismatch;
|
|
36
|
+
m.document.steps.forEach((step, i) => {
|
|
37
|
+
if (statementDone(rec, i)) {
|
|
38
|
+
done.push(i);
|
|
39
|
+
const sha = stepSha(step, m.files);
|
|
40
|
+
if (!mismatch && rec.statements.get(i)?.sha !== sha) {
|
|
41
|
+
mismatch = {
|
|
42
|
+
kind: "part-way",
|
|
43
|
+
id: m.id,
|
|
44
|
+
statement: i,
|
|
45
|
+
message: `${m.id} ran part way, and statement ${String(i)}, which succeeded, has changed in its files since; ${repair(m.id)}`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (resumeAt === m.document.steps.length) {
|
|
50
|
+
resumeAt = i;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const failed = [...rec.statements.values()].filter((s) => s.status === "failed").sort((a, b) => b.seq - a.seq)[0];
|
|
54
|
+
return {
|
|
55
|
+
partWay: {
|
|
56
|
+
status: rec.status === "failed" ? "failed" : "started",
|
|
57
|
+
resumeAt,
|
|
58
|
+
failedStatement: failed && !statementDone(rec, failed.index) ? failed.index : undefined,
|
|
59
|
+
error: rec.error || failed?.error || "",
|
|
60
|
+
done,
|
|
61
|
+
edited: rec.checksum !== actual,
|
|
62
|
+
},
|
|
63
|
+
...(mismatch ? { mismatch } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** Why a step apply runs on one dialect is refused in a migration of the other, or `undefined`. */
|
|
67
|
+
function dialectRefusal(run, dialect) {
|
|
68
|
+
if (run === "rebuild" && dialect !== "clickhouse")
|
|
69
|
+
return `a ClickHouseRebuildOp step in a ${dialect} migration`;
|
|
70
|
+
if (run === "pgMigration" && dialect !== "postgres")
|
|
71
|
+
return `a PostgresMigrationOp step in a ${dialect} migration`;
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
/** A migration's Op steps, split into the ones apply runs and the ones it refuses. A backfill step whose module is not among the migration's files is refused. */
|
|
75
|
+
export function classifySteps(m) {
|
|
76
|
+
const opSteps = [];
|
|
77
|
+
const refusedSteps = [];
|
|
78
|
+
m.document.steps.forEach((step, index) => {
|
|
79
|
+
if (step.kind === "statement")
|
|
80
|
+
return;
|
|
81
|
+
const plan = planStep(step);
|
|
82
|
+
const wrongDialect = dialectRefusal(plan.run, m.document.dialect);
|
|
83
|
+
if (plan.run === "refused")
|
|
84
|
+
refusedSteps.push({ index, step, reason: plan.reason });
|
|
85
|
+
else if (wrongDialect)
|
|
86
|
+
refusedSteps.push({ index, step, reason: wrongDialect });
|
|
87
|
+
else if (plan.run === "backfill" && m.files.extra?.[plan.file] === undefined) {
|
|
88
|
+
refusedSteps.push({ index, step, reason: `a backfill step whose module ${plan.file} is not in ${m.id}'s directory` });
|
|
89
|
+
}
|
|
90
|
+
else
|
|
91
|
+
opSteps.push({ index, step });
|
|
92
|
+
});
|
|
93
|
+
return { opSteps, refusedSteps };
|
|
94
|
+
}
|
|
95
|
+
/** Compares the chain with the history. */
|
|
96
|
+
export function compareHistory(ordered, state) {
|
|
97
|
+
const position = new Map(ordered.map((m, i) => [m.id, i]));
|
|
98
|
+
const mismatches = [];
|
|
99
|
+
const applied = [];
|
|
100
|
+
let lastApplied = -1;
|
|
101
|
+
for (const [i, m] of ordered.entries()) {
|
|
102
|
+
const rec = state.byId.get(m.id);
|
|
103
|
+
if (!rec || !isApplied(rec))
|
|
104
|
+
continue;
|
|
105
|
+
lastApplied = i;
|
|
106
|
+
const actual = computeChecksum(m.files);
|
|
107
|
+
applied.push({ id: m.id, checksum: rec.checksum, appliedBy: rec.appliedBy, recordedAt: rec.recordedAt, planDigest: rec.planDigest, index: i, ...(rec.repairs.length > 0 ? { repairs: rec.repairs } : {}) });
|
|
108
|
+
if (rec.checksum !== actual) {
|
|
109
|
+
mismatches.push({
|
|
110
|
+
kind: "applied",
|
|
111
|
+
id: m.id,
|
|
112
|
+
recorded: rec.checksum,
|
|
113
|
+
actual,
|
|
114
|
+
message: `${m.id} was applied with checksum ${rec.checksum}, but its files now hash to ${actual}; ${repair(m.id)}`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const gone = state.migrations.filter((r) => isApplied(r) && !position.has(r.id)).sort((a, b) => (a.appliedSeq ?? 0) - (b.appliedSeq ?? 0));
|
|
119
|
+
for (const r of gone) {
|
|
120
|
+
applied.push({ id: r.id, checksum: r.checksum, appliedBy: r.appliedBy, recordedAt: r.recordedAt, planDigest: r.planDigest, index: undefined, ...(r.repairs.length > 0 ? { repairs: r.repairs } : {}) });
|
|
121
|
+
mismatches.push({
|
|
122
|
+
kind: "missing",
|
|
123
|
+
id: r.id,
|
|
124
|
+
recorded: r.checksum,
|
|
125
|
+
message: `${r.id} is recorded applied, but the migrations directory no longer has it; restore it, or ${repair(r.id)}`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const pending = [];
|
|
129
|
+
for (const [i, m] of ordered.entries()) {
|
|
130
|
+
const rec = state.byId.get(m.id);
|
|
131
|
+
if (isApplied(rec))
|
|
132
|
+
continue;
|
|
133
|
+
const actual = computeChecksum(m.files);
|
|
134
|
+
let pw;
|
|
135
|
+
if (rec) {
|
|
136
|
+
const r = partWayOf(m, rec, actual);
|
|
137
|
+
pw = r.partWay;
|
|
138
|
+
if (r.mismatch)
|
|
139
|
+
mismatches.push(r.mismatch);
|
|
140
|
+
}
|
|
141
|
+
pending.push({
|
|
142
|
+
id: m.id,
|
|
143
|
+
index: i,
|
|
144
|
+
checksum: actual,
|
|
145
|
+
outOfOrder: i < lastApplied,
|
|
146
|
+
partWay: pw,
|
|
147
|
+
...classifySteps(m),
|
|
148
|
+
migration: m,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return { applied, pending, mismatches };
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/versioned/state.ts"],"names":[],"mappings":"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"}
|