@voltro/sql-mysql 0.2.0 → 0.2.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 +8 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +78 -85
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -39,6 +39,14 @@ _Changes staged for the next release accumulate here (rolled up from
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
+
## [0.2.1] — 2026-07-17
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- **@voltro/cli, @voltro/database** — `voltro codegen` / `dev` / `serve` / `build` no longer crash with `Cannot find package '@voltro/sql-mysql'` on an app that doesn't declare that driver (e.g. a memory-store app, or a postgres app for the mysql/mssql drivers). The CLI's framework-table assembly statically imported the CDC-offsets table schema from `@voltro/sql-mysql` / `@voltro/sql-mssql` (`import { _voltroCdcOffsetsTable } from '@voltro/sql-mysql'`), so merely LOADING the CLI resolved those driver packages — failing whenever one wasn't installed. This surfaced only in a production install where the drivers aren't present (0.2.0's app-declared-driver change), not in the workspace where all drivers are devDependencies. The two CDC-offsets table schemas (pure schema, no driver runtime) move to `@voltro/database` — the driver-agnostic package both the CLI and the drivers already depend on; the drivers re-export them so their public API + CDC readers are unchanged. The CLI now references a SQL driver only through the runtime `importDriver()` lookup (lazy, and only for the dialect actually in use). The lazily-imported driver modules are also typed with local structural interfaces instead of `typeof import('@voltro/sql-*')`, so no driver package is referenced in a type position either.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
42
50
|
## [0.2.0] — 2026-07-17
|
|
43
51
|
|
|
44
52
|
### ⚠ BREAKING
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CDC_OFFSETS_TABLE } from '@voltro/database';
|
|
1
2
|
import { CdcConfig } from '@voltro/database';
|
|
2
3
|
import { ChangeEvent } from '@voltro/database';
|
|
3
4
|
import { ChangeStrategy } from '@voltro/database';
|
|
@@ -22,8 +23,8 @@ import { SqlClient } from '@effect/sql';
|
|
|
22
23
|
import { SqlClient as SqlClient_2 } from '@effect/sql/SqlClient';
|
|
23
24
|
import { SqlDialect } from '@voltro/database';
|
|
24
25
|
import { SqlError } from '@effect/sql';
|
|
25
|
-
import { TableLike } from '@voltro/database';
|
|
26
26
|
import { TransactionConnection } from '@effect/sql/SqlClient';
|
|
27
|
+
import { _voltroCdcOffsetsTable } from '@voltro/database';
|
|
27
28
|
|
|
28
29
|
export declare interface BinlogCdcHandle {
|
|
29
30
|
readonly stop: () => Promise<void>;
|
|
@@ -99,7 +100,7 @@ export declare interface BinlogPosition {
|
|
|
99
100
|
readonly position: number;
|
|
100
101
|
}
|
|
101
102
|
|
|
102
|
-
export
|
|
103
|
+
export { CDC_OFFSETS_TABLE }
|
|
103
104
|
|
|
104
105
|
declare class CdcDeliveryGate {
|
|
105
106
|
private readonly variant;
|
|
@@ -368,6 +369,6 @@ export declare const startBinlogCdc: (opts: BinlogCdcOptions) => Promise<BinlogC
|
|
|
368
369
|
|
|
369
370
|
declare type TxnContext = Context.Tag.Service<typeof TransactionConnection>;
|
|
370
371
|
|
|
371
|
-
export
|
|
372
|
+
export { _voltroCdcOffsetsTable }
|
|
372
373
|
|
|
373
374
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -3,16 +3,16 @@ import { Config as t, Effect as n, Layer as r, ManagedRuntime as i, Option as a,
|
|
|
3
3
|
import { EventEmitter as c } from "node:events";
|
|
4
4
|
import { createLogger as l } from "@voltro/logger";
|
|
5
5
|
import { SqlClient as u, TransactionConnection as d } from "@effect/sql/SqlClient";
|
|
6
|
-
import {
|
|
6
|
+
import { CDC_OFFSETS_TABLE as f, _voltroCdcOffsetsTable as p, attachEagerLoads as m, compileEagerJson as h, compilePredicate as g, compileRawFragment as _, compileSelect as v, decodeRowsFromSchema as y, encodeRowForSchema as b, hasEagerLoads as x, qualifyTable as S, requireTable as C } from "@voltro/database";
|
|
7
7
|
//#region src/sqlLayer.ts
|
|
8
|
-
var
|
|
8
|
+
var w = (n) => e.layerConfig({
|
|
9
9
|
host: t.succeed(n.host),
|
|
10
10
|
port: t.succeed(n.port),
|
|
11
11
|
username: t.succeed(n.username),
|
|
12
12
|
password: t.succeed(o.make(n.password)),
|
|
13
13
|
database: t.succeed(n.database),
|
|
14
14
|
...n.maxConnections === void 0 ? {} : { maxConnections: t.succeed(n.maxConnections) }
|
|
15
|
-
}),
|
|
15
|
+
}), T = (e) => {
|
|
16
16
|
if (e.url) {
|
|
17
17
|
let t = new URL(e.url);
|
|
18
18
|
return {
|
|
@@ -32,34 +32,34 @@ var E = (n) => e.layerConfig({
|
|
|
32
32
|
database: e.database ?? "app",
|
|
33
33
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections }
|
|
34
34
|
};
|
|
35
|
-
},
|
|
35
|
+
}, E = (e) => w(T(e)), D = (e, t) => e === null ? !1 : t === null ? !0 : e.filename === t.filename ? e.position > t.position : e.filename > t.filename, O = (e) => e.msSinceProgress < e.stallThresholdMs ? "healthy" : e.primary !== null && !D(e.primary, e.reader) ? "idle-caught-up" : "reconnect", k = (e) => (e instanceof Error ? e.message : String(e ?? "")).includes("schema changed between binlog event and metadata fetch"), A = /* @__PURE__ */ new Set([
|
|
36
36
|
"writerows",
|
|
37
37
|
"updaterows",
|
|
38
38
|
"deleterows"
|
|
39
|
-
]),
|
|
39
|
+
]), j = /\b(alter|rename|drop|create)\s+(table|column)?/i, M = (e) => new Promise((t) => setTimeout(t, e)), N = async (e) => {
|
|
40
40
|
let t = l({ scope: `voltro:${e.variant}:cdc` }), n;
|
|
41
41
|
try {
|
|
42
42
|
n = (await import("@vlasky/zongji")).default;
|
|
43
43
|
} catch (t) {
|
|
44
44
|
throw Error(`changeStrategy='cdc' on ${e.variant} requires the '@vlasky/zongji' optional dependency. Install it (it ships as an optionalDependency of @voltro/sql-mysql) to enable binlog CDC.`, { cause: t });
|
|
45
45
|
}
|
|
46
|
-
let r = e.includeTables ? new Set(e.includeTables) : null, i = e.connection.database, a = e.startPosition?.filename ?? null, o = e.startPosition ?? null, s = (t, n) =>
|
|
46
|
+
let r = e.includeTables ? new Set(e.includeTables) : null, i = e.connection.database, a = e.startPosition?.filename ?? null, o = e.startPosition ?? null, s = (t, n) => y([n], t, e.variant)[0], c = null, u = !1, d = 0, f = Date.now(), p = !1, m = null, h = e.stallThresholdMs ?? 25e3, g = e.watchdogIntervalMs ?? 15e3, _ = () => {
|
|
47
47
|
f = Date.now();
|
|
48
|
-
},
|
|
49
|
-
|
|
48
|
+
}, v = (n) => {
|
|
49
|
+
_();
|
|
50
50
|
let l = n.getEventName();
|
|
51
51
|
if (l === "rotate" && n.binlogName) {
|
|
52
52
|
a = n.binlogName;
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
-
if (l === "query" && n.query &&
|
|
55
|
+
if (l === "query" && n.query && j.test(n.query)) {
|
|
56
56
|
c && (c.tableMap = {});
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
if (n.nextPosition && a && (o = {
|
|
60
60
|
filename: a,
|
|
61
61
|
position: n.nextPosition
|
|
62
|
-
}, e.onPosition?.(o)), !
|
|
62
|
+
}, e.onPosition?.(o)), !A.has(l)) return;
|
|
63
63
|
let u = n.tableMap[n.tableId];
|
|
64
64
|
if (!u || u.parentSchema !== i) return;
|
|
65
65
|
let d = u.tableName;
|
|
@@ -116,8 +116,8 @@ var E = (n) => e.layerConfig({
|
|
|
116
116
|
});
|
|
117
117
|
c = o;
|
|
118
118
|
let s = !1;
|
|
119
|
-
o.on("binlog",
|
|
120
|
-
|
|
119
|
+
o.on("binlog", v), o.on("ready", () => {
|
|
120
|
+
_(), !s && (s = !0, d = 0, t.info("cdc: binlog reader attached", {
|
|
121
121
|
serverId: e.serverId,
|
|
122
122
|
from: r ?? "current-end"
|
|
123
123
|
}), i());
|
|
@@ -137,11 +137,11 @@ var E = (n) => e.layerConfig({
|
|
|
137
137
|
try {
|
|
138
138
|
c?.stop();
|
|
139
139
|
} catch {}
|
|
140
|
-
if (d++, await
|
|
141
|
-
let r = o, i = x(n), s = !i &&
|
|
140
|
+
if (d++, await M(Math.min(3e4, 500 * 2 ** Math.min(d, 6))), u) return;
|
|
141
|
+
let r = o, i = x(n), s = !i && k(n);
|
|
142
142
|
(i || s) && (t.warn(s ? "cdc: un-replayable backlog event (schema moved past it) — jumping to current end + self-heal" : "cdc: binlog gap (purged/failover) — jumping to current end + self-heal"), r = e.resolveStartPosition ? await e.resolveStartPosition().catch(() => null) : null, a = r?.filename ?? null, e.onResync?.());
|
|
143
143
|
try {
|
|
144
|
-
await S(r), d = 0,
|
|
144
|
+
await S(r), d = 0, _();
|
|
145
145
|
return;
|
|
146
146
|
} catch (e) {
|
|
147
147
|
n = e;
|
|
@@ -161,21 +161,21 @@ var E = (n) => e.layerConfig({
|
|
|
161
161
|
c?.stop();
|
|
162
162
|
} catch {}
|
|
163
163
|
let n = e.resolveStartPosition ? await e.resolveStartPosition().catch(() => null) : null;
|
|
164
|
-
a = n?.filename ?? null, e.onResync?.(), await
|
|
164
|
+
a = n?.filename ?? null, e.onResync?.(), await M(500), await S(n);
|
|
165
165
|
} else throw n;
|
|
166
166
|
}
|
|
167
167
|
let w = async () => {
|
|
168
168
|
if (u || p || Date.now() - f < h) return;
|
|
169
169
|
let n = null;
|
|
170
170
|
if (e.resolveStartPosition && (n = await e.resolveStartPosition().catch(() => null)), u || p) return;
|
|
171
|
-
let r =
|
|
171
|
+
let r = O({
|
|
172
172
|
msSinceProgress: Date.now() - f,
|
|
173
173
|
stallThresholdMs: h,
|
|
174
174
|
primary: n,
|
|
175
175
|
reader: o
|
|
176
176
|
});
|
|
177
177
|
if (r !== "reconnect") {
|
|
178
|
-
r === "idle-caught-up" &&
|
|
178
|
+
r === "idle-caught-up" && _();
|
|
179
179
|
return;
|
|
180
180
|
}
|
|
181
181
|
t.warn("cdc: watchdog detected a stalled reader — forcing reconnect", {
|
|
@@ -197,14 +197,7 @@ var E = (n) => e.layerConfig({
|
|
|
197
197
|
},
|
|
198
198
|
currentPosition: () => o
|
|
199
199
|
};
|
|
200
|
-
},
|
|
201
|
-
id: b({ prefix: "cdcoff" }),
|
|
202
|
-
replicaId: w(),
|
|
203
|
-
streamName: w(),
|
|
204
|
-
binlogFile: w(),
|
|
205
|
-
binlogPosition: w(),
|
|
206
|
-
updatedAt: T()
|
|
207
|
-
}).index(["replicaId"]), R = /* @__PURE__ */ new Set(["1213", "1205"]), z = (e) => {
|
|
200
|
+
}, P = /* @__PURE__ */ new Set(["1213", "1205"]), F = (e) => {
|
|
208
201
|
let t = e;
|
|
209
202
|
for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
|
|
210
203
|
let e = t.errno;
|
|
@@ -213,31 +206,31 @@ var E = (n) => e.layerConfig({
|
|
|
213
206
|
if (typeof n == "string") return n;
|
|
214
207
|
t = t.cause;
|
|
215
208
|
}
|
|
216
|
-
},
|
|
217
|
-
let t =
|
|
218
|
-
return t !== void 0 &&
|
|
219
|
-
},
|
|
209
|
+
}, I = (e) => {
|
|
210
|
+
let t = F(e);
|
|
211
|
+
return t !== void 0 && P.has(t);
|
|
212
|
+
}, L = (e) => I(e) ? "retry" : "noRetry", R = (e) => {
|
|
220
213
|
if (e == null) return "null";
|
|
221
214
|
let t = typeof e;
|
|
222
215
|
if (t === "bigint") return `${e}n`;
|
|
223
216
|
if (t !== "object") return JSON.stringify(e);
|
|
224
217
|
if (e instanceof Date) return `"${e.toISOString()}"`;
|
|
225
|
-
if (Array.isArray(e)) return `[${e.map(
|
|
218
|
+
if (Array.isArray(e)) return `[${e.map(R).join(",")}]`;
|
|
226
219
|
let n = e;
|
|
227
|
-
return `{${Object.keys(n).sort().map((e) => `${JSON.stringify(e)}:${
|
|
228
|
-
},
|
|
229
|
-
let t =
|
|
220
|
+
return `{${Object.keys(n).sort().map((e) => `${JSON.stringify(e)}:${R(n[e])}`).join(",")}}`;
|
|
221
|
+
}, z = (e) => {
|
|
222
|
+
let t = R(e), n = 2166136261;
|
|
230
223
|
for (let e = 0; e < t.length; e++) n ^= t.charCodeAt(e), n = Math.imul(n, 16777619);
|
|
231
224
|
return (n >>> 0).toString(36);
|
|
232
|
-
},
|
|
225
|
+
}, B = (e, t) => {
|
|
233
226
|
let n = setTimeout(e, t);
|
|
234
227
|
typeof n.unref == "function" && n.unref();
|
|
235
|
-
},
|
|
228
|
+
}, V = class {
|
|
236
229
|
variant;
|
|
237
230
|
ttlMs;
|
|
238
231
|
schedule;
|
|
239
232
|
seen = /* @__PURE__ */ new Map();
|
|
240
|
-
constructor(e, t = 6e4, n =
|
|
233
|
+
constructor(e, t = 6e4, n = B) {
|
|
241
234
|
this.variant = e, this.ttlMs = t, this.schedule = n;
|
|
242
235
|
}
|
|
243
236
|
key(e) {
|
|
@@ -247,11 +240,11 @@ var E = (n) => e.layerConfig({
|
|
|
247
240
|
if (n == null) return null;
|
|
248
241
|
let r = t;
|
|
249
242
|
try {
|
|
250
|
-
r =
|
|
243
|
+
r = y([t], e.table, this.variant)[0] ?? t;
|
|
251
244
|
} catch {
|
|
252
245
|
r = t;
|
|
253
246
|
}
|
|
254
|
-
return `${e.table} ${e.op} ${String(n)} ${
|
|
247
|
+
return `${e.table} ${e.op} ${String(n)} ${z(r)}`;
|
|
255
248
|
}
|
|
256
249
|
admit(e) {
|
|
257
250
|
let t = this.key(e);
|
|
@@ -266,12 +259,12 @@ var E = (n) => e.layerConfig({
|
|
|
266
259
|
get pending() {
|
|
267
260
|
return this.seen.size;
|
|
268
261
|
}
|
|
269
|
-
},
|
|
262
|
+
}, H = async (e) => {
|
|
270
263
|
let t = e.variant ?? "mysql", n = l({ scope: `voltro:${t}` }), a = e.changeStrategy ?? "inline", o = a;
|
|
271
264
|
a === "cdc" && !e.cdcConfig && (n.warn("changeStrategy='cdc' requires cdcConfig (serverId + connection); falling back to 'inline'."), o = "inline");
|
|
272
|
-
let s = e.tracerLayer ? r.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, c = i.make(s), d = new
|
|
265
|
+
let s = e.tracerLayer ? r.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, c = i.make(s), d = new U(await c.runPromise(u), c, t, o);
|
|
273
266
|
return o === "cdc" && e.cdcConfig && await d.startCdcConsumer(e.cdcConfig), d;
|
|
274
|
-
},
|
|
267
|
+
}, U = class e {
|
|
275
268
|
sql;
|
|
276
269
|
runtime;
|
|
277
270
|
variant;
|
|
@@ -287,13 +280,13 @@ var E = (n) => e.layerConfig({
|
|
|
287
280
|
cdcStreamName = "default";
|
|
288
281
|
cdcGate;
|
|
289
282
|
constructor(e, t, n, r = "inline", i = null, a, o) {
|
|
290
|
-
this.sql = e, this.runtime = t, this.variant = n, this.changeStrategy = r, this.namespace = i, this.log = l({ scope: `voltro:${n}` }), this.emitter = a ?? new c(), this.cdcGate = o ?? new
|
|
283
|
+
this.sql = e, this.runtime = t, this.variant = n, this.changeStrategy = r, this.namespace = i, this.log = l({ scope: `voltro:${n}` }), this.emitter = a ?? new c(), this.cdcGate = o ?? new V(n);
|
|
291
284
|
}
|
|
292
285
|
withNamespace(t) {
|
|
293
286
|
return t === this.namespace ? this : new e(this.sql, this.runtime, this.variant, this.changeStrategy, t, this.emitter, this.cdcGate);
|
|
294
287
|
}
|
|
295
288
|
nsT(e) {
|
|
296
|
-
return
|
|
289
|
+
return S(this.namespace, e);
|
|
297
290
|
}
|
|
298
291
|
get dialectId() {
|
|
299
292
|
return this.variant;
|
|
@@ -305,8 +298,8 @@ var E = (n) => e.layerConfig({
|
|
|
305
298
|
};
|
|
306
299
|
}
|
|
307
300
|
async executeQuery(e, t) {
|
|
308
|
-
let r =
|
|
309
|
-
return
|
|
301
|
+
let r = v(e, this.sql, this.namespace), i = t ? n.provideService(r, d, t) : r;
|
|
302
|
+
return y(await this.runtime.runPromise(i), e.table, this.variant);
|
|
310
303
|
}
|
|
311
304
|
get supportsInsertReturning() {
|
|
312
305
|
return this.variant === "mariadb";
|
|
@@ -320,7 +313,7 @@ var E = (n) => e.layerConfig({
|
|
|
320
313
|
async executeInsert(e, t, r, i) {
|
|
321
314
|
let a = this.sql;
|
|
322
315
|
if (this.supportsInsertReturning) {
|
|
323
|
-
let o = a`INSERT INTO ${a(this.nsT(e))} ${a.insert(
|
|
316
|
+
let o = a`INSERT INTO ${a(this.nsT(e))} ${a.insert(b(t, e))} RETURNING *`, s = r ? n.provideService(o, d, r) : o, c = (await this.runtime.runPromise(s))[0];
|
|
324
317
|
if (!c) throw Error(`MysqlStore.insert: no row returned for table '${e}'`);
|
|
325
318
|
return this.routeEvent({
|
|
326
319
|
table: e,
|
|
@@ -329,7 +322,7 @@ var E = (n) => e.layerConfig({
|
|
|
329
322
|
new: c
|
|
330
323
|
}, i), c;
|
|
331
324
|
}
|
|
332
|
-
let o =
|
|
325
|
+
let o = b(t, e), s = t.id;
|
|
333
326
|
if (s === void 0) {
|
|
334
327
|
let t = await this.insertRecoverAutoId(e, o, r);
|
|
335
328
|
return this.routeEvent({
|
|
@@ -363,7 +356,7 @@ var E = (n) => e.layerConfig({
|
|
|
363
356
|
if (e) return this.runtime.runPromise(t(e));
|
|
364
357
|
this.inflightTxns++;
|
|
365
358
|
try {
|
|
366
|
-
let e = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(d), (e) => a.isNone(e) ? n.fail(/* @__PURE__ */ Error("MysqlStore.insert: TransactionConnection missing.")) : t(e.value)))), i = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(
|
|
359
|
+
let e = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(d), (e) => a.isNone(e) ? n.fail(/* @__PURE__ */ Error("MysqlStore.insert: TransactionConnection missing.")) : t(e.value)))), i = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(I)), o = e.pipe(n.retry(i), n.withSpan("store.insert", { attributes: {
|
|
367
360
|
"db.system": this.variant,
|
|
368
361
|
"db.operation": r
|
|
369
362
|
} }));
|
|
@@ -374,7 +367,7 @@ var E = (n) => e.layerConfig({
|
|
|
374
367
|
}
|
|
375
368
|
async executeInsertMany(e, t, r, i) {
|
|
376
369
|
if (t.length === 0) return [];
|
|
377
|
-
let a = this.sql, o = t.map((t) =>
|
|
370
|
+
let a = this.sql, o = t.map((t) => b(t, e));
|
|
378
371
|
if (this.supportsInsertReturning) {
|
|
379
372
|
let t = a`INSERT INTO ${a(this.nsT(e))} ${a.insert(o)} RETURNING *`, s = r ? n.provideService(t, d, r) : t, c = await this.runtime.runPromise(s);
|
|
380
373
|
for (let t of c) this.routeEvent({
|
|
@@ -433,7 +426,7 @@ var E = (n) => e.layerConfig({
|
|
|
433
426
|
async executeUpdate(e, t, r, i, a) {
|
|
434
427
|
let o = this.sql;
|
|
435
428
|
if (this.supportsUpdateReturning) {
|
|
436
|
-
let s = o`UPDATE ${o(this.nsT(e))} SET ${o.update(
|
|
429
|
+
let s = o`UPDATE ${o(this.nsT(e))} SET ${o.update(b(r, e))} WHERE ${o("id")} = ${t} RETURNING *`, c = i ? n.provideService(s, d, i) : s, l = (await this.runtime.runPromise(c))[0];
|
|
437
430
|
return l ? (this.routeEvent({
|
|
438
431
|
table: e,
|
|
439
432
|
op: "update",
|
|
@@ -441,7 +434,7 @@ var E = (n) => e.layerConfig({
|
|
|
441
434
|
new: l
|
|
442
435
|
}, a), l) : null;
|
|
443
436
|
}
|
|
444
|
-
let s = o`UPDATE ${o(this.nsT(e))} SET ${o.update(
|
|
437
|
+
let s = o`UPDATE ${o(this.nsT(e))} SET ${o.update(b(r, e))} WHERE ${o("id")} = ${t}`, c = i ? n.provideService(s, d, i) : s, l = await this.runtime.runPromise(c);
|
|
445
438
|
if (l && typeof l.affectedRows == "number" && l.affectedRows === 0) return null;
|
|
446
439
|
let u = o`SELECT * FROM ${o(this.nsT(e))} WHERE ${o("id")} = ${t}`, f = i ? n.provideService(u, d, i) : u, p = (await this.runtime.runPromise(f))[0];
|
|
447
440
|
return p ? (this.routeEvent({
|
|
@@ -502,7 +495,7 @@ var E = (n) => e.layerConfig({
|
|
|
502
495
|
return this.executeInsert(e, t, r, i);
|
|
503
496
|
}
|
|
504
497
|
async executeMariadbUpsert(e, t, r, i, a) {
|
|
505
|
-
let o = this.sql, s =
|
|
498
|
+
let o = this.sql, s = b(t, e), c = Object.keys(s).filter((e) => s[e] !== void 0), l = r.update === void 0 ? c.filter((e) => e !== "id" && !r.conflictColumns.includes(e)) : r.update, u = l.length > 0 ? o.csv(l.map((e) => o`${o(e)} = VALUES(${o(e)})`)) : o`${o(r.conflictColumns[0])} = VALUES(${o(r.conflictColumns[0])})`, f = o`INSERT INTO ${o(this.nsT(e))} ${o.insert(s)} ON DUPLICATE KEY UPDATE ${u} RETURNING *`, p = i ? n.provideService(f, d, i) : f, m = (await this.runtime.runPromise(p))[0];
|
|
506
499
|
if (!m) throw Error(`MysqlStore.upsert: no row returned for table '${e}'`);
|
|
507
500
|
let h = t.id !== void 0 && t.id === m.id ? "insert" : "update";
|
|
508
501
|
return this.routeEvent({
|
|
@@ -514,7 +507,7 @@ var E = (n) => e.layerConfig({
|
|
|
514
507
|
}
|
|
515
508
|
async executeInsertIgnore(e, t, r, i, a) {
|
|
516
509
|
if (this.variant === "mariadb") {
|
|
517
|
-
let o = this.sql, s = o`INSERT IGNORE INTO ${o(this.nsT(e))} ${o.insert(
|
|
510
|
+
let o = this.sql, s = o`INSERT IGNORE INTO ${o(this.nsT(e))} ${o.insert(b(t, e))} RETURNING *`, c = i ? n.provideService(s, d, i) : s, l = (await this.runtime.runPromise(c))[0];
|
|
518
511
|
if (l) return this.routeEvent({
|
|
519
512
|
table: e,
|
|
520
513
|
op: "insert",
|
|
@@ -536,19 +529,19 @@ var E = (n) => e.layerConfig({
|
|
|
536
529
|
return this.runWithEager(e, null);
|
|
537
530
|
}
|
|
538
531
|
raw(e, t) {
|
|
539
|
-
let n =
|
|
532
|
+
let n = _(e, this.sql);
|
|
540
533
|
return this.runtime.runPromise(n);
|
|
541
534
|
}
|
|
542
535
|
async runWithEager(e, t) {
|
|
543
|
-
if (!
|
|
544
|
-
let r = this.variant === "mariadb" ? "mariadb" : "mysql", i = this.namespace === null ?
|
|
536
|
+
if (!x(e)) return this.executeQuery(e, t);
|
|
537
|
+
let r = this.variant === "mariadb" ? "mariadb" : "mysql", i = this.namespace === null ? h(e, this.sql, r) : null;
|
|
545
538
|
if (i !== null) try {
|
|
546
539
|
let e = t ? n.provideService(i.fragment, d, t) : i.fragment, r = await this.runtime.runPromise(e);
|
|
547
540
|
return i.decode(r);
|
|
548
541
|
} catch (e) {
|
|
549
542
|
this.log.warn(`${this.variant} JSON-agg eager-load failed; falling back to walker`, { err: e });
|
|
550
543
|
}
|
|
551
|
-
return
|
|
544
|
+
return m(await this.executeQuery(e, t), e.eager, e.sourceTable ?? C(e.table), (e) => this.executeQuery(e, t));
|
|
552
545
|
}
|
|
553
546
|
getInternalRunWithEager() {
|
|
554
547
|
return this.runWithEager.bind(this);
|
|
@@ -576,7 +569,7 @@ var E = (n) => e.layerConfig({
|
|
|
576
569
|
}
|
|
577
570
|
async updateMany(e, t, r) {
|
|
578
571
|
if (this.supportsUpdateReturning) {
|
|
579
|
-
let n = this.sql, i =
|
|
572
|
+
let n = this.sql, i = g(r.where, n, this.namespace), a = n`UPDATE ${n(this.nsT(e))} SET ${n.update(b(t, e))} WHERE ${i} RETURNING *`, o = await this.runtime.runPromise(a);
|
|
580
573
|
for (let t of o) this.routeEvent({
|
|
581
574
|
table: e,
|
|
582
575
|
op: "update",
|
|
@@ -585,23 +578,23 @@ var E = (n) => e.layerConfig({
|
|
|
585
578
|
}, null);
|
|
586
579
|
return o.length;
|
|
587
580
|
}
|
|
588
|
-
let i = this.sql, o =
|
|
581
|
+
let i = this.sql, o = g(r.where, i, this.namespace);
|
|
589
582
|
this.inflightTxns++;
|
|
590
583
|
try {
|
|
591
584
|
let r = n.suspend(() => this.sql.withTransaction(n.flatMap(n.serviceOption(d), (r) => {
|
|
592
585
|
if (a.isNone(r)) return n.fail(/* @__PURE__ */ Error("MysqlStore.updateMany: TransactionConnection missing."));
|
|
593
|
-
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(
|
|
586
|
+
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(b(t, e))} WHERE ${o}`;
|
|
594
587
|
return n.flatMap(n.provideService(c, d, s), (t) => {
|
|
595
588
|
if (t.length === 0) return n.succeed([]);
|
|
596
589
|
let r = t.map((e) => e.id), a = i`SELECT * FROM ${i(this.nsT(e))} WHERE ${i("id")} IN ${i.in(r)}`;
|
|
597
590
|
return n.flatMap(n.provideService(l, d, s), () => n.provideService(a, d, s));
|
|
598
591
|
});
|
|
599
|
-
}))), c = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(
|
|
592
|
+
}))), c = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(I)), l = r.pipe(n.retry(c), n.withSpan("store.updateMany", { attributes: {
|
|
600
593
|
"db.system": this.variant,
|
|
601
594
|
"db.operation": "update"
|
|
602
595
|
} })), u = await this.runtime.runPromise(l);
|
|
603
596
|
if (u.length === 0) return 0;
|
|
604
|
-
let f =
|
|
597
|
+
let f = y(u, e, this.variant);
|
|
605
598
|
for (let t of f) this.routeEvent({
|
|
606
599
|
table: e,
|
|
607
600
|
op: "update",
|
|
@@ -614,9 +607,9 @@ var E = (n) => e.layerConfig({
|
|
|
614
607
|
}
|
|
615
608
|
}
|
|
616
609
|
async deleteMany(e, t) {
|
|
617
|
-
let r = this.sql, i =
|
|
610
|
+
let r = this.sql, i = g(t.where, r, this.namespace);
|
|
618
611
|
if (this.supportsDeleteReturning) {
|
|
619
|
-
let t = r`DELETE FROM ${r(this.nsT(e))} WHERE ${i} RETURNING *`, n =
|
|
612
|
+
let t = r`DELETE FROM ${r(this.nsT(e))} WHERE ${i} RETURNING *`, n = y(await this.runtime.runPromise(t), e, this.variant);
|
|
620
613
|
for (let t of n) this.routeEvent({
|
|
621
614
|
table: e,
|
|
622
615
|
op: "delete",
|
|
@@ -631,12 +624,12 @@ var E = (n) => e.layerConfig({
|
|
|
631
624
|
if (a.isNone(t)) return n.fail(/* @__PURE__ */ Error("MysqlStore.deleteMany: TransactionConnection missing."));
|
|
632
625
|
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}`;
|
|
633
626
|
return n.flatMap(n.provideService(s, d, o), (e) => e.length === 0 ? n.succeed(e) : n.as(n.provideService(c, d, o), e));
|
|
634
|
-
}))), o = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(
|
|
627
|
+
}))), o = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(I)), c = t.pipe(n.retry(o), n.withSpan("store.deleteMany", { attributes: {
|
|
635
628
|
"db.system": this.variant,
|
|
636
629
|
"db.operation": "delete"
|
|
637
630
|
} })), l = await this.runtime.runPromise(c);
|
|
638
631
|
if (l.length === 0) return 0;
|
|
639
|
-
let u =
|
|
632
|
+
let u = y(l, e, this.variant);
|
|
640
633
|
for (let t of u) this.routeEvent({
|
|
641
634
|
table: e,
|
|
642
635
|
op: "delete",
|
|
@@ -655,7 +648,7 @@ var E = (n) => e.layerConfig({
|
|
|
655
648
|
if (this.cdcHandle) return;
|
|
656
649
|
await this.assertBinlogConfig(), this.cdcReplicaId = e.replicaId;
|
|
657
650
|
let t = await this.readCdcOffset(e.replicaId) ?? await this.resolveBinlogEnd();
|
|
658
|
-
this.cdcHandle = await
|
|
651
|
+
this.cdcHandle = await N({
|
|
659
652
|
connection: e.connection,
|
|
660
653
|
serverId: e.serverId,
|
|
661
654
|
variant: this.variant,
|
|
@@ -706,7 +699,7 @@ var E = (n) => e.layerConfig({
|
|
|
706
699
|
try {
|
|
707
700
|
let t = this.sql, n = (await this.runtime.runPromise(t`
|
|
708
701
|
SELECT ${t("binlogFile")}, ${t("binlogPosition")}
|
|
709
|
-
FROM ${t(
|
|
702
|
+
FROM ${t(f)}
|
|
710
703
|
WHERE ${t("id")} = ${e} LIMIT 1`))[0];
|
|
711
704
|
if (!n) return null;
|
|
712
705
|
let r = Number(n.binlogPosition);
|
|
@@ -728,7 +721,7 @@ var E = (n) => e.layerConfig({
|
|
|
728
721
|
this.cdcPendingPosition = null;
|
|
729
722
|
try {
|
|
730
723
|
let t = this.sql, n = this.cdcReplicaId;
|
|
731
|
-
await this.runtime.runPromise(t`INSERT INTO ${t(
|
|
724
|
+
await this.runtime.runPromise(t`INSERT INTO ${t(f)} ${t.insert({
|
|
732
725
|
id: n,
|
|
733
726
|
replicaId: n,
|
|
734
727
|
streamName: this.cdcStreamName,
|
|
@@ -775,7 +768,7 @@ var E = (n) => e.layerConfig({
|
|
|
775
768
|
let r = ++t;
|
|
776
769
|
return this.sql.withTransaction(n.flatMap(n.serviceOption(d), (t) => {
|
|
777
770
|
if (a.isNone(t)) return n.fail(/* @__PURE__ */ Error("MysqlStore.transactional: TransactionConnection missing."));
|
|
778
|
-
let i = new
|
|
771
|
+
let i = new W(this, t.value);
|
|
779
772
|
return n.tryPromise({
|
|
780
773
|
try: () => e(i).then((e) => ({
|
|
781
774
|
result: e,
|
|
@@ -785,7 +778,7 @@ var E = (n) => e.layerConfig({
|
|
|
785
778
|
catch: (e) => e
|
|
786
779
|
});
|
|
787
780
|
}));
|
|
788
|
-
}), i = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(
|
|
781
|
+
}), i = s.exponential("10 millis").pipe(s.compose(s.recurs(3)), s.whileInput(I)), o = r.pipe(n.retry(i), n.withSpan("store.transactional", { attributes: {
|
|
789
782
|
"db.system": this.variant,
|
|
790
783
|
"db.operation": "transaction"
|
|
791
784
|
} }));
|
|
@@ -831,7 +824,7 @@ var E = (n) => e.layerConfig({
|
|
|
831
824
|
async ping() {
|
|
832
825
|
await this.runtime.runPromise(this.sql`SELECT 1`);
|
|
833
826
|
}
|
|
834
|
-
},
|
|
827
|
+
}, W = class {
|
|
835
828
|
parent;
|
|
836
829
|
txn;
|
|
837
830
|
events = [];
|
|
@@ -903,9 +896,9 @@ var E = (n) => e.layerConfig({
|
|
|
903
896
|
this.events.length = 0;
|
|
904
897
|
}
|
|
905
898
|
}
|
|
906
|
-
},
|
|
899
|
+
}, G = (e) => e.__mysqlReplicationFriend ?? null, K = () => ({
|
|
907
900
|
async capturePrimaryPosition(e) {
|
|
908
|
-
let t =
|
|
901
|
+
let t = G(e);
|
|
909
902
|
if (t === null) throw Error("mysqlReplicationAdapter: primary is not a MysqlStore (missing __mysqlReplicationFriend).");
|
|
910
903
|
return t.runEffect(n.gen(function* () {
|
|
911
904
|
let e = yield* u, r = (t.variant === "mariadb" ? yield* e`SELECT @@global.gtid_current_pos AS gtid` : yield* e`SELECT @@global.gtid_executed AS gtid`)[0]?.gtid;
|
|
@@ -913,7 +906,7 @@ var E = (n) => e.layerConfig({
|
|
|
913
906
|
}));
|
|
914
907
|
},
|
|
915
908
|
async probeReplicaPosition(e) {
|
|
916
|
-
let t =
|
|
909
|
+
let t = G(e);
|
|
917
910
|
if (t === null) throw Error("mysqlReplicationAdapter: replica is not a MysqlStore.");
|
|
918
911
|
return t.runEffect(n.gen(function* () {
|
|
919
912
|
let e = yield* u, r = (t.variant === "mariadb" ? yield* e`SELECT @@global.gtid_current_pos AS gtid` : yield* e`SELECT @@global.gtid_executed AS gtid`)[0]?.gtid;
|
|
@@ -923,24 +916,24 @@ var E = (n) => e.layerConfig({
|
|
|
923
916
|
compare(e, t) {
|
|
924
917
|
return "behind";
|
|
925
918
|
}
|
|
926
|
-
}),
|
|
919
|
+
}), q = {
|
|
927
920
|
id: "mysql",
|
|
928
|
-
makeSqlLayer: (e) =>
|
|
929
|
-
makeStore: (e) =>
|
|
921
|
+
makeSqlLayer: (e) => E(e),
|
|
922
|
+
makeStore: (e) => H({
|
|
930
923
|
...e,
|
|
931
924
|
variant: "mysql"
|
|
932
925
|
}),
|
|
933
926
|
compileContains: (e, t, n) => n`${e} LIKE ${`%${t.replace(/[\\%_]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
|
|
934
|
-
retryFilter:
|
|
935
|
-
},
|
|
927
|
+
retryFilter: L
|
|
928
|
+
}, J = {
|
|
936
929
|
id: "mariadb",
|
|
937
|
-
makeSqlLayer: (e) =>
|
|
938
|
-
makeStore: (e) =>
|
|
930
|
+
makeSqlLayer: (e) => E(e),
|
|
931
|
+
makeStore: (e) => H({
|
|
939
932
|
...e,
|
|
940
933
|
variant: "mariadb"
|
|
941
934
|
}),
|
|
942
935
|
compileContains: (e, t, n) => n`${e} LIKE ${`%${t.replace(/[\\%_]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
|
|
943
|
-
retryFilter:
|
|
936
|
+
retryFilter: L
|
|
944
937
|
};
|
|
945
938
|
//#endregion
|
|
946
|
-
export {
|
|
939
|
+
export { f as CDC_OFFSETS_TABLE, e as MysqlClient, p as _voltroCdcOffsetsTable, T as connectionFromConfig, w as makeMysqlSqlLayer, E as makeMysqlSqlLayerFromConfig, H as makeMysqlStore, J as mariadbDialect, q as mysqlDialect, K as mysqlReplicationAdapter, L as mysqlRetryFilter, N as startBinlogCdc };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/sql-mysql",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.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",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@effect/sql": "^0.51.1",
|
|
36
36
|
"@effect/sql-mysql2": "^0.52.0",
|
|
37
|
-
"@voltro/database": "0.2.
|
|
38
|
-
"@voltro/logger": "0.2.
|
|
37
|
+
"@voltro/database": "0.2.1",
|
|
38
|
+
"@voltro/logger": "0.2.1"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
41
|
"@vlasky/zongji": "^0.9.0"
|