@intentius/sql-yodeler 0.0.0-stage → 0.2.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 +112 -2
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +29 -0
- package/dist/bin.js.map +1 -0
- package/dist/chant/apply.d.ts +59 -0
- package/dist/chant/apply.js +116 -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 +112 -0
- package/dist/chant/drift.js +238 -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/chant/runnable.d.ts +19 -0
- package/dist/chant/runnable.js +47 -0
- package/dist/chant/runnable.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/command.d.ts +23 -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 +426 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/approve.d.ts +5 -0
- package/dist/commands/approve.js +111 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/drift.d.ts +14 -0
- package/dist/commands/drift.js +267 -0
- package/dist/commands/drift.js.map +1 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +28 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.js +139 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/lint.d.ts +3 -0
- package/dist/commands/lint.js +202 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.js +50 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/new.d.ts +5 -0
- package/dist/commands/new.js +292 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/override.d.ts +3 -0
- package/dist/commands/override.js +118 -0
- package/dist/commands/override.js.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.js +183 -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 +14 -0
- package/dist/commands/repair.js +125 -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 +148 -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 +162 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/settings.d.ts +53 -0
- package/dist/config/settings.js +116 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/env-args.d.ts +24 -0
- package/dist/env-args.js +92 -0
- package/dist/env-args.js.map +1 -0
- package/dist/exit.d.ts +20 -0
- package/dist/exit.js +28 -0
- package/dist/exit.js.map +1 -0
- package/dist/history/client.d.ts +25 -0
- package/dist/history/client.js +42 -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 +104 -0
- package/dist/history/lock.js +230 -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 +143 -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 +39 -0
- package/dist/init/live.js +68 -0
- package/dist/init/live.js.map +1 -0
- package/dist/lint/check.d.ts +88 -0
- package/dist/lint/check.js +227 -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/mcp/server.d.ts +40 -0
- package/dist/mcp/server.js +106 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +72 -0
- package/dist/mcp/tools.js +178 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/migrations/checks.d.ts +28 -0
- package/dist/migrations/checks.js +97 -0
- package/dist/migrations/checks.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 +75 -0
- package/dist/migrations/create.js +120 -0
- package/dist/migrations/create.js.map +1 -0
- package/dist/migrations/directory.d.ts +119 -0
- package/dist/migrations/directory.js +229 -0
- package/dist/migrations/directory.js.map +1 -0
- package/dist/migrations/document.d.ts +106 -0
- package/dist/migrations/document.js +83 -0
- package/dist/migrations/document.js.map +1 -0
- package/dist/migrations/index.d.ts +21 -0
- package/dist/migrations/index.js +22 -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 +54 -0
- package/dist/pr/forge.js +119 -0
- package/dist/pr/forge.js.map +1 -0
- package/dist/pr/issue.d.ts +68 -0
- package/dist/pr/issue.js +107 -0
- package/dist/pr/issue.js.map +1 -0
- package/dist/pr/model.d.ts +99 -0
- package/dist/pr/model.js +137 -0
- package/dist/pr/model.js.map +1 -0
- package/dist/pr/render.d.ts +29 -0
- package/dist/pr/render.js +279 -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 +39 -0
- package/dist/replay/index.js +57 -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/replay/shared.d.ts +28 -0
- package/dist/replay/shared.js +77 -0
- package/dist/replay/shared.js.map +1 -0
- package/dist/schemas.d.ts +34 -0
- package/dist/schemas.js +38 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +40 -0
- package/dist/server.js +87 -0
- package/dist/server.js.map +1 -0
- package/dist/steps/backfill.d.ts +132 -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 +155 -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/checks.d.ts +29 -0
- package/dist/versioned/checks.js +54 -0
- package/dist/versioned/checks.js.map +1 -0
- package/dist/versioned/clickhouse.d.ts +24 -0
- package/dist/versioned/clickhouse.js +42 -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 +51 -0
- package/dist/versioned/driver.js +13 -0
- package/dist/versioned/driver.js.map +1 -0
- package/dist/versioned/engine.d.ts +206 -0
- package/dist/versioned/engine.js +370 -0
- package/dist/versioned/engine.js.map +1 -0
- package/dist/versioned/explain.d.ts +123 -0
- package/dist/versioned/explain.js +294 -0
- package/dist/versioned/explain.js.map +1 -0
- package/dist/versioned/index.d.ts +46 -0
- package/dist/versioned/index.js +77 -0
- package/dist/versioned/index.js.map +1 -0
- package/dist/versioned/op.d.ts +72 -0
- package/dist/versioned/op.js +185 -0
- package/dist/versioned/op.js.map +1 -0
- package/dist/versioned/policy.d.ts +67 -0
- package/dist/versioned/policy.js +161 -0
- package/dist/versioned/policy.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 +71 -0
- package/dist/versioned/postgres/driver.js +140 -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/postgres/waits.d.ts +46 -0
- package/dist/versioned/postgres/waits.js +78 -0
- package/dist/versioned/postgres/waits.js.map +1 -0
- package/dist/versioned/report.d.ts +25 -0
- package/dist/versioned/report.js +84 -0
- package/dist/versioned/report.js.map +1 -0
- package/dist/versioned/stand-down.d.ts +30 -0
- package/dist/versioned/stand-down.js +56 -0
- package/dist/versioned/stand-down.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 +61 -4
- package/schemas/apply.schema.json +269 -0
- package/schemas/common.schema.json +213 -0
- package/schemas/drift.schema.json +36 -0
- package/schemas/init.schema.json +31 -0
- package/schemas/lint-rules.schema.json +54 -0
- package/schemas/lint.schema.json +290 -0
- package/schemas/mcp.schema.json +70 -0
- package/schemas/new.schema.json +71 -0
- package/schemas/plan.schema.json +371 -0
- package/schemas/rebase.schema.json +54 -0
- package/schemas/repair.schema.json +20 -0
- package/schemas/status.schema.json +310 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A backfill step: a data migration the author writes, run inside the
|
|
3
|
+
* migration between the statements around it, resumable from receipts.
|
|
4
|
+
*
|
|
5
|
+
* The step names a module in the migration's directory (`backfill.ts` by
|
|
6
|
+
* default) that exports a chant Op as `op` (or as its default export). Each
|
|
7
|
+
* step of its phases is an `effect()` step: one batch of the backfill, with
|
|
8
|
+
* its own receipt. The nested steps run SQL on the environment's server with
|
|
9
|
+
* the `yodelSql` activity yodel provides, or any activity chant has:
|
|
10
|
+
*
|
|
11
|
+
* import { EffectReceipt } from "@intentius/chant";
|
|
12
|
+
* import { Op, activity, effect, phase } from "@intentius/chant/op";
|
|
13
|
+
*
|
|
14
|
+
* const months = ["202601", "202602", "202603"];
|
|
15
|
+
* const batch = (m: string) =>
|
|
16
|
+
* effect(EffectReceipt(`country-${m}`, { effect: `country/${m}`, flavor: "existence" }), [
|
|
17
|
+
* activity("yodelSql", { sql: `ALTER TABLE shop.orders UPDATE country = ... WHERE toYYYYMM(ts) = ${m}` }, "atMostOnce"),
|
|
18
|
+
* ]);
|
|
19
|
+
*
|
|
20
|
+
* export const op = Op({ name: "backfill-country", overview: "...", phases: [phase("Backfill", months.map(batch))] });
|
|
21
|
+
*
|
|
22
|
+
* How a run goes is chant's `effect()` cycle, run by chant's local executor:
|
|
23
|
+
* for each batch, read its receipt; skip the batch when the receipt is there
|
|
24
|
+
* (an earlier run finished it); otherwise run its steps and write the
|
|
25
|
+
* receipt last, only when they all succeeded. A run that fails or is killed
|
|
26
|
+
* part way leaves the finished batches' receipts, so the next `yodel apply`
|
|
27
|
+
* resumes at the first batch without one and never redoes a finished one.
|
|
28
|
+
* A batch that was running when it stopped runs again: make each batch safe
|
|
29
|
+
* to repeat (an idempotent `UPDATE`, or a delete of its rows before the
|
|
30
|
+
* insert), as the rebuild's backfill does per partition.
|
|
31
|
+
*
|
|
32
|
+
* The receipts are rows on the environment's server, kept by the sql
|
|
33
|
+
* lexicon's receipt store (`sqlReceiptStore`), addressed
|
|
34
|
+
* `yodel/<env>/<migration id>/<effect>`, so the same effect name in two
|
|
35
|
+
* migrations is two receipts:
|
|
36
|
+
*
|
|
37
|
+
* - ClickHouse: `chant_receipts.receipts` (the table `ClickHouseRebuildOp`
|
|
38
|
+
* keeps its partition receipts in).
|
|
39
|
+
* - Postgres: `<history schema>.__chant_receipts`, in the schema yodel's
|
|
40
|
+
* history is in, over the apply's connection. Each batch runs in one
|
|
41
|
+
* transaction on that connection, and its receipt is written last
|
|
42
|
+
* inside it: the batch's statements and its receipt commit together or
|
|
43
|
+
* not at all, so a run killed anywhere leaves no batch half done, and a
|
|
44
|
+
* resumed backfill runs no batch twice. A batch's statements must be ones
|
|
45
|
+
* Postgres runs in a transaction block (no `CREATE INDEX CONCURRENTLY`,
|
|
46
|
+
* no `VACUUM`). The environment's `lockTimeoutMs` and `scanTimeoutMs` are
|
|
47
|
+
* the batch's `lock_timeout` and `statement_timeout`, and `yodelSql`'s
|
|
48
|
+
* `settings` are set for the batch's transaction (`set_config(..., true)`).
|
|
49
|
+
*
|
|
50
|
+
* The module is one of the migration's own files: it counts in the
|
|
51
|
+
* migration's checksum, so the plan digest an approval binds covers it, and
|
|
52
|
+
* an edit after it ran is a checksum mismatch. It is imported from the
|
|
53
|
+
* migration's directory, so it imports packages only (no relative imports).
|
|
54
|
+
* Its Op has no gates (the migration's gate approves it).
|
|
55
|
+
*/
|
|
56
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
57
|
+
import { createHash } from "node:crypto";
|
|
58
|
+
import { join } from "node:path";
|
|
59
|
+
import { pathToFileURL } from "node:url";
|
|
60
|
+
import { YodelError } from "../project.js";
|
|
61
|
+
import { gatesOf, runOp, StepOpFailed } from "./run.js";
|
|
62
|
+
import { BACKFILL_FILE, BACKFILL_OP } from "./kinds.js";
|
|
63
|
+
/** The activity a backfill's steps run SQL with: `activity("yodelSql", { sql, settings? })`. */
|
|
64
|
+
export const SQL_ACTIVITY = "yodelSql";
|
|
65
|
+
/** The step `yodel new --backfill` adds to a migration. */
|
|
66
|
+
export function backfillStep(migrationName, file = BACKFILL_FILE) {
|
|
67
|
+
return {
|
|
68
|
+
kind: "op",
|
|
69
|
+
object: "backfill",
|
|
70
|
+
type: "Yodel::Backfill",
|
|
71
|
+
name: migrationName,
|
|
72
|
+
op: BACKFILL_OP,
|
|
73
|
+
importPath: `./${file}`,
|
|
74
|
+
options: { file },
|
|
75
|
+
declaration: `the Op exported by ${file} in this migration's directory`,
|
|
76
|
+
changes: [],
|
|
77
|
+
detail: `a data backfill: the effect() steps of the Op in ${file}, each a batch with its own receipt; yodel apply runs it after the statements before it and resumes it from its receipts`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** Text only the template holds: a backfill still carrying it has not been written. */
|
|
81
|
+
export const TEMPLATE_MARK = "write the backfill of";
|
|
82
|
+
/** What `yodel new --backfill <file>` writes at `<file>` when there is none yet. */
|
|
83
|
+
export function backfillTemplate(name, dialect = "clickhouse") {
|
|
84
|
+
const todo = dialect === "postgres"
|
|
85
|
+
? `DO $$ BEGIN RAISE EXCEPTION 'write the backfill of ${name} for batch \${b}'; END $$`
|
|
86
|
+
: `SELECT throwIf(1, 'write the backfill of ${name} for batch \${b}')`;
|
|
87
|
+
return `/**
|
|
88
|
+
* The backfill of migration ${name}. yodel apply runs the Op this file
|
|
89
|
+
* exports, after the migration's statements before the step and before
|
|
90
|
+
* those after it. Each effect() is one batch with its own receipt: a rerun
|
|
91
|
+
* after a failure skips the batches that finished. ${dialect === "postgres"
|
|
92
|
+
? `Each batch is one transaction
|
|
93
|
+
* with its receipt, so a batch that was running when a run stopped left
|
|
94
|
+
* nothing and runs again whole.`
|
|
95
|
+
: `Make each batch safe to
|
|
96
|
+
* run twice (the one running when a run stopped runs again).`}
|
|
97
|
+
*
|
|
98
|
+
* This file is copied into the migration's directory and counts in its
|
|
99
|
+
* checksum. Import packages only, no relative paths. No gates: the
|
|
100
|
+
* migration's own gate approves it.
|
|
101
|
+
*/
|
|
102
|
+
import { EffectReceipt } from "@intentius/chant";
|
|
103
|
+
import { Op, activity, effect, phase } from "@intentius/chant/op";
|
|
104
|
+
|
|
105
|
+
// The batches: months, id ranges, partitions.
|
|
106
|
+
const batches: string[] = ["202601", "202602"];
|
|
107
|
+
|
|
108
|
+
const batch = (b: string) =>
|
|
109
|
+
effect(EffectReceipt(\`${name}-\${b}\`, { effect: \`${name}/\${b}\`, flavor: "existence" }), [
|
|
110
|
+
// TODO: the SQL for one batch.
|
|
111
|
+
activity("${SQL_ACTIVITY}", { sql: \`${todo}\` }, "atMostOnce"),
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
export const op = Op({
|
|
115
|
+
name: "backfill-${name}",
|
|
116
|
+
overview: "Backfill for migration ${name}",
|
|
117
|
+
phases: [phase("Backfill", batches.map(batch))],
|
|
118
|
+
});
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
const isRecord = (v) => typeof v === "object" && v !== null;
|
|
122
|
+
/** The Op config a module exports as `op` or as its default export. */
|
|
123
|
+
export function exportedOp(mod) {
|
|
124
|
+
for (const value of [mod.op, mod.default]) {
|
|
125
|
+
const props = isRecord(value) ? value.props : undefined;
|
|
126
|
+
if (isRecord(props) && typeof props.name === "string" && Array.isArray(props.phases))
|
|
127
|
+
return props;
|
|
128
|
+
}
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
/** What is wrong with a backfill's Op, if anything: every phase step is an effect() step, and there are no gates. */
|
|
132
|
+
export function backfillProblems(config) {
|
|
133
|
+
const problems = [];
|
|
134
|
+
const steps = config.phases.flatMap((p) => p.steps.map((s) => ({ phase: p.name, s })));
|
|
135
|
+
if (steps.length === 0)
|
|
136
|
+
problems.push("its Op has no steps");
|
|
137
|
+
for (const { phase, s } of steps) {
|
|
138
|
+
if (s.kind !== "effect")
|
|
139
|
+
problems.push(`phase "${phase}" has a ${s.kind === "gate" ? `gate (${s.gate ?? "unnamed"})` : `${s.fn} step`} outside an effect(): every step of a backfill is an effect() with its receipt, so a rerun resumes`);
|
|
140
|
+
}
|
|
141
|
+
const gates = gatesOf(config);
|
|
142
|
+
if (gates.length > 0)
|
|
143
|
+
problems.push(`it has a gate (${gates.join(", ")}); the migration's own gate approves the backfill`);
|
|
144
|
+
return problems;
|
|
145
|
+
}
|
|
146
|
+
/** Imports a backfill module and returns its Op, or throws naming what is wrong. `text` busts the import cache when the file changed. */
|
|
147
|
+
export async function loadBackfill(path, text) {
|
|
148
|
+
if (!existsSync(path))
|
|
149
|
+
throw new YodelError(`${path}: no such file; the backfill step runs the Op it exports`);
|
|
150
|
+
const body = text ?? readFileSync(path, "utf8");
|
|
151
|
+
const version = createHash("sha256").update(body).digest("hex").slice(0, 16);
|
|
152
|
+
let mod;
|
|
153
|
+
try {
|
|
154
|
+
mod = (await import(`${pathToFileURL(path).href}?yodel=${version}`));
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
throw new YodelError(`${path}: could not load it: ${e instanceof Error ? e.message : String(e)}`);
|
|
158
|
+
}
|
|
159
|
+
const config = exportedOp(mod);
|
|
160
|
+
if (!config)
|
|
161
|
+
throw new YodelError(`${path} exports no Op (export const op = Op({ ... }), or a default export)`);
|
|
162
|
+
const problems = backfillProblems(config);
|
|
163
|
+
if (problems.length > 0)
|
|
164
|
+
throw new YodelError(`${path}: ${problems.join("; ")}`);
|
|
165
|
+
return config;
|
|
166
|
+
}
|
|
167
|
+
/** A receipt store whose every effect is under `prefix`, so receipts of different migrations never meet. */
|
|
168
|
+
export function prefixedStore(store, prefix) {
|
|
169
|
+
return {
|
|
170
|
+
read: (r) => store.read({ ...r, effect: `${prefix}${r.effect}` }),
|
|
171
|
+
write: (r, expectation) => store.write({ ...r, effect: `${prefix}${r.effect}` }, expectation),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* The sql lexicon's receipt store on the environment's server, under the
|
|
176
|
+
* stack `yodel`. On Postgres it writes over the apply's connection (so a
|
|
177
|
+
* receipt written inside a batch's transaction commits with it, and the
|
|
178
|
+
* store never closes it), and the table is made here, before any batch's
|
|
179
|
+
* transaction opens.
|
|
180
|
+
*/
|
|
181
|
+
export async function serverReceipts(server, environment) {
|
|
182
|
+
const { sqlReceiptStore } = await import("@intentius/chant-lexicon-sql/receipts");
|
|
183
|
+
const where = "clickhouse" in server
|
|
184
|
+
? { clickhouse: { endpoint: server.clickhouse } }
|
|
185
|
+
: { postgres: { query: (sql, params) => server.postgres.query(sql, params), end: () => Promise.resolve() }, schema: server.schema };
|
|
186
|
+
const store = sqlReceiptStore({ environment, stack: "yodel", config: {}, ...where });
|
|
187
|
+
if ("postgres" in server)
|
|
188
|
+
await store.ensure();
|
|
189
|
+
return store;
|
|
190
|
+
}
|
|
191
|
+
function clickhouseBatches(port) {
|
|
192
|
+
return {
|
|
193
|
+
next: () => Promise.resolve(),
|
|
194
|
+
sql: async (sql, settings) => (await port.query(sql, settings ? { settings } : {})).length,
|
|
195
|
+
done: () => Promise.resolve(),
|
|
196
|
+
abandon: () => Promise.resolve(),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/** Each batch in one transaction, begun at its first statement and committed after its receipt. */
|
|
200
|
+
function postgresBatches(server) {
|
|
201
|
+
const { client, timeouts } = server;
|
|
202
|
+
let open = false;
|
|
203
|
+
/** Why this batch's transaction was rolled back: its later statements (an activity's retry) do not run without the earlier ones. */
|
|
204
|
+
let lost;
|
|
205
|
+
const rollback = async () => {
|
|
206
|
+
if (!open)
|
|
207
|
+
return;
|
|
208
|
+
open = false;
|
|
209
|
+
await client.query("ROLLBACK").catch(() => undefined);
|
|
210
|
+
};
|
|
211
|
+
return {
|
|
212
|
+
async next() {
|
|
213
|
+
await rollback();
|
|
214
|
+
lost = undefined;
|
|
215
|
+
},
|
|
216
|
+
async sql(sql, settings) {
|
|
217
|
+
if (lost !== undefined)
|
|
218
|
+
throw new Error(`this batch's transaction was rolled back (${lost}); the batch runs again whole on the next yodel apply`);
|
|
219
|
+
try {
|
|
220
|
+
if (!open) {
|
|
221
|
+
await client.query("BEGIN");
|
|
222
|
+
open = true;
|
|
223
|
+
await client.query(`SET LOCAL lock_timeout = '${String(Math.max(0, Math.floor(timeouts.lockTimeoutMs)))}ms'`);
|
|
224
|
+
await client.query(`SET LOCAL statement_timeout = '${String(Math.max(0, Math.floor(timeouts.scanTimeoutMs)))}ms'`);
|
|
225
|
+
}
|
|
226
|
+
for (const [name, value] of Object.entries(settings ?? {}))
|
|
227
|
+
await client.query("SELECT pg_catalog.set_config($1, $2, true)", [name, value]);
|
|
228
|
+
return (await client.query(sql)).length;
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
lost = e instanceof Error ? e.message : String(e);
|
|
232
|
+
await rollback();
|
|
233
|
+
throw e;
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
async done() {
|
|
237
|
+
if (!open)
|
|
238
|
+
return;
|
|
239
|
+
open = false;
|
|
240
|
+
await client.query("COMMIT");
|
|
241
|
+
},
|
|
242
|
+
abandon: rollback,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/** Runs a backfill step to the end, counting batches as they skip or finish. */
|
|
246
|
+
export async function runBackfill(file, run) {
|
|
247
|
+
const config = await loadBackfill(join(run.dir, file), run.text);
|
|
248
|
+
const summary = { op: "backfill", file, name: config.name, effects: config.phases.reduce((n, p) => n + p.steps.length, 0), skipped: 0, ran: 0 };
|
|
249
|
+
const session = run.postgres ? postgresBatches(run.postgres) : run.port ? clickhouseBatches(run.port) : undefined;
|
|
250
|
+
if (!session)
|
|
251
|
+
throw new YodelError("a backfill step needs the environment's server to run its SQL on, and has none");
|
|
252
|
+
const { receiptActivities } = await import("@intentius/chant/op/receipt-store");
|
|
253
|
+
const store = receiptActivities(prefixedStore(run.receipts, `${run.migrationId}/`));
|
|
254
|
+
const activities = {
|
|
255
|
+
receiptRead: async (args) => {
|
|
256
|
+
// A new batch: nothing of an earlier one is left open.
|
|
257
|
+
await session.next();
|
|
258
|
+
const r = await store.receiptRead(args);
|
|
259
|
+
if (r.applied)
|
|
260
|
+
summary.skipped++;
|
|
261
|
+
return r;
|
|
262
|
+
},
|
|
263
|
+
receiptWrite: async (args) => {
|
|
264
|
+
let r;
|
|
265
|
+
try {
|
|
266
|
+
r = await store.receiptWrite(args);
|
|
267
|
+
await session.done();
|
|
268
|
+
}
|
|
269
|
+
catch (e) {
|
|
270
|
+
await session.abandon();
|
|
271
|
+
throw e;
|
|
272
|
+
}
|
|
273
|
+
summary.ran++;
|
|
274
|
+
return r;
|
|
275
|
+
},
|
|
276
|
+
receiptStaleness: (args) => store.receiptStaleness(args),
|
|
277
|
+
[SQL_ACTIVITY]: async (args) => {
|
|
278
|
+
const sql = args.sql;
|
|
279
|
+
if (typeof sql !== "string" || sql.trim() === "")
|
|
280
|
+
throw new Error(`${SQL_ACTIVITY}: needs { sql: "<statement>" }`);
|
|
281
|
+
const settings = isRecord(args.settings) ? Object.fromEntries(Object.entries(args.settings).map(([k, v]) => [k, String(v)])) : undefined;
|
|
282
|
+
run.log?.(` ${sql.split("\n")[0] ?? ""}`);
|
|
283
|
+
return { rows: await session.sql(sql, settings) };
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
try {
|
|
287
|
+
const records = await runOp(config, {
|
|
288
|
+
cwd: run.projectDir,
|
|
289
|
+
environment: run.environment,
|
|
290
|
+
activities,
|
|
291
|
+
...(run.base ? { base: run.base } : {}),
|
|
292
|
+
...(run.signal ? { signal: run.signal } : {}),
|
|
293
|
+
...(run.onRecord ? { onRecord: run.onRecord } : {}),
|
|
294
|
+
});
|
|
295
|
+
return { summary, records };
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
if (e instanceof StepOpFailed)
|
|
299
|
+
e.summary = summary;
|
|
300
|
+
throw e;
|
|
301
|
+
}
|
|
302
|
+
finally {
|
|
303
|
+
// A batch stopped part way (a failed step that was not ours, an abort) leaves nothing behind.
|
|
304
|
+
await session.abandon();
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backfill.js","sourceRoot":"","sources":["../../src/steps/backfill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Op steps inside a migration (#12): what `yodel apply` runs besides SQL.
|
|
3
|
+
*
|
|
4
|
+
* planStep(step) statement, rebuild, backfill, or refused (with why)
|
|
5
|
+
* stepSha(step, files) the hash a step's history rows record
|
|
6
|
+
* runRebuild(...) a ClickHouseRebuildOp step (./rebuild.ts)
|
|
7
|
+
* runBackfill(...) a backfill step, an Op of effect() batches (./backfill.ts)
|
|
8
|
+
* runPgMigration(...) a PostgresMigrationOp step (./postgres-migration.ts)
|
|
9
|
+
* defaultStepRunner what the versioned apply calls for an Op step
|
|
10
|
+
*/
|
|
11
|
+
import type { ReceiptStore } from "@intentius/chant/op/receipt-store";
|
|
12
|
+
import type { ClickHouseEndpoint } from "@intentius/chant-lexicon-sql/clickhouse/http";
|
|
13
|
+
import type { ClickHousePort } from "../history/index.js";
|
|
14
|
+
import type { Migration } from "../migrations/index.js";
|
|
15
|
+
import { type PgBackfillServer } from "./backfill.js";
|
|
16
|
+
import type { StepPlan } from "./kinds.js";
|
|
17
|
+
export * from "./kinds.js";
|
|
18
|
+
export * from "./run.js";
|
|
19
|
+
export * from "./rebuild.js";
|
|
20
|
+
export * from "./backfill.js";
|
|
21
|
+
export * from "./postgres-migration.js";
|
|
22
|
+
/** What running one Op step needs. */
|
|
23
|
+
export interface StepContext {
|
|
24
|
+
environment: string;
|
|
25
|
+
/** The project directory, which holds chant.config.ts. */
|
|
26
|
+
projectDir: string;
|
|
27
|
+
/** The ClickHouse server a backfill's SQL runs on; absent on Postgres. */
|
|
28
|
+
port?: ClickHousePort | undefined;
|
|
29
|
+
/** Postgres: the apply's connection a backfill's SQL runs on, its timeouts, and the schema its receipts are kept in (the history's). */
|
|
30
|
+
postgres?: (PgBackfillServer & {
|
|
31
|
+
receiptsSchema: string;
|
|
32
|
+
}) | undefined;
|
|
33
|
+
/** Postgres: the environment's lock timeout, for a PostgresMigrationOp step whose options set none. */
|
|
34
|
+
lockTimeoutMs?: number | undefined;
|
|
35
|
+
/** The server, for the backfill's receipt store; the port is enough for everything else. */
|
|
36
|
+
endpoint?: ClickHouseEndpoint | undefined;
|
|
37
|
+
migration: Migration;
|
|
38
|
+
index: number;
|
|
39
|
+
plan: Exclude<StepPlan, {
|
|
40
|
+
run: "statement";
|
|
41
|
+
} | {
|
|
42
|
+
run: "refused";
|
|
43
|
+
}>;
|
|
44
|
+
log: (line: string) => void;
|
|
45
|
+
/** A backfill's receipt store; default the sql lexicon's on the server. */
|
|
46
|
+
receipts?: ReceiptStore | undefined;
|
|
47
|
+
}
|
|
48
|
+
/** Runs one Op step to the end and returns the summary its history row records. Throws `StepOpFailed` when it stops part way. */
|
|
49
|
+
export type StepRunner = (ctx: StepContext) => Promise<{
|
|
50
|
+
summary: unknown;
|
|
51
|
+
}>;
|
|
52
|
+
export declare const defaultStepRunner: StepRunner;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Op steps inside a migration (#12): what `yodel apply` runs besides SQL.
|
|
3
|
+
*
|
|
4
|
+
* planStep(step) statement, rebuild, backfill, or refused (with why)
|
|
5
|
+
* stepSha(step, files) the hash a step's history rows record
|
|
6
|
+
* runRebuild(...) a ClickHouseRebuildOp step (./rebuild.ts)
|
|
7
|
+
* runBackfill(...) a backfill step, an Op of effect() batches (./backfill.ts)
|
|
8
|
+
* runPgMigration(...) a PostgresMigrationOp step (./postgres-migration.ts)
|
|
9
|
+
* defaultStepRunner what the versioned apply calls for an Op step
|
|
10
|
+
*/
|
|
11
|
+
import { YodelError } from "../project.js";
|
|
12
|
+
import { runBackfill, serverReceipts } from "./backfill.js";
|
|
13
|
+
import { rebuildChantConfig, runRebuild } from "./rebuild.js";
|
|
14
|
+
import { runPgMigration } from "./postgres-migration.js";
|
|
15
|
+
export * from "./kinds.js";
|
|
16
|
+
export * from "./run.js";
|
|
17
|
+
export * from "./rebuild.js";
|
|
18
|
+
export * from "./backfill.js";
|
|
19
|
+
export * from "./postgres-migration.js";
|
|
20
|
+
export const defaultStepRunner = async (ctx) => {
|
|
21
|
+
if (ctx.plan.run === "rebuild") {
|
|
22
|
+
const config = await rebuildChantConfig(ctx.projectDir, ctx.environment);
|
|
23
|
+
const { summary } = await runRebuild(ctx.plan.options, { environment: ctx.environment, projectDir: ctx.projectDir, schema: ctx.migration.document.schema, log: ctx.log, config });
|
|
24
|
+
return { summary };
|
|
25
|
+
}
|
|
26
|
+
if (ctx.plan.run === "pgMigration") {
|
|
27
|
+
const { summary } = await runPgMigration(ctx.plan.options, { environment: ctx.environment, projectDir: ctx.projectDir, schema: ctx.migration.document.schema, lockTimeoutMs: ctx.lockTimeoutMs, log: ctx.log });
|
|
28
|
+
return { summary };
|
|
29
|
+
}
|
|
30
|
+
if (!ctx.port && !ctx.postgres)
|
|
31
|
+
throw new YodelError("a backfill step runs its SQL on the environment's server, and this environment has none");
|
|
32
|
+
const receipts = ctx.receipts ??
|
|
33
|
+
(ctx.postgres
|
|
34
|
+
? await serverReceipts({ postgres: ctx.postgres.client, schema: ctx.postgres.receiptsSchema }, ctx.environment)
|
|
35
|
+
: ctx.endpoint
|
|
36
|
+
? await serverReceipts({ clickhouse: ctx.endpoint }, ctx.environment)
|
|
37
|
+
: undefined);
|
|
38
|
+
if (!receipts)
|
|
39
|
+
throw new YodelError("a backfill step needs a receipt store, and this environment has no server endpoint for one");
|
|
40
|
+
const { summary } = await runBackfill(ctx.plan.file, {
|
|
41
|
+
environment: ctx.environment,
|
|
42
|
+
projectDir: ctx.projectDir,
|
|
43
|
+
migrationId: ctx.migration.id,
|
|
44
|
+
dir: ctx.migration.dir,
|
|
45
|
+
text: ctx.migration.files.extra?.[ctx.plan.file],
|
|
46
|
+
...(ctx.postgres ? { postgres: { client: ctx.postgres.client, timeouts: ctx.postgres.timeouts } } : { port: ctx.port }),
|
|
47
|
+
receipts,
|
|
48
|
+
log: ctx.log,
|
|
49
|
+
});
|
|
50
|
+
return { summary };
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/steps/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What each step of a migration is to `yodel apply`, and the hash its
|
|
3
|
+
* history rows record.
|
|
4
|
+
*
|
|
5
|
+
* A migration's `steps` (in `migration.json`) are chant's: a `statement`
|
|
6
|
+
* apply sends as SQL, an `op` step naming the Op that makes a change no
|
|
7
|
+
* statement makes, or a `manual` step a person acts on. Apply runs two kinds
|
|
8
|
+
* of Op step itself, inside the migration and under its lock and gate:
|
|
9
|
+
*
|
|
10
|
+
* - `ClickHouseRebuildOp`, the step `yodel new` writes for a ClickHouse sort
|
|
11
|
+
* key, engine or key-column change (`./rebuild.ts`);
|
|
12
|
+
* - `backfill`, a data backfill the author writes as an Op of `effect()`
|
|
13
|
+
* steps in a module in the migration's directory (`./backfill.ts`);
|
|
14
|
+
* - `PostgresMigrationOp`, the step `yodel new` writes for a Postgres column
|
|
15
|
+
* rename or type change across kinds (`./postgres-migration.ts`, #13).
|
|
16
|
+
*
|
|
17
|
+
* Everything else (a manual step, a rebuild in app mode) is refused before
|
|
18
|
+
* anything runs, with exit 2.
|
|
19
|
+
*/
|
|
20
|
+
import type { MigrationStep } from "@intentius/chant-lexicon-sql/migration-statements";
|
|
21
|
+
import { type MigrationFiles } from "../migrations/document.js";
|
|
22
|
+
/** The `op` of a backfill step. */
|
|
23
|
+
export declare const BACKFILL_OP = "backfill";
|
|
24
|
+
/** The module a backfill step runs, in the migration's directory, unless its `options.file` names another. */
|
|
25
|
+
export declare const BACKFILL_FILE = "backfill.ts";
|
|
26
|
+
export declare const REBUILD_OP = "ClickHouseRebuildOp";
|
|
27
|
+
export declare const PG_MIGRATION_OP = "PostgresMigrationOp";
|
|
28
|
+
type OpStep = Extract<MigrationStep, {
|
|
29
|
+
kind: "op";
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* A backfill step in `migration.json`. chant's `OpStep` shape, so every
|
|
33
|
+
* reader of steps sees an Op step:
|
|
34
|
+
*
|
|
35
|
+
* { "kind": "op", "object": "backfill", "type": "Yodel::Backfill", "name": "<migration name>",
|
|
36
|
+
* "op": "backfill", "importPath": "./backfill.ts", "options": { "file": "backfill.ts" },
|
|
37
|
+
* "declaration": "...", "changes": [], "detail": "..." }
|
|
38
|
+
*/
|
|
39
|
+
export interface BackfillStep extends Omit<OpStep, "op" | "options"> {
|
|
40
|
+
op: typeof BACKFILL_OP;
|
|
41
|
+
options: {
|
|
42
|
+
file: string;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export type DualWrite = {
|
|
46
|
+
mode: "materialized-view";
|
|
47
|
+
cutoverColumn: string;
|
|
48
|
+
cutoverDelay?: string;
|
|
49
|
+
} | {
|
|
50
|
+
mode: "app";
|
|
51
|
+
};
|
|
52
|
+
export interface RebuildOptions {
|
|
53
|
+
name: string;
|
|
54
|
+
table: string;
|
|
55
|
+
dualWrite: DualWrite;
|
|
56
|
+
}
|
|
57
|
+
/** A `PostgresMigrationOp` step's options: chant's `{ name, env, table, column }`, and what the author may add (`using`, `retain`, ...). */
|
|
58
|
+
export interface PgMigrationOptions {
|
|
59
|
+
name: string;
|
|
60
|
+
table: string;
|
|
61
|
+
column: string;
|
|
62
|
+
using?: string;
|
|
63
|
+
/** How long the old column is kept after the switch; default none, so the contract runs in the same apply. */
|
|
64
|
+
retain?: string;
|
|
65
|
+
batchSize?: number;
|
|
66
|
+
replicationLag?: {
|
|
67
|
+
max?: string;
|
|
68
|
+
wait?: string;
|
|
69
|
+
} | false;
|
|
70
|
+
lockTimeoutMs?: number;
|
|
71
|
+
statementTimeoutMs?: number;
|
|
72
|
+
}
|
|
73
|
+
export type StepPlan = {
|
|
74
|
+
run: "statement";
|
|
75
|
+
} | {
|
|
76
|
+
run: "rebuild";
|
|
77
|
+
options: RebuildOptions;
|
|
78
|
+
} | {
|
|
79
|
+
run: "pgMigration";
|
|
80
|
+
options: PgMigrationOptions;
|
|
81
|
+
} | {
|
|
82
|
+
run: "backfill";
|
|
83
|
+
file: string;
|
|
84
|
+
} | {
|
|
85
|
+
run: "refused";
|
|
86
|
+
reason: string;
|
|
87
|
+
};
|
|
88
|
+
/** The step as a backfill step, when it is one. */
|
|
89
|
+
export declare const asBackfill: (step: MigrationStep | BackfillStep) => BackfillStep | undefined;
|
|
90
|
+
/** How `yodel apply` treats one step. */
|
|
91
|
+
export declare function planStep(step: MigrationStep | BackfillStep): StepPlan;
|
|
92
|
+
/** One line naming a step, for logs and refusals. */
|
|
93
|
+
export declare function describeStep(step: MigrationStep | BackfillStep): string;
|
|
94
|
+
/**
|
|
95
|
+
* The hash a step's history rows record: for a statement, its SQL's (the
|
|
96
|
+
* history's `statementSha`); for an Op step, its canonical JSON and, for a
|
|
97
|
+
* backfill, the text of the module it runs. A step that ran and has since
|
|
98
|
+
* changed is how a part-way migration's edit is caught.
|
|
99
|
+
*/
|
|
100
|
+
export declare function stepSha(step: MigrationStep | BackfillStep, files?: Pick<MigrationFiles, "extra">): string;
|
|
101
|
+
export {};
|