@voltro/sql-mysql 0.43.2 → 0.44.1
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/CHANGELOG.md +50 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +83 -74
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -39,6 +39,56 @@ _Changes staged for the next release accumulate here (rolled up from
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
+
## [0.44.1] — 2026-08-19
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- **@voltro/database, @voltro/data-transfer, @voltro/cli** — A refused import row reported `(FiberFailure) SqlError: Failed to execute statement` — our runtime's rendering of a rejection, marker and stack frames and all — instead of the constraint that fired. It names neither a rule, nor a code, nor even which layer refused, and every row refused for the same cause carries it identically.
|
|
47
|
+
|
|
48
|
+
Two defects, and fixing either alone still leaves a reader stuck.
|
|
49
|
+
|
|
50
|
+
**`Cause.squash` elects a branch, and first is a position, not a ranking.** A `Cause` is a tree, and a transaction routinely produces one with more than one leaf: the statement that failed, and whatever the rollback or a finalizer did on the way out. When the first leaf was the bare wrapper, the driver error sitting in the sibling branch was never looked at. Measured: `sequential(bareSqlError, sqlErrorWithDriver)` classified as nothing while the same two branches in the opposite order classified as `unique constraint PRIMARY … [ER_DUP_ENTRY/1062]`. `extractDbCause` flattens failures AND defects now, in Cause order, expanding a nested `FiberFailure` leaf, and elects the branch that names a driver — the others' chains are appended rather than dropped.
|
|
51
|
+
|
|
52
|
+
**A row's reason may never read like a stack trace.** The runtime rendering is stripped before any tier looks at the text, so the failure mode cannot return invisibly. And when no driver detail is reachable at all, the reason now names the CHAIN of wrappers the failure passed through — the difference between "the database refused this row" and "the connection died mid-import" — while the run logs the full rendering of the first few such failures. Never returned over the wire: it carries frames, and on some engines a driver's sentence carries row data.
|
|
53
|
+
|
|
54
|
+
`RowsRefusedError` also gained `byTable`: **complete** per-table counts. `rows` is capped at 20, so per-table counts tallied off the printed list sum to the cap rather than to the failure — and nothing else in the payload offered any.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## [0.44.0] — 2026-08-19
|
|
59
|
+
|
|
60
|
+
### ⚠ BREAKING
|
|
61
|
+
|
|
62
|
+
- **@voltro/data-transfer, @voltro/cli** — `runImport` returns an `ImportOutcome` instead of the bundle's `Manifest`, and `--mode replace` runs as ONE transaction by default.
|
|
63
|
+
|
|
64
|
+
**Why the return type changed.** The summary line counted the rows the BUNDLE carries, not the rows the run wrote. Those differ most exactly where it matters: a bundle directory carries its own resume ledger, so a copied directory imports nothing — correctly, with a warning naming the file to delete — and the run then printed `import complete … rows: 242950` over a target it had not touched. The warning was one line above, which is one line too far for anyone piping the output through `tail -1`. The outcome carries `rowsWritten`, `rowsSkipped` and `fullyResumed`, the CLI reports written-vs-carried, and a fully-skipped run says so on its LAST line.
|
|
65
|
+
|
|
66
|
+
Migration: `runImport(...)` now resolves to `{ manifest, tablesWritten, rowsWritten, tablesSkipped, rowsSkipped, fullyResumed }`. Read `.manifest` where you read the manifest before.
|
|
67
|
+
|
|
68
|
+
**Why replace is atomic now.** The all-or-nothing guarantee was written for the emptying step, and read — reasonably — as covering the run. A replace that died partway through the LOAD left the target emptied of its old rows and holding part of the new ones, measured on a live instance over sixteen minutes. There is no useful state for a replace to stop in, so it is a default rather than a flag you have to know about. It also closes the window that produced that failure: with the tables emptied and the load uncommitted, a concurrent writer in the application waits instead of inserting a row the bundle is about to insert too.
|
|
69
|
+
|
|
70
|
+
`--no-atomic` (CLI) / `atomic: false` (API) opts out. The trade is stated where it bites: every write to those tables waits for the load, and on postgres the bulk `COPY` loader cannot join a transaction it does not own — an atomic run now says that once rather than being quietly slower.
|
|
71
|
+
|
|
72
|
+
Two smaller things from the same report: `--mode replace` against a running instance warns about the empty-target window when it is NOT atomic, and the `--target api` upload reports progress per chunk plus a line explaining that the final request stays open for the whole import — sixteen minutes of silence is indistinguishable from a hang, and one operator killed a run that had finished.
|
|
73
|
+
|
|
74
|
+
**`voltro update` carries you across this** — codemod `0.44.0/01_import-outcome`.
|
|
75
|
+
|
|
76
|
+
### Fixed
|
|
77
|
+
|
|
78
|
+
- **@voltro/sql-mysql, @voltro/sql-postgres, @voltro/sql-sqlite, @voltro/sql-mssql, @voltro/data-transfer** — A write and its write-recorders now succeed or fail together on every SQL dialect, and the data importer's retry is idempotent.
|
|
79
|
+
|
|
80
|
+
A recorder (a versioning trail, an audit log) runs on the caller's connection and is ALLOWED to fail — a recorder that throws must take the write down with it, that is its contract. Outside a caller transaction the two were not one unit: the row's statement committed on its own, and the recorder's INSERT ran afterwards as a second autocommit statement. So a recorder that threw left a COMMITTED row behind a write that reported failure. Measured directly: `insert` throws, the row is in the table, and a second attempt at the same row is `ER_DUP_ENTRY` on PRIMARY.
|
|
81
|
+
|
|
82
|
+
Anything that retries a failed write then meets its own row. The data importer retries by design — it holds a row whose write failed and tries again once the remaining tables have streamed — so a `--mode replace` that had just emptied a table failed on a duplicate key IN that table. From outside, that is the impossible-looking thing: an import that emptied a table and then failed because something was already in it. Reproduced verbatim, including the table name and `[ER_DUP_ENTRY/1062]`, by putting the old retry back.
|
|
83
|
+
|
|
84
|
+
Both ends are closed, and they are independent on purpose:
|
|
85
|
+
|
|
86
|
+
- **The cause.** A table that HAS recorders writes inside a transaction now, so the row and the trail commit together or not at all — on mysql, mariadb, postgres, sqlite and mssql, verified by one suite that asks all five the same question. A table with no recorders — the default — takes the direct path unchanged; `recordsTable` is a Map-size check first, so it costs one comparison. - **The defence.** The importer's retry upserts instead of inserting in `replace` mode. That covers every OTHER way a write can land while reporting failure: a driver timeout on a write the server applied, a connection lost after the commit, a concurrent writer inserting the same key. It is sound precisely because the table was emptied by this same run — there is nothing in it that is not ours.
|
|
87
|
+
|
|
88
|
+
The test that pinned the divergence went red when the fix landed, exactly as its own note said it would, and is inverted with that note kept.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
42
92
|
## [0.43.2] — 2026-08-18
|
|
43
93
|
|
|
44
94
|
### Fixed
|
package/dist/index.d.ts
CHANGED
|
@@ -495,6 +495,30 @@ export declare class MysqlStore implements DataStore {
|
|
|
495
495
|
* The gap being closed is specific: a plain write's statement commits ITSELF,
|
|
496
496
|
* so the transport fires while this is still awaiting the driver.
|
|
497
497
|
*/
|
|
498
|
+
/**
|
|
499
|
+
* A write and its write-recorders, as ONE unit.
|
|
500
|
+
*
|
|
501
|
+
* Without this they are two: the row's statement commits on its own, and the
|
|
502
|
+
* recorder's INSERT is a second autocommit statement afterwards. A recorder
|
|
503
|
+
* that throws — which it is SUPPOSED to be able to do, that is the whole
|
|
504
|
+
* contract — then leaves a committed row behind a write that reported failure.
|
|
505
|
+
*
|
|
506
|
+
* Measured against MariaDB: `insert` throws, the row is in the table, and a
|
|
507
|
+
* second attempt at the same row is `ER_DUP_ENTRY` on PRIMARY. Any caller that
|
|
508
|
+
* retries a failed write — the data importer holds and retries by design —
|
|
509
|
+
* meets its own row and reports a duplicate-key error for a row nobody wrote
|
|
510
|
+
* twice. That reads like the impossible thing it looks like: "we replaced
|
|
511
|
+
* everything and then failed because something was already there."
|
|
512
|
+
*
|
|
513
|
+
* Only tables that HAVE a recorder pay for the transaction. `recordsTable` is
|
|
514
|
+
* a Map-size check first, so the default — no recorders — costs one comparison
|
|
515
|
+
* and takes the direct path exactly as before.
|
|
516
|
+
*
|
|
517
|
+
* Events are buffered and emitted after COMMIT, the same order the
|
|
518
|
+
* transactional view uses: a subscriber must not see a change that then rolls
|
|
519
|
+
* back.
|
|
520
|
+
*/
|
|
521
|
+
private writeWithRecorders;
|
|
498
522
|
private localWrite;
|
|
499
523
|
insert(t: string, r: Row): Promise<Readonly<Record<string, unknown>>>;
|
|
500
524
|
insertMany(t: string, rows: ReadonlyArray<Row>): Promise<readonly Readonly<Record<string, unknown>>[]>;
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { MysqlClient as e } from "@effect/sql-mysql2";
|
|
2
2
|
import { Config as t, Effect as n, Layer as r, ManagedRuntime as i, Option as a, Redacted as o, Schedule as s } from "effect";
|
|
3
|
-
import { CDC_OFFSETS_TABLE as c, DEFAULT_ACQUIRE_TIMEOUT_MS as l, EagerCardinalityError as u, _voltroCdcOffsetsTable as d, attachEagerLoads as f, attributionFields as p, attributionKey as m, beginLocalWrite as h, bulkInsertLimitsFor as g, chunkRowsForInsert as _, compileEagerJson as v, compilePredicate as y, compileRawFragment as b, compileSelect as x, decodeRowsFromSchema as S, encodeRowForSchema as C, endLocalWrite as w, externalChangeEvent as T, getTable as E, hasEagerLoads as D, isTableReactive as O, makeEagerFallbackReporter as k, observeDbOp as A, qualifyTable as
|
|
4
|
-
import { EventEmitter as
|
|
5
|
-
import { createLogger as
|
|
6
|
-
import { SqlClient as
|
|
3
|
+
import { CDC_OFFSETS_TABLE as c, DEFAULT_ACQUIRE_TIMEOUT_MS as l, EagerCardinalityError as u, _voltroCdcOffsetsTable as d, attachEagerLoads as f, attributionFields as p, attributionKey as m, beginLocalWrite as h, bulkInsertLimitsFor as g, chunkRowsForInsert as _, compileEagerJson as v, compilePredicate as y, compileRawFragment as b, compileSelect as x, decodeRowsFromSchema as S, encodeRowForSchema as C, endLocalWrite as w, externalChangeEvent as T, getTable as E, hasEagerLoads as D, isTableReactive as O, makeEagerFallbackReporter as k, observeDbOp as A, qualifyTable as j, raiseChangeListenerCeiling as M, recordsTable as N, registerPendingAttribution as ee, requireTable as te, resolveEchoAttribution as ne, runStoreTransaction as re, runWriteRecorders as ie, stampGeneratedId as P, stampGeneratedIds as ae, withCapturedAttribution as F } from "@voltro/database";
|
|
4
|
+
import { EventEmitter as oe } from "node:events";
|
|
5
|
+
import { createLogger as I } from "@voltro/logger";
|
|
6
|
+
import { SqlClient as L, TransactionConnection as R } from "@effect/sql/SqlClient";
|
|
7
7
|
//#region src/sqlLayer.ts
|
|
8
|
-
var
|
|
8
|
+
var se = (e) => e ? { rejectUnauthorized: !1 } : void 0, ce = (e) => {
|
|
9
9
|
let t = e.acquireTimeoutMs ?? l;
|
|
10
10
|
return t > 0 ? t : void 0;
|
|
11
|
-
},
|
|
11
|
+
}, le = (e) => {
|
|
12
12
|
let t = e.acquireQueueLimit;
|
|
13
13
|
return t !== void 0 && t > 0 ? t : void 0;
|
|
14
|
-
},
|
|
15
|
-
let t = e.ssl === void 0 ? void 0 :
|
|
14
|
+
}, ue = (e) => {
|
|
15
|
+
let t = e.ssl === void 0 ? void 0 : se(e.ssl), n = ce(e), r = le(e);
|
|
16
16
|
return {
|
|
17
17
|
...t === void 0 ? {} : { ssl: t },
|
|
18
18
|
...n === void 0 ? {} : { connectTimeout: n },
|
|
@@ -24,7 +24,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
24
24
|
username: t.succeed(n.username),
|
|
25
25
|
password: t.succeed(o.make(n.password)),
|
|
26
26
|
database: t.succeed(n.database),
|
|
27
|
-
poolConfig: t.succeed(
|
|
27
|
+
poolConfig: t.succeed(ue(n)),
|
|
28
28
|
...n.maxConnections === void 0 ? {} : { maxConnections: t.succeed(n.maxConnections) }
|
|
29
29
|
}), B = (e) => {
|
|
30
30
|
let t = e.get("sslmode");
|
|
@@ -115,7 +115,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
115
115
|
"updaterows",
|
|
116
116
|
"deleterows"
|
|
117
117
|
]), Te = /\b(alter|rename|drop|create)\s+(table|column)?/i, G = (e) => new Promise((t) => setTimeout(t, e)), K = async (e) => {
|
|
118
|
-
let t =
|
|
118
|
+
let t = I({ scope: `voltro:${e.variant}:cdc` }), n;
|
|
119
119
|
try {
|
|
120
120
|
n = (await import("@vlasky/zongji")).default;
|
|
121
121
|
} catch (t) {
|
|
@@ -365,9 +365,9 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
365
365
|
1062,
|
|
366
366
|
1586
|
|
367
367
|
]), Z = async (e) => {
|
|
368
|
-
let t = e.variant ?? "mysql", n =
|
|
368
|
+
let t = e.variant ?? "mysql", n = I({ scope: `voltro:${t}` }), a = e.changeStrategy ?? "inline", o = a;
|
|
369
369
|
a === "cdc" && !e.cdcConfig && (n.warn("changeStrategy='cdc' requires cdcConfig (serverId + connection); falling back to 'inline'."), o = "inline");
|
|
370
|
-
let s = e.tracerLayer ? r.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, c = i.make(s), l = new Q(await c.runPromise(
|
|
370
|
+
let s = e.tracerLayer ? r.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, c = i.make(s), l = new Q(await c.runPromise(L), c, t, o);
|
|
371
371
|
return o === "cdc" && e.cdcConfig && await l.startCdcConsumer(e.cdcConfig), l;
|
|
372
372
|
}, Q = class e {
|
|
373
373
|
sql;
|
|
@@ -390,15 +390,15 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
390
390
|
cdcGate;
|
|
391
391
|
reportEagerFallback;
|
|
392
392
|
constructor(e, t, n, r = "inline", i = null, a, o) {
|
|
393
|
-
this.sql = e, this.runtime = t, this.variant = n, this.changeStrategy = r, this.namespace = i, this.log =
|
|
393
|
+
this.sql = e, this.runtime = t, this.variant = n, this.changeStrategy = r, this.namespace = i, this.log = I({ scope: `voltro:${n}` }), this.cdcReporter = ye((e, t) => {
|
|
394
394
|
e === "error" ? this.log.error(t) : e === "warn" ? this.log.warn(t) : this.log.info(t);
|
|
395
|
-
}), this.reportEagerFallback = k(this.log), this.emitter = a ?? new
|
|
395
|
+
}), this.reportEagerFallback = k(this.log), this.emitter = a ?? new oe(), M(this.emitter), this.cdcGate = o ?? new Ae(n);
|
|
396
396
|
}
|
|
397
397
|
withNamespace(t) {
|
|
398
398
|
return t === this.namespace ? this : new e(this.sql, this.runtime, this.variant, this.changeStrategy, t, this.emitter, this.cdcGate);
|
|
399
399
|
}
|
|
400
400
|
nsT(e) {
|
|
401
|
-
return
|
|
401
|
+
return j(this.namespace, e);
|
|
402
402
|
}
|
|
403
403
|
get dialectId() {
|
|
404
404
|
return this.variant;
|
|
@@ -410,7 +410,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
410
410
|
};
|
|
411
411
|
}
|
|
412
412
|
async executeQuery(e, t, r) {
|
|
413
|
-
let i = x(e, this.sql, this.namespace), a = t ? n.provideService(i,
|
|
413
|
+
let i = x(e, this.sql, this.namespace), a = t ? n.provideService(i, R, t) : i, o = await A(this.variant, "select", () => this.runtime.runPromise(a));
|
|
414
414
|
return S(o, e.table, this.variant);
|
|
415
415
|
}
|
|
416
416
|
get supportsInsertReturning() {
|
|
@@ -423,10 +423,10 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
423
423
|
return !1;
|
|
424
424
|
}
|
|
425
425
|
async executeInsert(e, t, r, i, a) {
|
|
426
|
-
t =
|
|
426
|
+
t = P(e, t);
|
|
427
427
|
let o = this.sql;
|
|
428
428
|
if (this.supportsInsertReturning) {
|
|
429
|
-
let s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(C(t, e))} RETURNING *`, c = r ? n.provideService(s,
|
|
429
|
+
let s = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(C(t, e))} RETURNING *`, c = r ? n.provideService(s, R, r) : s, l = (await this.runtime.runPromise(c))[0];
|
|
430
430
|
if (!l) throw Error(`MysqlStore.insert: no row returned for table '${e}'`);
|
|
431
431
|
return await this.routeEvent({
|
|
432
432
|
table: e,
|
|
@@ -445,9 +445,9 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
445
445
|
new: t
|
|
446
446
|
}, i, r, a), t;
|
|
447
447
|
}
|
|
448
|
-
let l = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(s)}`, u = r ? n.provideService(l,
|
|
448
|
+
let l = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(s)}`, u = r ? n.provideService(l, R, r) : l;
|
|
449
449
|
await this.runtime.runPromise(u);
|
|
450
|
-
let d = o`SELECT * FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${c}`, f = r ? n.provideService(d,
|
|
450
|
+
let d = o`SELECT * FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${c}`, f = r ? n.provideService(d, R, r) : d, p = (await this.runtime.runPromise(f))[0];
|
|
451
451
|
if (!p) throw Error(`MysqlStore.insert: row not found post-insert in '${e}'`);
|
|
452
452
|
return await this.routeEvent({
|
|
453
453
|
table: e,
|
|
@@ -460,16 +460,16 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
460
460
|
let i = this.sql;
|
|
461
461
|
return this.runPinned(r, (r) => n.gen(this, function* () {
|
|
462
462
|
let a = i`INSERT INTO ${i(this.nsT(e))} ${i.insert(t)}`;
|
|
463
|
-
yield* n.provideService(a,
|
|
464
|
-
let o = (yield* n.provideService(i`SELECT LAST_INSERT_ID() AS ${i("lastId")}`,
|
|
465
|
-
return o === void 0 || Number(o) === 0 ? yield* n.fail(/* @__PURE__ */ Error(`MysqlStore.insert: LAST_INSERT_ID() returned no id for '${e}' — is the primary key AUTO_INCREMENT?`)) : (yield* n.provideService(i`SELECT * FROM ${i(this.nsT(e))} WHERE ${i("id")} = ${o}`,
|
|
463
|
+
yield* n.provideService(a, R, r);
|
|
464
|
+
let o = (yield* n.provideService(i`SELECT LAST_INSERT_ID() AS ${i("lastId")}`, R, r))[0]?.lastId;
|
|
465
|
+
return o === void 0 || Number(o) === 0 ? yield* n.fail(/* @__PURE__ */ Error(`MysqlStore.insert: LAST_INSERT_ID() returned no id for '${e}' — is the primary key AUTO_INCREMENT?`)) : (yield* n.provideService(i`SELECT * FROM ${i(this.nsT(e))} WHERE ${i("id")} = ${o}`, R, r))[0] || (yield* n.fail(/* @__PURE__ */ Error(`MysqlStore.insert: row not found post-insert in '${e}'`)));
|
|
466
466
|
}), "insert");
|
|
467
467
|
}
|
|
468
468
|
async runPinned(e, t, r) {
|
|
469
469
|
if (e) return this.runtime.runPromise(t(e));
|
|
470
470
|
this.inflightTxns++;
|
|
471
471
|
try {
|
|
472
|
-
let e = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(
|
|
472
|
+
let e = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(R), (e) => a.isNone(e) ? n.fail(/* @__PURE__ */ Error(`MysqlStore.${r}: TransactionConnection missing.`)) : t(e.value)))), i = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(q)), o = e.pipe(n.retry(i), n.withSpan(`store.${r}`, { attributes: {
|
|
473
473
|
"db.system": this.variant,
|
|
474
474
|
"db.operation": r
|
|
475
475
|
} }));
|
|
@@ -479,16 +479,16 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
481
|
async executeInsertMany(e, t, r, i, a) {
|
|
482
|
-
if (t =
|
|
482
|
+
if (t = ae(e, t), t.length === 0) return [];
|
|
483
483
|
let o = this.sql, s = t.map((t) => C(t, e)), c = _(s, g(this.variant));
|
|
484
484
|
if (this.supportsInsertReturning) {
|
|
485
485
|
let t = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t)} RETURNING *`, s;
|
|
486
486
|
if (c.length === 1) {
|
|
487
|
-
let e = t(c[0]), i = r ? n.provideService(e,
|
|
487
|
+
let e = t(c[0]), i = r ? n.provideService(e, R, r) : e;
|
|
488
488
|
s = await this.runtime.runPromise(i);
|
|
489
489
|
} else if (r) {
|
|
490
490
|
let e = [];
|
|
491
|
-
for (let i of c) e.push(...await this.runtime.runPromise(n.provideService(t(i),
|
|
491
|
+
for (let i of c) e.push(...await this.runtime.runPromise(n.provideService(t(i), R, r)));
|
|
492
492
|
s = e;
|
|
493
493
|
} else s = await this.runtime.runPromise(o.withTransaction(n.map(n.forEach(c, t, { concurrency: 1 }), (e) => e.flat())));
|
|
494
494
|
for (let t of s) await this.routeEvent({
|
|
@@ -513,16 +513,16 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
513
513
|
if (l.some((e) => e === void 0)) throw Error("MysqlStore.insertMany: rows mix client-supplied and missing 'id's — supply an id for every row or none (AUTO_INCREMENT recovery).");
|
|
514
514
|
let u = (t) => o`INSERT INTO ${o(this.nsT(e))} ${o.insert(t)}`;
|
|
515
515
|
if (c.length === 1) {
|
|
516
|
-
let e = r ? n.provideService(u(c[0]),
|
|
516
|
+
let e = r ? n.provideService(u(c[0]), R, r) : u(c[0]);
|
|
517
517
|
await this.runtime.runPromise(e);
|
|
518
|
-
} else if (r) for (let e of c) await this.runtime.runPromise(n.provideService(u(e),
|
|
518
|
+
} else if (r) for (let e of c) await this.runtime.runPromise(n.provideService(u(e), R, r));
|
|
519
519
|
else await this.runtime.runPromise(o.withTransaction(n.forEach(c, u, {
|
|
520
520
|
concurrency: 1,
|
|
521
521
|
discard: !0
|
|
522
522
|
})));
|
|
523
523
|
let d = _(l.map((e) => ({ id: e })), g(this.variant)), f = [];
|
|
524
524
|
for (let t of d) {
|
|
525
|
-
let i = o`SELECT * FROM ${o(this.nsT(e))} WHERE ${o("id")} IN ${o.in(t.map((e) => e.id))}`, a = r ? n.provideService(i,
|
|
525
|
+
let i = o`SELECT * FROM ${o(this.nsT(e))} WHERE ${o("id")} IN ${o.in(t.map((e) => e.id))}`, a = r ? n.provideService(i, R, r) : i;
|
|
526
526
|
f.push(...await this.runtime.runPromise(a));
|
|
527
527
|
}
|
|
528
528
|
let p = new Map(f.map((e) => [e.id, e])), m = l.map((e) => p.get(e)).filter((e) => e !== void 0);
|
|
@@ -540,19 +540,19 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
540
540
|
let a = [];
|
|
541
541
|
for (let o of t) {
|
|
542
542
|
let t = i`INSERT INTO ${i(this.nsT(e))} ${i.insert(o)}`;
|
|
543
|
-
yield* n.provideService(t,
|
|
544
|
-
let s = (yield* n.provideService(i`SELECT LAST_INSERT_ID() AS ${i("firstId")}`,
|
|
543
|
+
yield* n.provideService(t, R, r);
|
|
544
|
+
let s = (yield* n.provideService(i`SELECT LAST_INSERT_ID() AS ${i("firstId")}`, R, r))[0]?.firstId;
|
|
545
545
|
if (s === void 0 || Number(s) === 0) return yield* n.fail(/* @__PURE__ */ Error(`MysqlStore.insertMany: LAST_INSERT_ID() returned no id for '${e}' — is the primary key AUTO_INCREMENT?`));
|
|
546
|
-
let c = Number(s), l = yield* n.provideService(i`SELECT * FROM ${i(this.nsT(e))} WHERE ${i("id")} BETWEEN ${c} AND ${c + o.length - 1} ORDER BY ${i("id")} ASC`,
|
|
546
|
+
let c = Number(s), l = yield* n.provideService(i`SELECT * FROM ${i(this.nsT(e))} WHERE ${i("id")} BETWEEN ${c} AND ${c + o.length - 1} ORDER BY ${i("id")} ASC`, R, r);
|
|
547
547
|
a.push(...l);
|
|
548
548
|
}
|
|
549
549
|
return a;
|
|
550
550
|
}), "insert");
|
|
551
551
|
}
|
|
552
552
|
async executePatchJson(e, t, r, i, a, o, s) {
|
|
553
|
-
let c = this.sql, l = r.split("."), u = l[0], d = l.slice(1), f = JSON.stringify(i ?? null), p = d.length === 0 ? "$" : `$.${d.join(".")}`, m = c`UPDATE ${c(this.nsT(e))} SET ${c(u)} = JSON_SET(COALESCE(${c(u)}, '{}'), ${p}, CAST(${f} AS JSON)) WHERE ${c("id")} = ${t}`, h = a ? n.provideService(m,
|
|
553
|
+
let c = this.sql, l = r.split("."), u = l[0], d = l.slice(1), f = JSON.stringify(i ?? null), p = d.length === 0 ? "$" : `$.${d.join(".")}`, m = c`UPDATE ${c(this.nsT(e))} SET ${c(u)} = JSON_SET(COALESCE(${c(u)}, '{}'), ${p}, CAST(${f} AS JSON)) WHERE ${c("id")} = ${t}`, h = a ? n.provideService(m, R, a) : m, g = await this.runtime.runPromise(h);
|
|
554
554
|
if (g && typeof g.affectedRows == "number" && g.affectedRows === 0) return null;
|
|
555
|
-
let _ = c`SELECT * FROM ${c(this.nsT(e))} WHERE ${c("id")} = ${t}`, v = a ? n.provideService(_,
|
|
555
|
+
let _ = c`SELECT * FROM ${c(this.nsT(e))} WHERE ${c("id")} = ${t}`, v = a ? n.provideService(_, R, a) : _, y = (await this.runtime.runPromise(v))[0];
|
|
556
556
|
return y ? (await this.routeEvent({
|
|
557
557
|
table: e,
|
|
558
558
|
op: "update",
|
|
@@ -563,7 +563,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
563
563
|
async executeUpdate(e, t, r, i, a, o) {
|
|
564
564
|
let s = this.sql;
|
|
565
565
|
if (this.supportsUpdateReturning) {
|
|
566
|
-
let c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(C(r, e))} WHERE ${s("id")} = ${t} RETURNING *`, l = i ? n.provideService(c,
|
|
566
|
+
let c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(C(r, e))} WHERE ${s("id")} = ${t} RETURNING *`, l = i ? n.provideService(c, R, i) : c, u = (await this.runtime.runPromise(l))[0];
|
|
567
567
|
return u ? (await this.routeEvent({
|
|
568
568
|
table: e,
|
|
569
569
|
op: "update",
|
|
@@ -571,9 +571,9 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
571
571
|
new: u
|
|
572
572
|
}, a, i, o), u) : null;
|
|
573
573
|
}
|
|
574
|
-
let c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(C(r, e))} WHERE ${s("id")} = ${t}`, l = i ? n.provideService(c,
|
|
574
|
+
let c = s`UPDATE ${s(this.nsT(e))} SET ${s.update(C(r, e))} WHERE ${s("id")} = ${t}`, l = i ? n.provideService(c, R, i) : c, u = await this.runtime.runPromise(l);
|
|
575
575
|
if (u && typeof u.affectedRows == "number" && u.affectedRows === 0) return null;
|
|
576
|
-
let d = s`SELECT * FROM ${s(this.nsT(e))} WHERE ${s("id")} = ${t}`, f = i ? n.provideService(d,
|
|
576
|
+
let d = s`SELECT * FROM ${s(this.nsT(e))} WHERE ${s("id")} = ${t}`, f = i ? n.provideService(d, R, i) : d, p = (await this.runtime.runPromise(f))[0];
|
|
577
577
|
return p ? (await this.routeEvent({
|
|
578
578
|
table: e,
|
|
579
579
|
op: "update",
|
|
@@ -584,7 +584,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
584
584
|
async executeDelete(e, t, r, i, a) {
|
|
585
585
|
let o = this.sql;
|
|
586
586
|
if (this.supportsDeleteReturning) {
|
|
587
|
-
let s = o`DELETE FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${t} RETURNING *`, c = r ? n.provideService(s,
|
|
587
|
+
let s = o`DELETE FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${t} RETURNING *`, c = r ? n.provideService(s, R, r) : s, l = (await this.runtime.runPromise(c))[0];
|
|
588
588
|
return l ? (await this.routeEvent({
|
|
589
589
|
table: e,
|
|
590
590
|
op: "delete",
|
|
@@ -592,9 +592,9 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
592
592
|
new: null
|
|
593
593
|
}, i, r, a), !0) : !1;
|
|
594
594
|
}
|
|
595
|
-
let s = o`SELECT * FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${t}`, c = r ? n.provideService(s,
|
|
595
|
+
let s = o`SELECT * FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${t}`, c = r ? n.provideService(s, R, r) : s, l = (await this.runtime.runPromise(c))[0];
|
|
596
596
|
if (!l) return !1;
|
|
597
|
-
let u = o`DELETE FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${t}`, d = r ? n.provideService(u,
|
|
597
|
+
let u = o`DELETE FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${t}`, d = r ? n.provideService(u, R, r) : u;
|
|
598
598
|
return await this.runtime.runPromise(d), await this.routeEvent({
|
|
599
599
|
table: e,
|
|
600
600
|
op: "delete",
|
|
@@ -604,17 +604,17 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
604
604
|
}
|
|
605
605
|
async appendInTxn(e, t, r) {
|
|
606
606
|
let i = this.sql, a = i`INSERT INTO ${i(this.nsT(e))} ${i.insert(C(t, e))}`;
|
|
607
|
-
await this.runtime.runPromise(r ? n.provideService(a,
|
|
607
|
+
await this.runtime.runPromise(r ? n.provideService(a, R, r) : a);
|
|
608
608
|
}
|
|
609
609
|
async maxInTxn(e, t, r, i) {
|
|
610
|
-
let a = this.sql, o = Object.entries(r).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(i ? n.provideService(s,
|
|
610
|
+
let a = this.sql, o = Object.entries(r).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(this.nsT(e))} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(i ? n.provideService(s, R, i) : s))[0]?.m;
|
|
611
611
|
return c == null ? null : Number(c);
|
|
612
612
|
}
|
|
613
613
|
async routeEvent(e, t, n = null, r) {
|
|
614
614
|
if (e = {
|
|
615
615
|
...p(r),
|
|
616
616
|
...e
|
|
617
|
-
},
|
|
617
|
+
}, N(e.table) && await ie({
|
|
618
618
|
append: (e, t) => this.appendInTxn(e, t, n),
|
|
619
619
|
maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
|
|
620
620
|
}, {
|
|
@@ -626,7 +626,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
626
626
|
subjectId: e.subjectId
|
|
627
627
|
}), this.changeStrategy === "cdc") {
|
|
628
628
|
let t = (e.op === "delete" ? e.old : e.new)?.id;
|
|
629
|
-
t != null &&
|
|
629
|
+
t != null && ee(m(e.table, e.op, t), {
|
|
630
630
|
...e.traceId === void 0 ? {} : { traceId: e.traceId },
|
|
631
631
|
...e.subjectId === void 0 ? {} : { subjectId: e.subjectId }
|
|
632
632
|
});
|
|
@@ -664,12 +664,12 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
664
664
|
}
|
|
665
665
|
return await this.executeUpdate(e, o.id, a, r, i) ?? o;
|
|
666
666
|
}
|
|
667
|
-
return
|
|
667
|
+
return F((n) => this.executeInsert(e, t, r, i, n));
|
|
668
668
|
}
|
|
669
669
|
async executeMariadbUpsert(e, t, r, i, a, o) {
|
|
670
670
|
let s = this.sql, c = C(t, e), l = Object.keys(c).filter((e) => c[e] !== void 0), u = r.update === void 0 ? l.filter((e) => e !== "id" && !r.conflictColumns.includes(e)) : r.update, d = u.length > 0 ? s.csv(u.map((e) => s`${s(e)} = VALUES(${s(e)})`)) : s`${s(r.conflictColumns[0])} = VALUES(${s(r.conflictColumns[0])})`, f = await this.runPinned(i, (i) => n.tryPromise({
|
|
671
671
|
try: async () => {
|
|
672
|
-
let a = s`INSERT INTO ${s(this.nsT(e))} ${s.insert(c)} ON DUPLICATE KEY UPDATE ${d} RETURNING *`, o = (await this.runtime.runPromise(n.provideService(a,
|
|
672
|
+
let a = s`INSERT INTO ${s(this.nsT(e))} ${s.insert(c)} ON DUPLICATE KEY UPDATE ${d} RETURNING *`, o = (await this.runtime.runPromise(n.provideService(a, R, i)))[0];
|
|
673
673
|
if (!o) throw Error(`MysqlStore.upsert: no row returned for table '${e}'`);
|
|
674
674
|
let l = t.id;
|
|
675
675
|
if (l != null && o.id !== l) throw Error(`MysqlStore.upsert: the row written to '${e}' is not the row that was passed in. Upserting id '${String(l)}' matched an existing row with id '${String(o.id)}' on a DIFFERENT unique constraint than the conflictColumns [${r.conflictColumns.join(", ")}] you named, so that row would have been updated and yours never written. Nothing was changed. Name the constraint that actually collides, or resolve the duplicate first.`);
|
|
@@ -685,7 +685,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
685
685
|
}, a, i, o), f;
|
|
686
686
|
}
|
|
687
687
|
async executeInsertIgnore(e, t, r, i, a, o) {
|
|
688
|
-
if (t =
|
|
688
|
+
if (t = P(e, t), t.id === void 0) return await this.findByConflict(e, t, r.conflictColumns, i) || F((n) => this.executeInsert(e, t, i, a, n));
|
|
689
689
|
let s = await this.runPinned(i, (i) => n.tryPromise({
|
|
690
690
|
try: () => this.decideInsertIgnore(e, t, r, i),
|
|
691
691
|
catch: (e) => e
|
|
@@ -698,7 +698,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
698
698
|
}, a, i, o), s.row;
|
|
699
699
|
}
|
|
700
700
|
async decideInsertIgnore(e, t, r, i) {
|
|
701
|
-
let a = this.sql, o = C(t, e), s = (e) => this.runtime.runPromise(n.provideService(e,
|
|
701
|
+
let a = this.sql, o = C(t, e), s = (e) => this.runtime.runPromise(n.provideService(e, R, i));
|
|
702
702
|
if (this.supportsInsertReturning) {
|
|
703
703
|
let n = (await s(a`INSERT IGNORE INTO ${a(this.nsT(e))} ${a.insert(o)} RETURNING *`))[0];
|
|
704
704
|
if (n) return {
|
|
@@ -749,7 +749,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
749
749
|
if (e === null) return [];
|
|
750
750
|
try {
|
|
751
751
|
let t = this.sql`SHOW WARNINGS`.unprepared;
|
|
752
|
-
return (await this.runtime.runPromise(n.provideService(t,
|
|
752
|
+
return (await this.runtime.runPromise(n.provideService(t, R, e))).map((e) => ({
|
|
753
753
|
code: Number(e.Code ?? e.code ?? 0),
|
|
754
754
|
message: String(e.Message ?? e.message ?? "")
|
|
755
755
|
}));
|
|
@@ -759,7 +759,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
759
759
|
}
|
|
760
760
|
async findByConflict(e, t, r, i) {
|
|
761
761
|
if (r.length === 0) return;
|
|
762
|
-
let a = this.sql, o = r.map((e) => a`${a(e)} = ${t[e]}`), s = a`SELECT * FROM ${a(this.nsT(e))} WHERE ${a.and(o)} LIMIT 1`, c = i ? n.provideService(s,
|
|
762
|
+
let a = this.sql, o = r.map((e) => a`${a(e)} = ${t[e]}`), s = a`SELECT * FROM ${a(this.nsT(e))} WHERE ${a.and(o)} LIMIT 1`, c = i ? n.provideService(s, R, i) : s;
|
|
763
763
|
return (await this.runtime.runPromise(c))[0];
|
|
764
764
|
}
|
|
765
765
|
query(e) {
|
|
@@ -773,7 +773,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
773
773
|
if (!D(e)) return this.executeQuery(e, t);
|
|
774
774
|
let r = this.variant === "mariadb" ? "mariadb" : "mysql", i = this.namespace === null ? v(e, this.sql, r) : null;
|
|
775
775
|
if (i !== null) try {
|
|
776
|
-
let e = t ? n.provideService(i.fragment,
|
|
776
|
+
let e = t ? n.provideService(i.fragment, R, t) : i.fragment, r = await A(this.variant, "select", () => this.runtime.runPromise(e));
|
|
777
777
|
return i.decode(r);
|
|
778
778
|
} catch (t) {
|
|
779
779
|
if (t instanceof u) throw t;
|
|
@@ -790,42 +790,51 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
790
790
|
reason: "not-compilable"
|
|
791
791
|
});
|
|
792
792
|
let a = await this.executeQuery(e, t);
|
|
793
|
-
return f(a, e.eager, e.sourceTable ??
|
|
793
|
+
return f(a, e.eager, e.sourceTable ?? te(e.table), (e) => this.executeQuery(e, t));
|
|
794
794
|
}
|
|
795
795
|
getInternalRunWithEager() {
|
|
796
796
|
return this.runWithEager.bind(this);
|
|
797
797
|
}
|
|
798
|
+
async writeWithRecorders(e, t) {
|
|
799
|
+
let r = [], i = await this.runPinned(null, (i) => n.tryPromise({
|
|
800
|
+
try: () => e(t, i, r),
|
|
801
|
+
catch: (e) => e
|
|
802
|
+
}), "insert");
|
|
803
|
+
for (let e of r) this.emitChange(e);
|
|
804
|
+
return i;
|
|
805
|
+
}
|
|
798
806
|
async localWrite(e, t, n) {
|
|
807
|
+
let r = (e) => N(t) ? this.writeWithRecorders(n, e) : n(e, null, null);
|
|
799
808
|
return A(this.variant, e, async () => {
|
|
800
|
-
if (this.changeStrategy !== "cdc") return
|
|
809
|
+
if (this.changeStrategy !== "cdc") return F(r);
|
|
801
810
|
h(t);
|
|
802
811
|
try {
|
|
803
|
-
return await
|
|
812
|
+
return await F(r);
|
|
804
813
|
} finally {
|
|
805
814
|
w(t);
|
|
806
815
|
}
|
|
807
816
|
});
|
|
808
817
|
}
|
|
809
818
|
insert(e, t) {
|
|
810
|
-
return this.localWrite("insert", e, (n) => this.executeInsert(e, t,
|
|
819
|
+
return this.localWrite("insert", e, (n, r, i) => this.executeInsert(e, t, r, i, n));
|
|
811
820
|
}
|
|
812
821
|
insertMany(e, t) {
|
|
813
|
-
return this.localWrite("insert", e, (n) => this.executeInsertMany(e, t,
|
|
822
|
+
return this.localWrite("insert", e, (n, r, i) => this.executeInsertMany(e, t, r, i, n));
|
|
814
823
|
}
|
|
815
824
|
patchJson(e, t, n, r) {
|
|
816
|
-
return this.localWrite("update", e, (i) => this.executePatchJson(e, t, n, r,
|
|
825
|
+
return this.localWrite("update", e, (i, a, o) => this.executePatchJson(e, t, n, r, a, o, i));
|
|
817
826
|
}
|
|
818
827
|
upsert(e, t, n) {
|
|
819
|
-
return this.localWrite("upsert", e, (r) => this.executeUpsert(e, t, n,
|
|
828
|
+
return this.localWrite("upsert", e, (r, i, a) => this.executeUpsert(e, t, n, i, a, r));
|
|
820
829
|
}
|
|
821
830
|
insertIgnore(e, t, n) {
|
|
822
|
-
return this.localWrite("upsert", e, (r) => this.executeInsertIgnore(e, t, n,
|
|
831
|
+
return this.localWrite("upsert", e, (r, i, a) => this.executeInsertIgnore(e, t, n, i, a, r));
|
|
823
832
|
}
|
|
824
833
|
update(e, t, n) {
|
|
825
|
-
return this.localWrite("update", e, (r) => this.executeUpdate(e, t, n,
|
|
834
|
+
return this.localWrite("update", e, (r, i, a) => this.executeUpdate(e, t, n, i, a, r));
|
|
826
835
|
}
|
|
827
836
|
delete(e, t) {
|
|
828
|
-
return this.localWrite("delete", e, (n) => this.executeDelete(e, t,
|
|
837
|
+
return this.localWrite("delete", e, (n, r, i) => this.executeDelete(e, t, r, i, n));
|
|
829
838
|
}
|
|
830
839
|
async updateMany(e, t, r) {
|
|
831
840
|
if (this.supportsUpdateReturning) {
|
|
@@ -841,13 +850,13 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
841
850
|
let i = this.sql, o = y(r.where, i, this.namespace);
|
|
842
851
|
this.changeStrategy === "cdc" && h(e), this.inflightTxns++;
|
|
843
852
|
try {
|
|
844
|
-
let r = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(
|
|
853
|
+
let r = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(R), (r) => {
|
|
845
854
|
if (a.isNone(r)) return n.fail(/* @__PURE__ */ Error("MysqlStore.updateMany: TransactionConnection missing."));
|
|
846
855
|
let s = r.value, c = i`SELECT id FROM ${i(this.nsT(e))} WHERE ${o} FOR UPDATE`, l = i`UPDATE ${i(this.nsT(e))} SET ${i.update(C(t, e))} WHERE ${o}`;
|
|
847
|
-
return n.flatMap(n.provideService(c,
|
|
856
|
+
return n.flatMap(n.provideService(c, R, s), (t) => {
|
|
848
857
|
if (t.length === 0) return n.succeed([]);
|
|
849
858
|
let r = t.map((e) => e.id), a = i`SELECT * FROM ${i(this.nsT(e))} WHERE ${i("id")} IN ${i.in(r)}`;
|
|
850
|
-
return n.flatMap(n.provideService(l,
|
|
859
|
+
return n.flatMap(n.provideService(l, R, s), () => n.provideService(a, R, s));
|
|
851
860
|
});
|
|
852
861
|
}))), c = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(q)), l = r.pipe(n.retry(c), n.withSpan("store.updateMany", { attributes: {
|
|
853
862
|
"db.system": this.variant,
|
|
@@ -880,10 +889,10 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
880
889
|
}
|
|
881
890
|
this.changeStrategy === "cdc" && h(e), this.inflightTxns++;
|
|
882
891
|
try {
|
|
883
|
-
let t = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(
|
|
892
|
+
let t = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(R), (t) => {
|
|
884
893
|
if (a.isNone(t)) return n.fail(/* @__PURE__ */ Error("MysqlStore.deleteMany: TransactionConnection missing."));
|
|
885
894
|
let o = t.value, s = r`SELECT * FROM ${r(this.nsT(e))} WHERE ${i} FOR UPDATE`, c = r`DELETE FROM ${r(this.nsT(e))} WHERE ${i}`;
|
|
886
|
-
return n.flatMap(n.provideService(s,
|
|
895
|
+
return n.flatMap(n.provideService(s, R, o), (e) => e.length === 0 ? n.succeed(e) : n.as(n.provideService(c, R, o), e));
|
|
887
896
|
}))), o = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(q)), c = t.pipe(n.retry(o), n.withSpan("store.deleteMany", { attributes: {
|
|
888
897
|
"db.system": this.variant,
|
|
889
898
|
"db.operation": "delete"
|
|
@@ -947,7 +956,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
947
956
|
let t = this.cdcAdminRuntime;
|
|
948
957
|
if (t === null) return !0;
|
|
949
958
|
try {
|
|
950
|
-
let r = await t.runPromise(n.flatMap(
|
|
959
|
+
let r = await t.runPromise(n.flatMap(L, (e) => e`SHOW BINARY LOGS`.unprepared));
|
|
951
960
|
return r.length === 0 || r.some((t) => (t.Log_name ?? t.log_name) === e);
|
|
952
961
|
} catch (e) {
|
|
953
962
|
return this.log.debug(`cdc: could not list binary logs (${e?.message ?? String(e)}) — trusting the persisted offset`), !0;
|
|
@@ -975,7 +984,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
975
984
|
async resolveBinlogEndOverCdc() {
|
|
976
985
|
let e = this.cdcAdminRuntime;
|
|
977
986
|
if (e === null) return null;
|
|
978
|
-
let t = (e) => n.flatMap(
|
|
987
|
+
let t = (e) => n.flatMap(L, (t) => t`${t.unsafe(e)}`.unprepared);
|
|
979
988
|
for (let n of this.variant === "mysql" ? ["SHOW BINARY LOG STATUS", "SHOW MASTER STATUS"] : ["SHOW MASTER STATUS", "SHOW BINARY LOG STATUS"]) try {
|
|
980
989
|
let r = (await e.runPromise(t(n)))[0];
|
|
981
990
|
if (r?.File) return {
|
|
@@ -1071,13 +1080,13 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
1071
1080
|
}
|
|
1072
1081
|
async emptyTablesOn(e, t) {
|
|
1073
1082
|
if (e.length === 0) return;
|
|
1074
|
-
let r = this.sql, i = (e) => this.nsT(e), a = (e) => r.unsafe(`SET FOREIGN_KEY_CHECKS = ${+!!e}`).unprepared, o = n.acquireUseRelease(a(!1), () => n.forEach(e, (e) => r`DELETE FROM ${r(i(e))}`, { discard: !0 }), () => n.orDie(n.ignore(a(!0)))), s = t === null ? r.withTransaction(o) : n.provideService(o,
|
|
1083
|
+
let r = this.sql, i = (e) => this.nsT(e), a = (e) => r.unsafe(`SET FOREIGN_KEY_CHECKS = ${+!!e}`).unprepared, o = n.acquireUseRelease(a(!1), () => n.forEach(e, (e) => r`DELETE FROM ${r(i(e))}`, { discard: !0 }), () => n.orDie(n.ignore(a(!0)))), s = t === null ? r.withTransaction(o) : n.provideService(o, R, t);
|
|
1075
1084
|
await this.runtime.runPromise(s);
|
|
1076
1085
|
}
|
|
1077
1086
|
async transactional(e) {
|
|
1078
1087
|
this.inflightTxns++;
|
|
1079
1088
|
try {
|
|
1080
|
-
return await
|
|
1089
|
+
return await re({
|
|
1081
1090
|
...this.txnSpec("MysqlStore.transactional"),
|
|
1082
1091
|
work: e,
|
|
1083
1092
|
makeView: (e, t) => new je(this, e, t)
|
|
@@ -1113,7 +1122,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
1113
1122
|
injectExternalChange(e) {
|
|
1114
1123
|
if (this.changeStrategy === "cdc" && !this.cdcGate.admit(e) || !O(e.table)) return;
|
|
1115
1124
|
let t = (e.op === "delete" ? e.old : e.new)?.id;
|
|
1116
|
-
|
|
1125
|
+
ne(e.table, e.op, t, (t) => {
|
|
1117
1126
|
this.emitter.emit("change", T(e, t));
|
|
1118
1127
|
});
|
|
1119
1128
|
}
|
|
@@ -1232,7 +1241,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
1232
1241
|
let t = $(e);
|
|
1233
1242
|
if (t === null) throw Error("mysqlReplicationAdapter: primary is not a MysqlStore (missing __mysqlReplicationFriend).");
|
|
1234
1243
|
return t.runEffect(n.gen(function* () {
|
|
1235
|
-
let e = yield*
|
|
1244
|
+
let e = yield* L, r = (t.variant === "mariadb" ? yield* e`SELECT @@global.gtid_current_pos AS gtid` : yield* e`SELECT @@global.gtid_executed AS gtid`)[0]?.gtid;
|
|
1236
1245
|
return typeof r == "string" ? r : yield* n.die("mysql/mariadb did not return a GTID set");
|
|
1237
1246
|
}));
|
|
1238
1247
|
},
|
|
@@ -1240,7 +1249,7 @@ var ce = (e) => e ? { rejectUnauthorized: !1 } : void 0, le = (e) => {
|
|
|
1240
1249
|
let t = $(e);
|
|
1241
1250
|
if (t === null) throw Error("mysqlReplicationAdapter: replica is not a MysqlStore.");
|
|
1242
1251
|
return t.runEffect(n.gen(function* () {
|
|
1243
|
-
let e = yield*
|
|
1252
|
+
let e = yield* L, r = (t.variant === "mariadb" ? yield* e`SELECT @@global.gtid_current_pos AS gtid` : yield* e`SELECT @@global.gtid_executed AS gtid`)[0]?.gtid;
|
|
1244
1253
|
return typeof r == "string" ? r : yield* n.die("mysql/mariadb replica did not return a GTID set");
|
|
1245
1254
|
}));
|
|
1246
1255
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/sql-mysql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.1",
|
|
4
4
|
"description": "MySQL/MariaDB dialect adapter for Voltro's cross-dialect DataStore (mariadb binlog CDC; mysql inline reactivity).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@effect/sql": "^0.52.0",
|
|
37
37
|
"@effect/sql-mysql2": "^0.53.0",
|
|
38
|
-
"@voltro/database": "0.
|
|
39
|
-
"@voltro/logger": "0.
|
|
38
|
+
"@voltro/database": "0.44.1",
|
|
39
|
+
"@voltro/logger": "0.44.1"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
42
|
"@vlasky/zongji": "^0.9.0"
|