@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.
Files changed (324) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +112 -2
  3. package/dist/bin.d.ts +2 -0
  4. package/dist/bin.js +29 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/chant/apply.d.ts +59 -0
  7. package/dist/chant/apply.js +116 -0
  8. package/dist/chant/apply.js.map +1 -0
  9. package/dist/chant/build.d.ts +34 -0
  10. package/dist/chant/build.js +48 -0
  11. package/dist/chant/build.js.map +1 -0
  12. package/dist/chant/drift.d.ts +112 -0
  13. package/dist/chant/drift.js +238 -0
  14. package/dist/chant/drift.js.map +1 -0
  15. package/dist/chant/plan.d.ts +45 -0
  16. package/dist/chant/plan.js +61 -0
  17. package/dist/chant/plan.js.map +1 -0
  18. package/dist/chant/process.d.ts +41 -0
  19. package/dist/chant/process.js +87 -0
  20. package/dist/chant/process.js.map +1 -0
  21. package/dist/chant/runnable.d.ts +19 -0
  22. package/dist/chant/runnable.js +47 -0
  23. package/dist/chant/runnable.js.map +1 -0
  24. package/dist/cli.d.ts +8 -0
  25. package/dist/cli.js +99 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/command.d.ts +23 -0
  28. package/dist/command.js +13 -0
  29. package/dist/command.js.map +1 -0
  30. package/dist/commands/apply.d.ts +3 -0
  31. package/dist/commands/apply.js +426 -0
  32. package/dist/commands/apply.js.map +1 -0
  33. package/dist/commands/approve.d.ts +5 -0
  34. package/dist/commands/approve.js +111 -0
  35. package/dist/commands/approve.js.map +1 -0
  36. package/dist/commands/drift.d.ts +14 -0
  37. package/dist/commands/drift.js +267 -0
  38. package/dist/commands/drift.js.map +1 -0
  39. package/dist/commands/index.d.ts +3 -0
  40. package/dist/commands/index.js +28 -0
  41. package/dist/commands/index.js.map +1 -0
  42. package/dist/commands/init.d.ts +6 -0
  43. package/dist/commands/init.js +139 -0
  44. package/dist/commands/init.js.map +1 -0
  45. package/dist/commands/lint.d.ts +3 -0
  46. package/dist/commands/lint.js +202 -0
  47. package/dist/commands/lint.js.map +1 -0
  48. package/dist/commands/mcp.d.ts +3 -0
  49. package/dist/commands/mcp.js +50 -0
  50. package/dist/commands/mcp.js.map +1 -0
  51. package/dist/commands/new.d.ts +5 -0
  52. package/dist/commands/new.js +292 -0
  53. package/dist/commands/new.js.map +1 -0
  54. package/dist/commands/override.d.ts +3 -0
  55. package/dist/commands/override.js +118 -0
  56. package/dist/commands/override.js.map +1 -0
  57. package/dist/commands/plan.d.ts +3 -0
  58. package/dist/commands/plan.js +183 -0
  59. package/dist/commands/plan.js.map +1 -0
  60. package/dist/commands/rebase.d.ts +3 -0
  61. package/dist/commands/rebase.js +167 -0
  62. package/dist/commands/rebase.js.map +1 -0
  63. package/dist/commands/repair.d.ts +14 -0
  64. package/dist/commands/repair.js +125 -0
  65. package/dist/commands/repair.js.map +1 -0
  66. package/dist/commands/status.d.ts +7 -0
  67. package/dist/commands/status.js +54 -0
  68. package/dist/commands/status.js.map +1 -0
  69. package/dist/config/define.d.ts +148 -0
  70. package/dist/config/define.js +20 -0
  71. package/dist/config/define.js.map +1 -0
  72. package/dist/config/index.d.ts +11 -0
  73. package/dist/config/index.js +12 -0
  74. package/dist/config/index.js.map +1 -0
  75. package/dist/config/load.d.ts +17 -0
  76. package/dist/config/load.js +162 -0
  77. package/dist/config/load.js.map +1 -0
  78. package/dist/config/settings.d.ts +53 -0
  79. package/dist/config/settings.js +116 -0
  80. package/dist/config/settings.js.map +1 -0
  81. package/dist/env-args.d.ts +24 -0
  82. package/dist/env-args.js +92 -0
  83. package/dist/env-args.js.map +1 -0
  84. package/dist/exit.d.ts +20 -0
  85. package/dist/exit.js +28 -0
  86. package/dist/exit.js.map +1 -0
  87. package/dist/history/client.d.ts +25 -0
  88. package/dist/history/client.js +42 -0
  89. package/dist/history/client.js.map +1 -0
  90. package/dist/history/ddl.d.ts +58 -0
  91. package/dist/history/ddl.js +100 -0
  92. package/dist/history/ddl.js.map +1 -0
  93. package/dist/history/index.d.ts +25 -0
  94. package/dist/history/index.js +26 -0
  95. package/dist/history/index.js.map +1 -0
  96. package/dist/history/lock.d.ts +104 -0
  97. package/dist/history/lock.js +230 -0
  98. package/dist/history/lock.js.map +1 -0
  99. package/dist/history/postgres/ddl.d.ts +22 -0
  100. package/dist/history/postgres/ddl.js +47 -0
  101. package/dist/history/postgres/ddl.js.map +1 -0
  102. package/dist/history/postgres/index.d.ts +12 -0
  103. package/dist/history/postgres/index.js +13 -0
  104. package/dist/history/postgres/index.js.map +1 -0
  105. package/dist/history/postgres/lock.d.ts +48 -0
  106. package/dist/history/postgres/lock.js +95 -0
  107. package/dist/history/postgres/lock.js.map +1 -0
  108. package/dist/history/postgres/store.d.ts +39 -0
  109. package/dist/history/postgres/store.js +68 -0
  110. package/dist/history/postgres/store.js.map +1 -0
  111. package/dist/history/rows.d.ts +96 -0
  112. package/dist/history/rows.js +73 -0
  113. package/dist/history/rows.js.map +1 -0
  114. package/dist/history/store.d.ts +72 -0
  115. package/dist/history/store.js +134 -0
  116. package/dist/history/store.js.map +1 -0
  117. package/dist/history/topology.d.ts +41 -0
  118. package/dist/history/topology.js +54 -0
  119. package/dist/history/topology.js.map +1 -0
  120. package/dist/index.d.ts +10 -0
  121. package/dist/index.js +10 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/init/adopt.d.ts +70 -0
  124. package/dist/init/adopt.js +143 -0
  125. package/dist/init/adopt.js.map +1 -0
  126. package/dist/init/baseline.d.ts +61 -0
  127. package/dist/init/baseline.js +88 -0
  128. package/dist/init/baseline.js.map +1 -0
  129. package/dist/init/files.d.ts +23 -0
  130. package/dist/init/files.js +77 -0
  131. package/dist/init/files.js.map +1 -0
  132. package/dist/init/index.d.ts +16 -0
  133. package/dist/init/index.js +17 -0
  134. package/dist/init/index.js.map +1 -0
  135. package/dist/init/live.d.ts +39 -0
  136. package/dist/init/live.js +68 -0
  137. package/dist/init/live.js.map +1 -0
  138. package/dist/lint/check.d.ts +88 -0
  139. package/dist/lint/check.js +227 -0
  140. package/dist/lint/check.js.map +1 -0
  141. package/dist/lint/config.d.ts +21 -0
  142. package/dist/lint/config.js +43 -0
  143. package/dist/lint/config.js.map +1 -0
  144. package/dist/lint/index.d.ts +31 -0
  145. package/dist/lint/index.js +43 -0
  146. package/dist/lint/index.js.map +1 -0
  147. package/dist/lint/project-rules.d.ts +19 -0
  148. package/dist/lint/project-rules.js +32 -0
  149. package/dist/lint/project-rules.js.map +1 -0
  150. package/dist/lint/report.d.ts +7 -0
  151. package/dist/lint/report.js +48 -0
  152. package/dist/lint/report.js.map +1 -0
  153. package/dist/lint/rules.d.ts +53 -0
  154. package/dist/lint/rules.js +42 -0
  155. package/dist/lint/rules.js.map +1 -0
  156. package/dist/lint/silences.d.ts +49 -0
  157. package/dist/lint/silences.js +91 -0
  158. package/dist/lint/silences.js.map +1 -0
  159. package/dist/lint/statements.d.ts +38 -0
  160. package/dist/lint/statements.js +120 -0
  161. package/dist/lint/statements.js.map +1 -0
  162. package/dist/mcp/server.d.ts +40 -0
  163. package/dist/mcp/server.js +106 -0
  164. package/dist/mcp/server.js.map +1 -0
  165. package/dist/mcp/tools.d.ts +72 -0
  166. package/dist/mcp/tools.js +178 -0
  167. package/dist/mcp/tools.js.map +1 -0
  168. package/dist/migrations/checks.d.ts +28 -0
  169. package/dist/migrations/checks.js +97 -0
  170. package/dist/migrations/checks.js.map +1 -0
  171. package/dist/migrations/checksum.d.ts +56 -0
  172. package/dist/migrations/checksum.js +72 -0
  173. package/dist/migrations/checksum.js.map +1 -0
  174. package/dist/migrations/create.d.ts +75 -0
  175. package/dist/migrations/create.js +120 -0
  176. package/dist/migrations/create.js.map +1 -0
  177. package/dist/migrations/directory.d.ts +119 -0
  178. package/dist/migrations/directory.js +229 -0
  179. package/dist/migrations/directory.js.map +1 -0
  180. package/dist/migrations/document.d.ts +106 -0
  181. package/dist/migrations/document.js +83 -0
  182. package/dist/migrations/document.js.map +1 -0
  183. package/dist/migrations/index.d.ts +21 -0
  184. package/dist/migrations/index.js +22 -0
  185. package/dist/migrations/index.js.map +1 -0
  186. package/dist/pr/comment.d.ts +32 -0
  187. package/dist/pr/comment.js +99 -0
  188. package/dist/pr/comment.js.map +1 -0
  189. package/dist/pr/forge.d.ts +54 -0
  190. package/dist/pr/forge.js +119 -0
  191. package/dist/pr/forge.js.map +1 -0
  192. package/dist/pr/issue.d.ts +68 -0
  193. package/dist/pr/issue.js +107 -0
  194. package/dist/pr/issue.js.map +1 -0
  195. package/dist/pr/model.d.ts +99 -0
  196. package/dist/pr/model.js +137 -0
  197. package/dist/pr/model.js.map +1 -0
  198. package/dist/pr/render.d.ts +29 -0
  199. package/dist/pr/render.js +279 -0
  200. package/dist/pr/render.js.map +1 -0
  201. package/dist/project.d.ts +62 -0
  202. package/dist/project.js +92 -0
  203. package/dist/project.js.map +1 -0
  204. package/dist/rebase/index.d.ts +121 -0
  205. package/dist/rebase/index.js +390 -0
  206. package/dist/rebase/index.js.map +1 -0
  207. package/dist/rebase/repair.d.ts +41 -0
  208. package/dist/rebase/repair.js +68 -0
  209. package/dist/rebase/repair.js.map +1 -0
  210. package/dist/replay/clickhouse.d.ts +33 -0
  211. package/dist/replay/clickhouse.js +106 -0
  212. package/dist/replay/clickhouse.js.map +1 -0
  213. package/dist/replay/index.d.ts +39 -0
  214. package/dist/replay/index.js +57 -0
  215. package/dist/replay/index.js.map +1 -0
  216. package/dist/replay/postgres.d.ts +31 -0
  217. package/dist/replay/postgres.js +140 -0
  218. package/dist/replay/postgres.js.map +1 -0
  219. package/dist/replay/replay.d.ts +114 -0
  220. package/dist/replay/replay.js +98 -0
  221. package/dist/replay/replay.js.map +1 -0
  222. package/dist/replay/report.d.ts +18 -0
  223. package/dist/replay/report.js +72 -0
  224. package/dist/replay/report.js.map +1 -0
  225. package/dist/replay/shared.d.ts +28 -0
  226. package/dist/replay/shared.js +77 -0
  227. package/dist/replay/shared.js.map +1 -0
  228. package/dist/schemas.d.ts +34 -0
  229. package/dist/schemas.js +38 -0
  230. package/dist/schemas.js.map +1 -0
  231. package/dist/server.d.ts +40 -0
  232. package/dist/server.js +87 -0
  233. package/dist/server.js.map +1 -0
  234. package/dist/steps/backfill.d.ts +132 -0
  235. package/dist/steps/backfill.js +307 -0
  236. package/dist/steps/backfill.js.map +1 -0
  237. package/dist/steps/index.d.ts +52 -0
  238. package/dist/steps/index.js +52 -0
  239. package/dist/steps/index.js.map +1 -0
  240. package/dist/steps/kinds.d.ts +101 -0
  241. package/dist/steps/kinds.js +143 -0
  242. package/dist/steps/kinds.js.map +1 -0
  243. package/dist/steps/postgres-migration.d.ts +95 -0
  244. package/dist/steps/postgres-migration.js +149 -0
  245. package/dist/steps/postgres-migration.js.map +1 -0
  246. package/dist/steps/rebuild.d.ts +97 -0
  247. package/dist/steps/rebuild.js +155 -0
  248. package/dist/steps/rebuild.js.map +1 -0
  249. package/dist/steps/run.d.ts +45 -0
  250. package/dist/steps/run.js +72 -0
  251. package/dist/steps/run.js.map +1 -0
  252. package/dist/topology/render.d.ts +17 -0
  253. package/dist/topology/render.js +17 -0
  254. package/dist/topology/render.js.map +1 -0
  255. package/dist/version.d.ts +2 -0
  256. package/dist/version.js +11 -0
  257. package/dist/version.js.map +1 -0
  258. package/dist/versioned/approval.d.ts +35 -0
  259. package/dist/versioned/approval.js +53 -0
  260. package/dist/versioned/approval.js.map +1 -0
  261. package/dist/versioned/checks.d.ts +29 -0
  262. package/dist/versioned/checks.js +54 -0
  263. package/dist/versioned/checks.js.map +1 -0
  264. package/dist/versioned/clickhouse.d.ts +24 -0
  265. package/dist/versioned/clickhouse.js +42 -0
  266. package/dist/versioned/clickhouse.js.map +1 -0
  267. package/dist/versioned/digest.d.ts +77 -0
  268. package/dist/versioned/digest.js +69 -0
  269. package/dist/versioned/digest.js.map +1 -0
  270. package/dist/versioned/driver.d.ts +51 -0
  271. package/dist/versioned/driver.js +13 -0
  272. package/dist/versioned/driver.js.map +1 -0
  273. package/dist/versioned/engine.d.ts +206 -0
  274. package/dist/versioned/engine.js +370 -0
  275. package/dist/versioned/engine.js.map +1 -0
  276. package/dist/versioned/explain.d.ts +123 -0
  277. package/dist/versioned/explain.js +294 -0
  278. package/dist/versioned/explain.js.map +1 -0
  279. package/dist/versioned/index.d.ts +46 -0
  280. package/dist/versioned/index.js +77 -0
  281. package/dist/versioned/index.js.map +1 -0
  282. package/dist/versioned/op.d.ts +72 -0
  283. package/dist/versioned/op.js +185 -0
  284. package/dist/versioned/op.js.map +1 -0
  285. package/dist/versioned/policy.d.ts +67 -0
  286. package/dist/versioned/policy.js +161 -0
  287. package/dist/versioned/policy.js.map +1 -0
  288. package/dist/versioned/postgres/catalog.d.ts +33 -0
  289. package/dist/versioned/postgres/catalog.js +34 -0
  290. package/dist/versioned/postgres/catalog.js.map +1 -0
  291. package/dist/versioned/postgres/driver.d.ts +71 -0
  292. package/dist/versioned/postgres/driver.js +140 -0
  293. package/dist/versioned/postgres/driver.js.map +1 -0
  294. package/dist/versioned/postgres/executor.d.ts +104 -0
  295. package/dist/versioned/postgres/executor.js +172 -0
  296. package/dist/versioned/postgres/executor.js.map +1 -0
  297. package/dist/versioned/postgres/index.d.ts +11 -0
  298. package/dist/versioned/postgres/index.js +12 -0
  299. package/dist/versioned/postgres/index.js.map +1 -0
  300. package/dist/versioned/postgres/waits.d.ts +46 -0
  301. package/dist/versioned/postgres/waits.js +78 -0
  302. package/dist/versioned/postgres/waits.js.map +1 -0
  303. package/dist/versioned/report.d.ts +25 -0
  304. package/dist/versioned/report.js +84 -0
  305. package/dist/versioned/report.js.map +1 -0
  306. package/dist/versioned/stand-down.d.ts +30 -0
  307. package/dist/versioned/stand-down.js +56 -0
  308. package/dist/versioned/stand-down.js.map +1 -0
  309. package/dist/versioned/state.d.ts +108 -0
  310. package/dist/versioned/state.js +153 -0
  311. package/dist/versioned/state.js.map +1 -0
  312. package/package.json +61 -4
  313. package/schemas/apply.schema.json +269 -0
  314. package/schemas/common.schema.json +213 -0
  315. package/schemas/drift.schema.json +36 -0
  316. package/schemas/init.schema.json +31 -0
  317. package/schemas/lint-rules.schema.json +54 -0
  318. package/schemas/lint.schema.json +290 -0
  319. package/schemas/mcp.schema.json +70 -0
  320. package/schemas/new.schema.json +71 -0
  321. package/schemas/plan.schema.json +371 -0
  322. package/schemas/rebase.schema.json +54 -0
  323. package/schemas/repair.schema.json +20 -0
  324. package/schemas/status.schema.json +310 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * The versioned apply: pending migrations, statement by statement, each
3
+ * statement's start and outcome appended to the history, under the lock,
4
+ * after the plan digest the run was approved under is checked again.
5
+ *
6
+ * Statements are the `statement` steps of each migration's `migration.json`,
7
+ * written for a single node, each rendered for the environment's topology
8
+ * as it is sent (#9, `../topology/render.ts`). A statement whose latest
9
+ * history row is `succeeded` is never sent again, so a migration that failed
10
+ * part way resumes at the statement that failed. A statement whose latest
11
+ * row is `started` (the runner stopped while it ran) is sent again: the
12
+ * history cannot tell whether the server ran it.
13
+ *
14
+ * An Op step (#12) runs in its place among the statements: the statements
15
+ * before it first, the ones after it only once it succeeded. A
16
+ * `ClickHouseRebuildOp` step runs chant's rebuild Op, a backfill step the
17
+ * author's Op of `effect()` batches (`../steps/`), each in this process
18
+ * under the same lock, and behind the same approval: the step and any file
19
+ * it runs are in the migration's checksum, so in the plan digest. Its rows
20
+ * are `kind = 'step'`, with the step's summary (receipts skipped, work done)
21
+ * in `note`. A step that failed or was stopped runs again on the next run
22
+ * and resumes from its receipts: the partitions or batches that finished
23
+ * are skipped.
24
+ *
25
+ * On Postgres (#13) a `PostgresMigrationOp` step (a column rename or type
26
+ * change) runs the same way, as chant's expand-and-contract Op
27
+ * (`../steps/postgres-migration.ts`).
28
+ *
29
+ * What is the dialect's (the lock, the live-schema fingerprint, how a
30
+ * statement is sent and its `succeeded` row written) is the driver's
31
+ * (`./driver.ts`): on Postgres a transactional statement and its row commit
32
+ * in one transaction, under `lock_timeout`, retried on a lock timeout
33
+ * (`./postgres/executor.ts`).
34
+ *
35
+ * A migration's pre-migration checks (#52, `./checks.ts`) run under the
36
+ * lock just before its first statement; one that fails refuses (exit 4)
37
+ * with a `failed` migration row naming it, and nothing of it is sent.
38
+ *
39
+ * Manual steps, and Op steps apply does not run (a rebuild in app mode, a
40
+ * step of the other dialect), are refused before anything runs (exit 2).
41
+ */
42
+ import { YodelError } from "../project.js";
43
+ import { PLAN_NEEDS_OP } from "../chant/plan.js";
44
+ import { environmentSettings } from "../config/settings.js";
45
+ import { defaultStepRunner, describeStep, planStep, stepSha, StepOpFailed } from "../steps/index.js";
46
+ import { HistoryRecorder, HistoryStore, httpPort, MIGRATION_ROW, newRunContext, SINGLE, statementDone, statementSha, withLock, appliedBy, LockHeldError, } from "../history/index.js";
47
+ import { clickhouseVersion, postgresVersion, serverAddress, softly } from "../server.js";
48
+ import { clickhouseDriver } from "./clickhouse.js";
49
+ import { openPostgres } from "./postgres/driver.js";
50
+ import { compareHistory, outOfOrder } from "./state.js";
51
+ import { digestSubject, planDigest, sameDigest } from "./digest.js";
52
+ import { checksDue, checksRefusal, failedChecks, runChecks } from "./checks.js";
53
+ /** Exit code: a checksum mismatch, an applied migration gone from the directory, or an out-of-order migration without `--allow-out-of-order`. */
54
+ export const REFUSED = 4;
55
+ /**
56
+ * Binds an environment's server (`sql.profiles.<env>`) and history. `port`
57
+ * (ClickHouse) and `pgConnect` (Postgres) stand in for the server in tests.
58
+ * Close it with {@link closeVersioned} when done: on Postgres it holds a
59
+ * connection.
60
+ */
61
+ export async function openVersioned(project, env, processEnv = process.env, port, pgConnect) {
62
+ const settings = environmentSettings(project, env.name, processEnv);
63
+ if (project.dialect === "postgres") {
64
+ const pg = await openPostgres(project, env, processEnv, settings.historyDatabase, pgConnect);
65
+ return {
66
+ environment: env.name,
67
+ dialect: "postgres",
68
+ driver: pg.driver,
69
+ store: pg.store,
70
+ location: { database: settings.historyDatabase, topology: SINGLE },
71
+ scope: { databases: pg.schemas, historyDatabase: settings.historyDatabase },
72
+ serverKey: pg.endpoint.url,
73
+ lockTtlMs: settings.lockTtlMs,
74
+ lockWaitMs: settings.lockWaitMs,
75
+ projectDir: project.dir,
76
+ server: async () => ({ dialect: "postgres", address: serverAddress("postgres", pg.endpoint.url), version: await softly(() => postgresVersion(pg.client)) }),
77
+ };
78
+ }
79
+ const { resolveClickHouseTarget, isUnresolvedTarget } = await import("@intentius/chant-lexicon-sql/clickhouse/live/bind");
80
+ const target = resolveClickHouseTarget({ environment: env.name, config: project.config, env: processEnv });
81
+ if (isUnresolvedTarget(target))
82
+ throw new YodelError(target.detail);
83
+ const endpoint = target.endpoint;
84
+ const location = { database: settings.historyDatabase, topology: settings.historyTopology };
85
+ const p = port ?? (await httpPort(endpoint));
86
+ const scope = { databases: target.databases, historyDatabase: settings.historyDatabase };
87
+ return {
88
+ environment: env.name,
89
+ dialect: "clickhouse",
90
+ driver: clickhouseDriver({ port: p, location, scope, serverKey: endpoint.url, lockTtlMs: settings.lockTtlMs, endpoint, topology: settings.topology }),
91
+ port: p,
92
+ store: new HistoryStore(p, location),
93
+ location,
94
+ scope,
95
+ serverKey: endpoint.url,
96
+ lockTtlMs: settings.lockTtlMs,
97
+ lockWaitMs: settings.lockWaitMs,
98
+ projectDir: project.dir,
99
+ endpoint,
100
+ topology: settings.topology,
101
+ topologySource: settings.topologySource,
102
+ server: async () => ({ dialect: "clickhouse", address: serverAddress("clickhouse", endpoint.url), version: await softly(() => clickhouseVersion(p)) }),
103
+ };
104
+ }
105
+ /** Closes what {@link openVersioned} opened (a Postgres connection). Safe to call twice. */
106
+ export const closeVersioned = (venv) => venv.driver.close();
107
+ /** The history and how the directory compares with it. Reads only; takes no lock. */
108
+ export async function inspect(venv, ordered, options = {}) {
109
+ const state = await venv.store.state(options);
110
+ return { state, status: compareHistory(ordered, state) };
111
+ }
112
+ /** The refusal for an integrity problem, or `undefined`. */
113
+ export function integrityRefusal(status, allowOutOfOrder) {
114
+ if (status.mismatches.length > 0) {
115
+ return new YodelError(`refused: the history does not match the migrations directory; nothing was applied:\n${status.mismatches.map((m) => ` ${m.message}`).join("\n")}`, REFUSED);
116
+ }
117
+ const late = outOfOrder(status);
118
+ if (late.length > 0 && !allowOutOfOrder) {
119
+ const newest = status.applied.filter((a) => a.index !== undefined).at(-1)?.id ?? "";
120
+ return new YodelError(`refused: ${late.map((p) => p.id).join(", ")} ${late.length === 1 ? "is" : "are"} out of order: the chain puts ${late.length === 1 ? "it" : "them"} before ${newest}, which is already applied. ` +
121
+ `Nothing was applied. Pass --allow-out-of-order to apply ${late.length === 1 ? "it" : "them"} now (in chain order); ${late.length === 1 ? "it is" : "they are"} never skipped.`, REFUSED);
122
+ }
123
+ return undefined;
124
+ }
125
+ /** The refusal for the steps among `toApply` that apply does not run (manual steps, Ops it does not run), or `undefined`. */
126
+ export function stepRefusal(toApply) {
127
+ const lines = toApply.flatMap((p) => p.refusedSteps.map(({ index, reason }) => ` ${p.id} step ${String(index)}: ${reason}`));
128
+ if (lines.length === 0)
129
+ return undefined;
130
+ return new YodelError(`refused: a pending migration has a step yodel apply does not run: a person acts on a manual step, and yodel apply runs only ClickHouseRebuildOp (materialized-view mode) and backfill steps on ClickHouse, and PostgresMigrationOp on Postgres. Nothing was applied:\n${lines.join("\n")}`, PLAN_NEEDS_OP);
131
+ }
132
+ /** What a run would apply, in chain order, or the refusal. */
133
+ export function selectToApply(status, allowOutOfOrder) {
134
+ const refusal = integrityRefusal(status, allowOutOfOrder) ?? stepRefusal(status.pending);
135
+ if (refusal)
136
+ throw refusal;
137
+ return status.pending;
138
+ }
139
+ /** The plan digest of applying `toApply` from the server's state now. */
140
+ export async function currentDigest(venv, status, toApply) {
141
+ const live = await venv.driver.liveFingerprint();
142
+ return planDigest(digestSubject({ environment: venv.environment, historyDatabase: venv.location.database, topology: venv.topology, applied: status.applied, toApply, live }));
143
+ }
144
+ export class ApplyFailed extends YodelError {
145
+ migration;
146
+ statement;
147
+ serverError;
148
+ constructor(migration, statement, serverError) {
149
+ super(`${migration} failed at statement ${String(statement)}: ${serverError}\n` +
150
+ `Fix the cause (on the server, or that statement in the migration's files), then run yodel apply again: ` +
151
+ `it resumes at statement ${String(statement)} and never sends again the statements that succeeded.`, 1);
152
+ this.migration = migration;
153
+ this.statement = statement;
154
+ this.serverError = serverError;
155
+ this.name = "ApplyFailed";
156
+ }
157
+ }
158
+ /** An Op step failed or stopped part way; the next run resumes it from its receipts. */
159
+ export class StepFailed extends YodelError {
160
+ migration;
161
+ step;
162
+ detail;
163
+ constructor(migration, step, detail) {
164
+ super(`${migration} failed at step ${String(step)}: ${detail}\n` +
165
+ `Fix the cause, then run yodel apply again: it resumes at step ${String(step)}, whose finished work (the partitions or batches with a receipt) is not done again, ` +
166
+ `and never sends again the statements that succeeded.`, 1);
167
+ this.migration = migration;
168
+ this.step = step;
169
+ this.detail = detail;
170
+ this.name = "StepFailed";
171
+ }
172
+ }
173
+ const seconds = (ms) => (ms % 1000 === 0 ? `${String(ms / 1000)}s` : `${(ms / 1000).toFixed(1)}s`);
174
+ /**
175
+ * Takes the lock, waiting up to `waitMs` while another apply holds it: a
176
+ * line naming the holder when the wait starts and whenever the holder
177
+ * changes, a try every `pollMs`. A lock still held at the end of the wait
178
+ * is the {@link LockHeldError} it was (exit 5), saying how long it waited.
179
+ * With `standDown`, a newer commit ends the wait: `{ stoodDown }`.
180
+ */
181
+ export async function acquireWaiting(venv, holder, options) {
182
+ const started = Date.now();
183
+ let first;
184
+ let last = "";
185
+ for (;;) {
186
+ try {
187
+ const lock = await venv.driver.acquireLock(holder);
188
+ if (!first)
189
+ return { lock };
190
+ const ms = Date.now() - started;
191
+ options.log(`lock: taken after waiting ${seconds(ms)}`);
192
+ return { lock, waited: { ms, heldBy: first.holder, where: first.where } };
193
+ }
194
+ catch (e) {
195
+ if (!(e instanceof LockHeldError))
196
+ throw e;
197
+ first ??= e;
198
+ const left = options.waitMs - (Date.now() - started);
199
+ if (left <= 0) {
200
+ if (options.waitMs <= 0)
201
+ throw e;
202
+ throw new LockHeldError(e.holder, e.expiresAt, e.where, e.clear, `waited ${seconds(options.waitMs)} (--lock-wait), and it is still held`);
203
+ }
204
+ if (e.holder !== last)
205
+ options.log(`lock: held by ${e.holder} (${e.where}); waiting up to ${seconds(left)} for it`);
206
+ last = e.holder;
207
+ const line = await options.standDown?.();
208
+ if (line)
209
+ return { stoodDown: line };
210
+ await new Promise((r) => setTimeout(r, Math.min(options.pollMs ?? 1000, left)));
211
+ }
212
+ }
213
+ }
214
+ /**
215
+ * Applies the pending migrations: takes the lock, reads the history again
216
+ * under it, refuses on any integrity problem or a digest that moved since
217
+ * approval, then runs each statement not yet succeeded.
218
+ */
219
+ export async function executeApply(venv, ordered, options) {
220
+ const standDown = async () => {
221
+ const line = await options.standDown?.();
222
+ if (line)
223
+ options.log(line);
224
+ return line;
225
+ };
226
+ const early = await standDown();
227
+ if (early)
228
+ return { applied: [], skipped: [], lock: { kind: "local", where: "(not taken: this run stood down)" }, stoodDown: early };
229
+ const got = await acquireWaiting(venv, appliedBy(options.processEnv), {
230
+ waitMs: options.lockWaitMs ?? venv.lockWaitMs ?? 0,
231
+ ...(options.lockPollMs !== undefined ? { pollMs: options.lockPollMs } : {}),
232
+ log: options.log,
233
+ standDown: options.standDown ? standDown : undefined,
234
+ });
235
+ if ("stoodDown" in got)
236
+ return { applied: [], skipped: [], lock: { kind: "local", where: "(not taken: this run stood down)" }, stoodDown: got.stoodDown };
237
+ const { lock, waited } = got;
238
+ if (lock.notice)
239
+ options.log(`lock: ${lock.notice}`);
240
+ else
241
+ options.log(`lock: held in ${lock.where}`);
242
+ const lockDoc = { kind: lock.kind, where: lock.where, ...(lock.notice ? { notice: lock.notice } : {}), ...(waited ? { waited } : {}) };
243
+ return withLock(lock, venv.lockTtlMs, async (beat) => {
244
+ await venv.store.ensure();
245
+ const { state, status } = await inspect(venv, ordered);
246
+ const toApply = selectToApply(status, options.allowOutOfOrder);
247
+ // Nothing pending under the lock (another apply, which held it first, applied it all): nothing to send, so nothing to approve.
248
+ if (toApply.length === 0) {
249
+ options.log("nothing pending under the lock: every migration is applied");
250
+ return { applied: [], skipped: [], lock: lockDoc };
251
+ }
252
+ const digest = await currentDigest(venv, status, toApply);
253
+ if (!(await sameDigest(digest, options.approvedDigest))) {
254
+ const { describeMove, explainAgainst } = await import("./explain.js");
255
+ const moved = await explainAgainst(venv, ordered, { approvedDigest: options.approvedDigest });
256
+ throw new YodelError(`refused: the plan moved since it was approved (approved ${options.approvedDigest}, now ${digest}): ${describeMove(moved)}. ` +
257
+ `Nothing was applied; run yodel apply ${venv.environment} again and approve the new plan.`, 1);
258
+ }
259
+ await options.approve(digest);
260
+ // The policy (#53), judged again under the lock for the digest computed here: a denial with no override for it refuses.
261
+ const overrides = options.policy ? await options.policy(digest, toApply) : [];
262
+ const recorder = new HistoryRecorder(venv.store, newRunContext(options.approvedDigest, options.processEnv), state.maxSeq);
263
+ const result = { applied: [], skipped: [], lock: lockDoc };
264
+ for (const p of toApply) {
265
+ await applyMigration(venv, p, state.byId.get(p.id), recorder, beat, options, result, overrides);
266
+ result.applied.push(p.id);
267
+ }
268
+ return result;
269
+ });
270
+ }
271
+ async function applyMigration(venv, p, rec, recorder, beat, options, result, overrides = []) {
272
+ const m = p.migration;
273
+ const silences = options.silences?.(m) ?? "[]";
274
+ const base = { migration_id: m.id, parent: m.parent ?? "", checksum: p.checksum, silences };
275
+ // The started row's note: the policy overrides the run relied on (#53), and the checks' outcomes (#52).
276
+ const noted = overrides.length > 0 ? { policy: { overrides } } : {};
277
+ let checksNote = Object.keys(noted).length > 0 ? JSON.stringify(noted) : "";
278
+ if (checksDue(p)) {
279
+ const outcomes = await runChecks(venv.driver, m);
280
+ checksNote = JSON.stringify({ ...noted, checks: outcomes });
281
+ const refusal = checksRefusal(m, outcomes, "under the lock, before its first statement");
282
+ if (refusal) {
283
+ const failed = failedChecks(m, outcomes);
284
+ await recorder.record({ ...base, kind: "migration", statement_index: MIGRATION_ROW, statement_sha: "", status: "failed", error: failed.join("; "), note: checksNote });
285
+ for (const f of failed)
286
+ options.log(`${m.id}: ${f}`);
287
+ throw refusal;
288
+ }
289
+ for (const o of outcomes)
290
+ options.log(`${m.id}: check ${o.name} passed (${o.detail})`);
291
+ }
292
+ options.log(`${m.id}: ${p.partWay ? `resuming at statement ${String(p.partWay.resumeAt)}` : "applying"}${p.outOfOrder ? " (out of order, allowed)" : ""}`);
293
+ await recorder.record({ ...base, kind: "migration", statement_index: MIGRATION_ROW, statement_sha: "", status: "started", ...(checksNote ? { note: checksNote } : {}) });
294
+ for (const [i, step] of m.document.steps.entries()) {
295
+ if (statementDone(rec, i)) {
296
+ options.log(` statement ${String(i)}: succeeded in an earlier run; not sent`);
297
+ result.skipped.push({ id: m.id, statement: i });
298
+ continue;
299
+ }
300
+ if (step.kind !== "statement") {
301
+ await beat();
302
+ await runOpStep(venv, p, i, recorder, base, options);
303
+ continue;
304
+ }
305
+ await beat();
306
+ // The neutral statement's sha, so a resume matches on every topology; the note says what it was rendered for.
307
+ const sha = statementSha(step.sql);
308
+ const rowNote = venv.driver.rowNote ?? "";
309
+ const row = { ...base, kind: "statement", statement_index: i, statement_sha: sha, note: rowNote };
310
+ await recorder.record({ ...row, status: "started" });
311
+ try {
312
+ // The driver writes the succeeded row: on Postgres in the statement's own transaction, so the two commit together.
313
+ await venv.driver.runStatement(step, {
314
+ succeeded: (note) => recorder.record({ ...row, status: "succeeded", note: [rowNote, note].filter(Boolean).join("; ") }),
315
+ log: options.log,
316
+ });
317
+ }
318
+ catch (e) {
319
+ const error = e instanceof Error ? e.message : String(e);
320
+ await recorder.record({ ...row, status: "failed", error });
321
+ await recorder.record({ ...base, kind: "migration", statement_index: MIGRATION_ROW, statement_sha: "", status: "failed", error: `statement ${String(i)}: ${error}` });
322
+ options.log(` statement ${String(i)}: failed: ${error.split("\n")[0] ?? ""}`);
323
+ throw new ApplyFailed(m.id, i, error.split("\n")[0] ?? error);
324
+ }
325
+ options.log(` statement ${String(i)}: ok (${step.rule} ${step.class}, ${step.name})`);
326
+ }
327
+ await recorder.record({ ...base, kind: "migration", statement_index: MIGRATION_ROW, statement_sha: "", status: "succeeded" });
328
+ options.log(`${m.id}: applied`);
329
+ }
330
+ /** Runs Op step `i` of `p`, recording its start and outcome. */
331
+ async function runOpStep(venv, p, i, recorder, base, options) {
332
+ const m = p.migration;
333
+ const step = m.document.steps[i];
334
+ if (!step)
335
+ throw new YodelError(`${m.id} has no step ${String(i)}`);
336
+ const plan = planStep(step);
337
+ if (plan.run === "statement" || plan.run === "refused" || p.refusedSteps.some((r) => r.index === i)) {
338
+ throw stepRefusal([p]) ?? new YodelError(`${m.id} step ${String(i)}: ${plan.run === "refused" ? plan.reason : "not a step yodel apply runs"}`, PLAN_NEEDS_OP);
339
+ }
340
+ const row = { ...base, kind: "step", statement_index: i, statement_sha: stepSha(step, m.files) };
341
+ const resumed = p.partWay !== undefined && p.partWay.resumeAt === i;
342
+ options.log(` step ${String(i)}: ${describeStep(step)}${resumed ? " (resuming from its receipts)" : ""}`);
343
+ await recorder.record({ ...row, status: "started" });
344
+ const run = options.runStep ?? defaultStepRunner;
345
+ let summary;
346
+ try {
347
+ ({ summary } = await run({
348
+ environment: venv.environment,
349
+ projectDir: venv.projectDir ?? process.cwd(),
350
+ ...venv.driver.stepContext(),
351
+ migration: m,
352
+ index: i,
353
+ plan,
354
+ log: options.log,
355
+ receipts: options.receipts,
356
+ }));
357
+ }
358
+ catch (e) {
359
+ const detail = e instanceof Error ? e.message : String(e);
360
+ const note = e instanceof StepOpFailed && e.summary !== undefined ? JSON.stringify(e.summary) : "";
361
+ await recorder.record({ ...row, status: "failed", error: detail, note });
362
+ await recorder.record({ ...base, kind: "migration", statement_index: MIGRATION_ROW, statement_sha: "", status: "failed", error: `step ${String(i)}: ${detail}` });
363
+ options.log(` step ${String(i)}: failed: ${detail.split("\n")[0] ?? ""}${note ? ` (${note})` : ""}`);
364
+ throw new StepFailed(m.id, i, detail.split("\n")[0] ?? detail);
365
+ }
366
+ const note = JSON.stringify(summary ?? {});
367
+ await recorder.record({ ...row, status: "succeeded", note });
368
+ options.log(` step ${String(i)}: ok ${note}`);
369
+ }
370
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/versioned/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * What moved: why the plan digest now differs from one approved earlier.
3
+ *
4
+ * The digest is a hash of its subject (`./digest.ts`): the environment, the
5
+ * history database, the topology, the applied migrations with their recorded checksums,
6
+ * the pending ones with their checksums and the statements of each already
7
+ * done, and the live schema's fingerprint. A hash says nothing about which
8
+ * of those changed, so yodel works back to the subject it was taken over:
9
+ *
10
+ * - When the older subject is known (the pull request comment carries it,
11
+ * hidden), the two subjects are compared part by part.
12
+ * - Otherwise it rebuilds candidates from what it can read: the history as
13
+ * it stood at the approval's time (the rows recorded up to then), each
14
+ * ordered subset of today's pending migrations (one added after approval
15
+ * is missing from the older plan), and each pending migration's files as
16
+ * git has held them (one edited after approval had another checksum). A
17
+ * candidate whose digest equals the approved one is the subject it was
18
+ * taken over, and the comparison is exact ("confirmed").
19
+ * - When no candidate matches, today's live schema is not the one it was
20
+ * approved against (or a part yodel cannot rebuild moved): it says so, and
21
+ * lists what it saw move (rows recorded since, files committed since).
22
+ */
23
+ import type { GateLedgerPort } from "@intentius/chant/op/gate";
24
+ import { type Migration } from "../migrations/index.js";
25
+ import { type HistoryRow } from "../history/index.js";
26
+ import { type DigestSubject } from "./digest.js";
27
+ import type { VersionedEnv } from "./engine.js";
28
+ import type { MigrateOpRef } from "./op.js";
29
+ import { type AppliedMigration, type PendingMigration, type VersionedStatus } from "./state.js";
30
+ export type MovedPart = "environment" | "history" | "pending" | "live";
31
+ export interface Moved {
32
+ part: MovedPart;
33
+ message: string;
34
+ }
35
+ export interface MoveExplanation {
36
+ approved: string;
37
+ now: string;
38
+ /** A rebuilt (or carried) subject hashes to the approved digest, so `changes` is exact. */
39
+ confirmed: boolean;
40
+ changes: Moved[];
41
+ }
42
+ /** The subject `currentDigest` hashes, read now. */
43
+ export declare function currentSubject(venv: VersionedEnv, status: VersionedStatus, toApply: readonly PendingMigration[]): Promise<DigestSubject>;
44
+ /** A subject as text safe to carry in an HTML comment: base64url of its JSON. */
45
+ export declare const encodeSubject: (s: DigestSubject) => string;
46
+ export declare function decodeSubject(text: string): DigestSubject | undefined;
47
+ /**
48
+ * How `after` differs from `before`, part by part. `applied` (today's, with
49
+ * who applied each and when) names the run that applied a migration since.
50
+ */
51
+ export declare function diffSubjects(before: DigestSubject, after: DigestSubject, applied?: readonly AppliedMigration[]): Moved[];
52
+ /** The checksums git has held for one migration's files, newest first. Empty outside git. */
53
+ export declare function gitChecksums(migrationsDir: string, id: string, limit?: number): string[];
54
+ /** Migration directories git saw commits to after `sinceIso`, with the newest commit. Empty outside git. */
55
+ export declare function gitChangesSince(migrationsDir: string, sinceIso: string): Array<{
56
+ id: string;
57
+ commit: string;
58
+ at: string;
59
+ }>;
60
+ /** ClickHouse's `YYYY-MM-DD hh:mm:ss.ffffff` (UTC) or ISO, as epoch ms. */
61
+ export declare const recordedTime: (t: string | undefined) => number;
62
+ export interface ExplainInput {
63
+ approvedDigest: string;
64
+ /** When the approval was recorded (ISO); lets yodel read the history as it stood then. */
65
+ approvedAt?: string | undefined;
66
+ now: DigestSubject;
67
+ /** The subject the approved digest was shown with, when something kept it (the PR comment). */
68
+ previous?: DigestSubject | undefined;
69
+ /** The chain, as the directory has it today. */
70
+ ordered: readonly Migration[];
71
+ /** Today's applied migrations, for who applied what. */
72
+ applied?: readonly AppliedMigration[];
73
+ /** Every history row, to rebuild the history as it stood at `approvedAt`. */
74
+ rows?: readonly HistoryRow[];
75
+ /** The checksums a migration's files have had (default: none but today's). */
76
+ checksums?: (id: string) => string[];
77
+ /** Directories committed to since `approvedAt`, for the unconfirmed case. */
78
+ changedSince?: (iso: string) => Array<{
79
+ id: string;
80
+ commit: string;
81
+ at: string;
82
+ }>;
83
+ /** Candidates tried at most. */
84
+ budget?: number;
85
+ }
86
+ /** Why `input.now` no longer hashes to `input.approvedDigest`. */
87
+ export declare function explainMove(input: ExplainInput): Promise<MoveExplanation>;
88
+ /** One line: "the plan moved since it was approved: <part>: <what>; ...". */
89
+ export declare function describeMove(e: MoveExplanation): string;
90
+ /** The newest approval of a gate, as {@link latestApproval} reads it. */
91
+ export interface LatestApproval {
92
+ digest: string | undefined;
93
+ by: string;
94
+ at: string;
95
+ /** It counts for the digest asked about, by the gate's rule. */
96
+ holds: boolean;
97
+ /** Its digest is the one asked about (it may still not hold: see `askedAgain`). */
98
+ sameDigest: boolean;
99
+ /**
100
+ * A run reached the gate after this approval and asked for approval again:
101
+ * the first such pending gate record, with the digest that run was holding.
102
+ * The approval no longer counts, whatever its digest.
103
+ */
104
+ askedAgain?: {
105
+ at: string;
106
+ digest: string | undefined;
107
+ } | undefined;
108
+ }
109
+ /** The newest approval of `op`'s gate in the ledger, and whether it holds for `digest` by the gate's rule (for that digest, newer than the gate's newest pending fact). */
110
+ export declare function latestApproval(ledger: GateLedgerPort, op: Pick<MigrateOpRef, "name" | "gate">, digest: string | undefined): Promise<LatestApproval | undefined>;
111
+ /** Why an approval for this very digest does not hold: a run asked for approval again after it. */
112
+ export declare function askedAgainLine(a: Pick<LatestApproval, "askedAgain">, code?: (s: string) => string): string;
113
+ /**
114
+ * {@link explainMove} with what yodel can read itself: today's subject (the
115
+ * pending migrations of `ordered` against the history now, unless `now` is
116
+ * given), the history's rows, and git's copies of the migrations' files.
117
+ */
118
+ export declare function explainAgainst(venv: VersionedEnv, ordered: readonly Migration[], input: {
119
+ approvedDigest: string;
120
+ approvedAt?: string | undefined;
121
+ now?: DigestSubject | undefined;
122
+ previous?: DigestSubject | undefined;
123
+ }): Promise<MoveExplanation>;