@voltro/sql-postgres 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1801 -0
- package/dist/index.d.ts +106 -9
- package/dist/index.js +336 -199
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,39 +1,47 @@
|
|
|
1
1
|
import { PgClient as e, PgClient as t } from "@effect/sql-pg";
|
|
2
|
-
import { Config as n,
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
import { Config as n, Duration as r, Effect as i, Fiber as a, Layer as o, ManagedRuntime as s, Metric as c, Redacted as l, Schedule as u, Stream as d } from "effect";
|
|
3
|
+
import f from "pg";
|
|
4
|
+
import { DEFAULT_ACQUIRE_TIMEOUT_MS as p, EagerCardinalityError as m, attachEagerLoads as h, attributionFields as g, attributionKey as ee, beginLocalWrite as _, bulkInsertLimitsFor as te, chunkRowsForInsert as ne, compileEagerJson as v, compilePredicate as y, compileRawFragment as re, compileSelect as ie, encodeRowForSchema as b, endLocalWrite as ae, hasEagerLoads as x, isTableReactive as S, makeEagerFallbackReporter as C, observeDbOp as w, raiseChangeListenerCeiling as oe, recordsTable as T, registerPendingAttribution as E, requireTable as D, resolveEchoAttribution as O, runRetryingTransaction as k, runStoreTransaction as A, runWriteRecorders as se, stampGeneratedId as j, stampGeneratedIds as ce, withCapturedAttribution as M } from "@voltro/database";
|
|
5
|
+
import { EventEmitter as le } from "node:events";
|
|
6
|
+
import { createLogger as ue } from "@voltro/logger";
|
|
7
|
+
import { SqlClient as N, TransactionConnection as P } from "@effect/sql/SqlClient";
|
|
8
|
+
//#region src/sqlLayer.ts
|
|
9
|
+
var F = (e) => {
|
|
10
|
+
let t = e.acquireTimeoutMs ?? p;
|
|
11
|
+
return t > 0 ? t : void 0;
|
|
12
|
+
}, I = (e) => e ? { rejectUnauthorized: !1 } : !1, L = /^[A-Za-z_][A-Za-z0-9_]*$/, R = (e) => {
|
|
13
|
+
let t = F(e);
|
|
14
|
+
return {
|
|
15
|
+
host: n.succeed(e.host),
|
|
16
|
+
port: n.succeed(e.port),
|
|
17
|
+
username: n.succeed(e.username),
|
|
18
|
+
password: n.succeed(l.make(e.password)),
|
|
19
|
+
database: n.succeed(e.database),
|
|
20
|
+
...e.maxConnections === void 0 ? {} : { maxConnections: n.succeed(e.maxConnections) },
|
|
21
|
+
...e.ssl === void 0 ? {} : { ssl: n.succeed(I(e.ssl)) },
|
|
22
|
+
...t === void 0 ? {} : { connectTimeout: n.succeed(r.millis(t)) }
|
|
23
|
+
};
|
|
24
|
+
}, z = (t) => {
|
|
25
|
+
if (t.schema === void 0 && t.statementTimeoutMs === void 0) return e.layerConfig(R(t));
|
|
26
|
+
let n = {};
|
|
19
27
|
if (t.schema !== void 0) {
|
|
20
|
-
if (!
|
|
21
|
-
|
|
28
|
+
if (!L.test(t.schema)) throw Error(`DB_SCHEMA '${t.schema}' is not a valid postgres identifier (expected ${L}).`);
|
|
29
|
+
n = { options: `-c search_path="${t.schema}"` };
|
|
22
30
|
}
|
|
23
|
-
let a =
|
|
31
|
+
let r = F(t), a = i.acquireRelease(i.sync(() => new f.Pool({
|
|
24
32
|
host: t.host,
|
|
25
33
|
port: t.port,
|
|
26
34
|
user: t.username,
|
|
27
35
|
password: t.password,
|
|
28
36
|
database: t.database,
|
|
29
37
|
...t.maxConnections === void 0 ? {} : { max: t.maxConnections },
|
|
30
|
-
...t.ssl === void 0 ? {} : { ssl:
|
|
38
|
+
...t.ssl === void 0 ? {} : { ssl: I(t.ssl) },
|
|
31
39
|
...t.statementTimeoutMs === void 0 ? {} : { statement_timeout: t.statementTimeoutMs },
|
|
32
|
-
connectionTimeoutMillis:
|
|
33
|
-
...
|
|
34
|
-
})), (e) =>
|
|
40
|
+
...r === void 0 ? {} : { connectionTimeoutMillis: r },
|
|
41
|
+
...n
|
|
42
|
+
})), (e) => i.promise(() => e.end()));
|
|
35
43
|
return e.layerFromPool({ acquire: a });
|
|
36
|
-
},
|
|
44
|
+
}, B = (e) => {
|
|
37
45
|
let t = e.get("sslmode");
|
|
38
46
|
if (t !== null) {
|
|
39
47
|
if (t === "require") return !0;
|
|
@@ -46,19 +54,20 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
46
54
|
if (n === "false" || n === "0") return !1;
|
|
47
55
|
throw Error(`DB_URL '?ssl=${n}' is not supported by the postgres dialect — use 'true'/'1' or 'false'/'0'.`);
|
|
48
56
|
}
|
|
49
|
-
},
|
|
50
|
-
let t = e.schema === void 0 ? {} : { schema: e.schema };
|
|
57
|
+
}, V = (e) => {
|
|
58
|
+
let t = e.schema === void 0 ? {} : { schema: e.schema }, n = e.acquireTimeoutMs === void 0 ? {} : { acquireTimeoutMs: e.acquireTimeoutMs };
|
|
51
59
|
if (e.url) {
|
|
52
|
-
let
|
|
60
|
+
let r = new URL(e.url), i = e.ssl ?? B(r.searchParams);
|
|
53
61
|
return {
|
|
54
|
-
host:
|
|
55
|
-
port:
|
|
56
|
-
username: decodeURIComponent(
|
|
57
|
-
password: decodeURIComponent(
|
|
58
|
-
database:
|
|
62
|
+
host: r.hostname || "localhost",
|
|
63
|
+
port: r.port ? Number(r.port) : 5432,
|
|
64
|
+
username: decodeURIComponent(r.username || "app"),
|
|
65
|
+
password: decodeURIComponent(r.password || "app"),
|
|
66
|
+
database: r.pathname.replace(/^\//, "") || "app",
|
|
59
67
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
60
68
|
...e.statementTimeoutMs === void 0 ? {} : { statementTimeoutMs: e.statementTimeoutMs },
|
|
61
|
-
...
|
|
69
|
+
...i === void 0 ? {} : { ssl: i },
|
|
70
|
+
...n,
|
|
62
71
|
...t
|
|
63
72
|
};
|
|
64
73
|
}
|
|
@@ -71,170 +80,271 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
71
80
|
...e.maxConnections === void 0 ? {} : { maxConnections: e.maxConnections },
|
|
72
81
|
...e.statementTimeoutMs === void 0 ? {} : { statementTimeoutMs: e.statementTimeoutMs },
|
|
73
82
|
...e.ssl === void 0 ? {} : { ssl: e.ssl },
|
|
83
|
+
...n,
|
|
74
84
|
...t
|
|
75
85
|
};
|
|
76
|
-
},
|
|
86
|
+
}, H = (e) => z(V(e)), de = /* @__PURE__ */ new Set(["40001", "40P01"]), fe = (e) => {
|
|
77
87
|
let t = e;
|
|
78
88
|
for (let e = 0; e < 5 && typeof t == "object" && t; e++) {
|
|
79
89
|
let e = t.code;
|
|
80
90
|
if (typeof e == "string") return e;
|
|
81
91
|
t = t.cause;
|
|
82
92
|
}
|
|
93
|
+
}, U = (e) => {
|
|
94
|
+
let t = fe(e);
|
|
95
|
+
return t !== void 0 && de.has(t);
|
|
96
|
+
}, W = (e) => U(e) ? "retry" : "noRetry", G = c.counter("voltro_cdc_oversized_total", { description: "Change events whose row images exceeded the postgres NOTIFY payload cap, by what re-hydration recovered (rehydrated = row re-read · tombstone = delete, primary key only · unrecovered = content lost to taps)." }), pe = {
|
|
97
|
+
rehydrated: c.tagged(G, "outcome", "rehydrated"),
|
|
98
|
+
tombstone: c.tagged(G, "outcome", "tombstone"),
|
|
99
|
+
unrecovered: c.tagged(G, "outcome", "unrecovered")
|
|
83
100
|
}, K = (e) => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
101
|
+
i.runSync(c.increment(pe[e]));
|
|
102
|
+
}, me = {
|
|
103
|
+
rehydrateTimeoutMs: 5e3,
|
|
104
|
+
rehydrateRetries: 2
|
|
105
|
+
}, q = (e) => {
|
|
106
|
+
let t = process.env[e];
|
|
107
|
+
if (t === void 0 || t.trim() === "") return;
|
|
108
|
+
let n = Number(t);
|
|
109
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
110
|
+
}, J = (e) => {
|
|
111
|
+
let t = me, n = e ?? {};
|
|
112
|
+
return {
|
|
113
|
+
rehydrateTimeoutMs: Math.max(1, n.rehydrateTimeoutMs ?? q("VOLTRO_CDC_REHYDRATE_TIMEOUT_MS") ?? t.rehydrateTimeoutMs),
|
|
114
|
+
rehydrateRetries: Math.max(0, n.rehydrateRetries ?? q("VOLTRO_CDC_REHYDRATE_RETRIES") ?? t.rehydrateRetries)
|
|
115
|
+
};
|
|
116
|
+
}, he = (e) => i.suspend(() => {
|
|
117
|
+
let t = e.notification, n = t.id, a = {
|
|
118
|
+
table: t.table,
|
|
119
|
+
op: t.op
|
|
120
|
+
}, o = (e) => ({
|
|
121
|
+
event: {
|
|
122
|
+
...a,
|
|
123
|
+
old: null,
|
|
124
|
+
new: null,
|
|
125
|
+
oversized: "unrecovered"
|
|
126
|
+
},
|
|
127
|
+
outcome: "unrecovered",
|
|
128
|
+
reason: e
|
|
129
|
+
});
|
|
130
|
+
if (typeof n != "string" && typeof n != "number") return K("unrecovered"), i.succeed(o("no-key"));
|
|
131
|
+
if (t.op === "delete") {
|
|
132
|
+
K("tombstone");
|
|
133
|
+
let e = {
|
|
134
|
+
event: {
|
|
135
|
+
...a,
|
|
136
|
+
old: { id: n },
|
|
137
|
+
new: null,
|
|
138
|
+
oversized: "tombstone"
|
|
139
|
+
},
|
|
140
|
+
outcome: "tombstone"
|
|
141
|
+
};
|
|
142
|
+
return i.succeed(e);
|
|
143
|
+
}
|
|
144
|
+
let s = u.exponential(r.millis(50), 2).pipe(u.intersect(u.recurs(e.tunables.rehydrateRetries)));
|
|
145
|
+
return e.fetchRow({
|
|
146
|
+
schema: t.schema,
|
|
147
|
+
table: t.table,
|
|
148
|
+
key: n
|
|
149
|
+
}).pipe(i.retry(s), i.timeout(r.millis(e.tunables.rehydrateTimeoutMs)), i.map((e) => e === null ? (K("unrecovered"), o("row-gone")) : (K("rehydrated"), {
|
|
150
|
+
event: {
|
|
151
|
+
...a,
|
|
152
|
+
old: null,
|
|
153
|
+
new: e,
|
|
154
|
+
oversized: "rehydrated"
|
|
155
|
+
},
|
|
156
|
+
outcome: "rehydrated"
|
|
157
|
+
})), i.catchAllCause(() => (K("unrecovered"), i.succeed(o("read-failed")))));
|
|
158
|
+
}), ge = (e) => {
|
|
159
|
+
let t = /* @__PURE__ */ new Set();
|
|
160
|
+
return (n, r) => {
|
|
161
|
+
if (r.outcome === "unrecovered") {
|
|
162
|
+
e.error("cdc: oversized change could not be recovered — every tap (search, analytics, cdc-out, history) will miss this row; subscriptions re-query and are unaffected", {
|
|
163
|
+
table: n.table,
|
|
164
|
+
op: n.op,
|
|
165
|
+
reason: r.reason,
|
|
166
|
+
...r.reason === "no-key" ? { remedy: "run `voltro db apply` — this database's change-notify function predates the key" } : {}
|
|
167
|
+
});
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
t.has(n.table) || (t.add(n.table), e.warn("cdc: rows on this table exceed the postgres NOTIFY payload cap (8000 bytes) — their change events are re-read from the database before delivery. Counted as voltro_cdc_oversized_total.", {
|
|
171
|
+
table: n.table,
|
|
172
|
+
outcome: r.outcome,
|
|
173
|
+
note: r.outcome === "tombstone" ? "a delete of an oversized row delivers the primary key only — the pre-image is unrecoverable" : "the re-read returns the row as it is NOW, not the image at commit"
|
|
174
|
+
}));
|
|
175
|
+
};
|
|
176
|
+
}, Y = ["json"], X = ue({ scope: "voltro:postgres" }), Z = async (e) => {
|
|
177
|
+
let t = e.tracerLayer ? o.mergeAll(e.sqlLayer, e.tracerLayer) : e.sqlLayer, n = s.make(t), r = await n.runPromise(N), i = e.changeStrategy ?? "inline", a = new _e(r, n, i, e.cdcChannel ?? "framework_changes", J({
|
|
178
|
+
...e.cdcRehydrateTimeoutMs === void 0 ? {} : { rehydrateTimeoutMs: e.cdcRehydrateTimeoutMs },
|
|
179
|
+
...e.cdcRehydrateRetries === void 0 ? {} : { rehydrateRetries: e.cdcRehydrateRetries }
|
|
180
|
+
}));
|
|
181
|
+
return i === "cdc" && await a.startCdcConsumer(), a;
|
|
182
|
+
}, _e = class {
|
|
93
183
|
sql;
|
|
94
184
|
runtime;
|
|
95
185
|
changeStrategy;
|
|
96
186
|
cdcChannel;
|
|
97
|
-
|
|
187
|
+
cdcRehydrate;
|
|
188
|
+
emitter = new le();
|
|
98
189
|
cdcFiber = null;
|
|
99
190
|
inflightTxns = 0;
|
|
100
|
-
|
|
101
|
-
|
|
191
|
+
reportOversized = ge(X);
|
|
192
|
+
reportEagerFallback = C(X);
|
|
193
|
+
constructor(e, t, n, r, i = J()) {
|
|
194
|
+
this.sql = e, this.runtime = t, this.changeStrategy = n, this.cdcChannel = r, this.cdcRehydrate = i, oe(this.emitter);
|
|
195
|
+
}
|
|
196
|
+
txnSpec(e, t, n) {
|
|
197
|
+
return {
|
|
198
|
+
label: e,
|
|
199
|
+
dialect: "postgres",
|
|
200
|
+
withTransaction: (e) => this.sql.withTransaction(e),
|
|
201
|
+
runPromiseExit: (e) => this.runtime.runPromiseExit(e),
|
|
202
|
+
isRetryable: U,
|
|
203
|
+
span: {
|
|
204
|
+
name: t,
|
|
205
|
+
attributes: {
|
|
206
|
+
"db.system": "postgresql",
|
|
207
|
+
"db.operation": n
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
};
|
|
102
211
|
}
|
|
103
212
|
withNamespace(e) {
|
|
104
|
-
return e === null ? this : new
|
|
213
|
+
return e === null ? this : new ve(this, e);
|
|
105
214
|
}
|
|
106
215
|
async runInNamespace(e, t) {
|
|
216
|
+
let n = this.sql;
|
|
107
217
|
this.inflightTxns++;
|
|
108
|
-
let n = T(), i = Z(), a = this.sql, o = this.sql.withTransaction(r.flatMap(r.serviceOption(h), (o) => {
|
|
109
|
-
if (s.isNone(o)) return r.fail(/* @__PURE__ */ Error("PostgresDataStore.runInNamespace: TransactionConnection missing."));
|
|
110
|
-
let c = o.value, l = r.provideService(a`SET LOCAL search_path TO ${a(e)}`, h, c), u = new Q(this, c, n);
|
|
111
|
-
return r.flatMap(l, () => r.tryPromise({
|
|
112
|
-
try: () => i(() => t(u)).then((e) => ({
|
|
113
|
-
result: e,
|
|
114
|
-
view: u
|
|
115
|
-
})),
|
|
116
|
-
catch: (e) => e
|
|
117
|
-
}));
|
|
118
|
-
})).pipe(r.withSpan("store.namespace", { attributes: {
|
|
119
|
-
"db.system": "postgresql",
|
|
120
|
-
"db.operation": "namespace.transaction"
|
|
121
|
-
} }));
|
|
122
218
|
try {
|
|
123
|
-
|
|
124
|
-
|
|
219
|
+
return await A({
|
|
220
|
+
...this.txnSpec("PostgresDataStore.runInNamespace", "store.namespace", "namespace.transaction"),
|
|
221
|
+
prepare: (t) => i.provideService(n`SET LOCAL search_path TO ${n(e)}`, P, t),
|
|
222
|
+
work: t,
|
|
223
|
+
makeView: (e, t) => new Q(this, e, t)
|
|
224
|
+
});
|
|
125
225
|
} finally {
|
|
126
226
|
this.inflightTxns--;
|
|
127
227
|
}
|
|
128
228
|
}
|
|
129
229
|
__postgresReplicationFriend = { runEffect: (e) => this.runtime.runPromise(e) };
|
|
130
|
-
async executeQuery(e, t) {
|
|
131
|
-
let
|
|
132
|
-
return this.runtime.runPromise(
|
|
230
|
+
async executeQuery(e, t, n = null) {
|
|
231
|
+
let r = ie(e, this.sql, n), a = t ? i.provideService(r, P, t) : r;
|
|
232
|
+
return w("postgres", "select", () => this.runtime.runPromise(a));
|
|
133
233
|
}
|
|
134
|
-
async executeInsert(e, t, n,
|
|
135
|
-
t =
|
|
136
|
-
let o = this.sql, s = o`INSERT INTO ${o(e)} ${o.insert(
|
|
234
|
+
async executeInsert(e, t, n, r, a) {
|
|
235
|
+
t = j(e, t);
|
|
236
|
+
let o = this.sql, s = o`INSERT INTO ${o(e)} ${o.insert(b(t, e, Y))} RETURNING *`, c = n ? i.provideService(s, P, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
137
237
|
if (!l) throw Error(`PostgresDataStore.insert: no row returned for table '${e}'`);
|
|
138
238
|
return await this.routeEvent({
|
|
139
239
|
table: e,
|
|
140
240
|
op: "insert",
|
|
141
241
|
old: null,
|
|
142
242
|
new: l
|
|
143
|
-
},
|
|
243
|
+
}, r, n, a), l;
|
|
144
244
|
}
|
|
145
|
-
async executeUpdate(e, t, n,
|
|
146
|
-
let s = this.sql, c = s`UPDATE ${s(e)} SET ${s.update(
|
|
245
|
+
async executeUpdate(e, t, n, r, a, o) {
|
|
246
|
+
let s = this.sql, c = s`UPDATE ${s(e)} SET ${s.update(b(n, e, Y))} WHERE ${s("id")} = ${t} RETURNING *`, l = r ? i.provideService(c, P, r) : c, u = (await this.runtime.runPromise(l))[0];
|
|
147
247
|
return u ? (await this.routeEvent({
|
|
148
248
|
table: e,
|
|
149
249
|
op: "update",
|
|
150
250
|
old: null,
|
|
151
251
|
new: u
|
|
152
|
-
}, a,
|
|
252
|
+
}, a, r, o), u) : null;
|
|
153
253
|
}
|
|
154
|
-
async executeUpsert(e, t, n,
|
|
155
|
-
let
|
|
254
|
+
async executeUpsert(e, t, n, r, a, o) {
|
|
255
|
+
let s = this.sql;
|
|
156
256
|
if (typeof n.update == "function") {
|
|
157
|
-
let o = n.update,
|
|
158
|
-
let
|
|
159
|
-
return this.runtime.runPromise(
|
|
257
|
+
let o = n.update, c = n.conflictColumns.map((e) => s`${s(e)} = ${t[e]}`), l = (n) => {
|
|
258
|
+
let r = s`SELECT * FROM ${s(e)} WHERE ${s.and(c)} LIMIT 1 FOR UPDATE`;
|
|
259
|
+
return this.runtime.runPromise(i.flatMap(i.provideService(r, P, n), (r) => i.promise(() => r[0] ? this.executeUpdate(e, r[0].id, o(r[0]), n, a).then((e) => e) : this.executeInsert(e, t, n, a))));
|
|
160
260
|
};
|
|
161
|
-
if (
|
|
261
|
+
if (r) return l(r);
|
|
162
262
|
this.inflightTxns++;
|
|
163
263
|
try {
|
|
164
|
-
|
|
165
|
-
|
|
264
|
+
return await k({
|
|
265
|
+
...this.txnSpec("PostgresDataStore.upsert", "store.upsert", "upsert.transaction"),
|
|
266
|
+
body: (e) => l(e)
|
|
267
|
+
});
|
|
166
268
|
} finally {
|
|
167
269
|
this.inflightTxns--;
|
|
168
270
|
}
|
|
169
271
|
}
|
|
170
|
-
let
|
|
171
|
-
if (!
|
|
272
|
+
let c = n.conflictColumns.map((e) => s`${s(e)}`), l = Object.keys(t).filter((e) => t[e] !== void 0), u = n.update === void 0 ? l.filter((e) => e !== "id" && !n.conflictColumns.includes(e)) : n.update, d = u.length > 0 ? s.csv(u.map((e) => s`${s(e)} = EXCLUDED.${s(e)}`)) : s`${s(n.conflictColumns[0])} = EXCLUDED.${s(n.conflictColumns[0])}`, f = s`INSERT INTO ${s(e)} ${s.insert(b(t, e, Y))} ON CONFLICT (${s.csv(c)}) DO UPDATE SET ${d} RETURNING *`, p = r ? i.provideService(f, P, r) : f, m = (await this.runtime.runPromise(p))[0];
|
|
273
|
+
if (!m) throw Error(`PostgresDataStore.upsert: no row returned for table '${e}'`);
|
|
172
274
|
{
|
|
173
|
-
let n = t.id !== void 0 && t.id ===
|
|
275
|
+
let n = t.id !== void 0 && t.id === m.id ? "insert" : "update";
|
|
174
276
|
await this.routeEvent({
|
|
175
277
|
table: e,
|
|
176
278
|
op: n,
|
|
177
279
|
old: null,
|
|
178
|
-
new:
|
|
179
|
-
}, a,
|
|
280
|
+
new: m
|
|
281
|
+
}, a, r, o);
|
|
180
282
|
}
|
|
181
|
-
return
|
|
283
|
+
return m;
|
|
182
284
|
}
|
|
183
|
-
async executeInsertIgnore(e, t, n,
|
|
184
|
-
t =
|
|
185
|
-
let s = this.sql, c = n.conflictColumns.map((e) => s`${s(e)}`), l = s`INSERT INTO ${s(e)} ${s.insert(
|
|
285
|
+
async executeInsertIgnore(e, t, n, r, a, o) {
|
|
286
|
+
t = j(e, t);
|
|
287
|
+
let s = this.sql, c = n.conflictColumns.map((e) => s`${s(e)}`), l = s`INSERT INTO ${s(e)} ${s.insert(b(t, e, Y))} ON CONFLICT (${s.csv(c)}) DO NOTHING RETURNING *`, u = r ? i.provideService(l, P, r) : l, d = (await this.runtime.runPromise(u))[0];
|
|
186
288
|
if (d) return await this.routeEvent({
|
|
187
289
|
table: e,
|
|
188
290
|
op: "insert",
|
|
189
291
|
old: null,
|
|
190
292
|
new: d
|
|
191
|
-
}, a,
|
|
192
|
-
let f = n.conflictColumns.map((e) => s`${s(e)} = ${t[e]}`), p = s`SELECT * FROM ${s(e)} WHERE ${s.and(f)} LIMIT 1`, m =
|
|
193
|
-
if (!
|
|
194
|
-
return
|
|
195
|
-
}
|
|
196
|
-
async executeInsertMany(e, t, n,
|
|
197
|
-
if (t =
|
|
198
|
-
let o = this.sql, s =
|
|
293
|
+
}, a, r, o), d;
|
|
294
|
+
let f = n.conflictColumns.map((e) => s`${s(e)} = ${t[e]}`), p = s`SELECT * FROM ${s(e)} WHERE ${s.and(f)} LIMIT 1`, m = r ? i.provideService(p, P, r) : p, h = await this.runtime.runPromise(m);
|
|
295
|
+
if (!h[0]) throw Error(`PostgresDataStore.insertIgnore: the insert was skipped as a conflict, but no existing row matches conflictColumns [${n.conflictColumns.join(", ")}] on '${e}'. A DIFFERENT unique constraint fired — a second unique index, or the primary key when you named something else. insertIgnore models ONE conflict target: name the columns of the constraint that actually collides, or handle the unique violation yourself.`);
|
|
296
|
+
return h[0];
|
|
297
|
+
}
|
|
298
|
+
async executeInsertMany(e, t, n, r, a) {
|
|
299
|
+
if (t = ce(e, t), t.length === 0) return [];
|
|
300
|
+
let o = this.sql, s = ne(t.map((t) => b(t, e, Y)), te("postgres")), c = (t) => o`INSERT INTO ${o(e)} ${o.insert(t)} RETURNING *`, l;
|
|
301
|
+
if (s.length === 1) {
|
|
302
|
+
let e = c(s[0]), t = n ? i.provideService(e, P, n) : e;
|
|
303
|
+
l = await this.runtime.runPromise(t);
|
|
304
|
+
} else if (n) {
|
|
305
|
+
let e = [];
|
|
306
|
+
for (let t of s) e.push(...await this.runtime.runPromise(i.provideService(c(t), P, n)));
|
|
307
|
+
l = e;
|
|
308
|
+
} else l = await this.runtime.runPromise(o.withTransaction(i.map(i.forEach(s, c, { concurrency: 1 }), (e) => e.flat())));
|
|
199
309
|
for (let t of l) await this.routeEvent({
|
|
200
310
|
table: e,
|
|
201
311
|
op: "insert",
|
|
202
312
|
old: null,
|
|
203
313
|
new: t
|
|
204
|
-
},
|
|
314
|
+
}, r, n, a);
|
|
205
315
|
return l;
|
|
206
316
|
}
|
|
207
|
-
async executePatchJson(e, t, n,
|
|
208
|
-
let c = this.sql, l = n.split("."), u = l[0], d = l.slice(1), f = JSON.stringify(
|
|
209
|
-
return
|
|
317
|
+
async executePatchJson(e, t, n, r, a, o, s) {
|
|
318
|
+
let c = this.sql, l = n.split("."), u = l[0], d = l.slice(1), f = JSON.stringify(r ?? null), p = d.length === 0 ? c`${c(u)} = COALESCE(${c(u)}, '{}'::jsonb) || ${f}::jsonb` : c`${c(u)} = jsonb_set(COALESCE(${c(u)}, '{}'::jsonb), ${`{${d.join(",")}}`}, ${f}::jsonb, true)`, m = c`UPDATE ${c(e)} SET ${p} WHERE ${c("id")} = ${t} RETURNING *`, h = a ? i.provideService(m, P, a) : m, g = (await this.runtime.runPromise(h))[0];
|
|
319
|
+
return g ? (await this.routeEvent({
|
|
210
320
|
table: e,
|
|
211
321
|
op: "update",
|
|
212
322
|
old: null,
|
|
213
|
-
new:
|
|
214
|
-
}, o, a, s),
|
|
323
|
+
new: g
|
|
324
|
+
}, o, a, s), g) : null;
|
|
215
325
|
}
|
|
216
|
-
async executeDelete(e, t, n,
|
|
217
|
-
let o = this.sql, s = o`DELETE FROM ${o(e)} WHERE ${o("id")} = ${t} RETURNING *`, c = n ?
|
|
326
|
+
async executeDelete(e, t, n, r, a) {
|
|
327
|
+
let o = this.sql, s = o`DELETE FROM ${o(e)} WHERE ${o("id")} = ${t} RETURNING *`, c = n ? i.provideService(s, P, n) : s, l = (await this.runtime.runPromise(c))[0];
|
|
218
328
|
return l ? (await this.routeEvent({
|
|
219
329
|
table: e,
|
|
220
330
|
op: "delete",
|
|
221
331
|
old: l,
|
|
222
332
|
new: null
|
|
223
|
-
},
|
|
333
|
+
}, r, n, a), !0) : !1;
|
|
224
334
|
}
|
|
225
335
|
async appendInTxn(e, t, n) {
|
|
226
|
-
let
|
|
227
|
-
await this.runtime.runPromise(n ?
|
|
336
|
+
let r = this.sql, a = r`INSERT INTO ${r(e)} ${r.insert(b(t, e, Y))}`;
|
|
337
|
+
await this.runtime.runPromise(n ? i.provideService(a, P, n) : a);
|
|
228
338
|
}
|
|
229
|
-
async maxInTxn(e, t, n,
|
|
230
|
-
let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(e)} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(
|
|
339
|
+
async maxInTxn(e, t, n, r) {
|
|
340
|
+
let a = this.sql, o = Object.entries(n).map(([e, t]) => a`${a(e)} = ${t}`), s = a`SELECT MAX(${a(t)}) AS ${a("m")} FROM ${a(e)} WHERE ${a.and(o)}`, c = (await this.runtime.runPromise(r ? i.provideService(s, P, r) : s))[0]?.m;
|
|
231
341
|
return c == null ? null : Number(c);
|
|
232
342
|
}
|
|
233
343
|
async routeEvent(e, t, n = null, r) {
|
|
234
344
|
if (e = {
|
|
235
|
-
...
|
|
345
|
+
...g(r),
|
|
236
346
|
...e
|
|
237
|
-
},
|
|
347
|
+
}, T(e.table) && await se({
|
|
238
348
|
append: (e, t) => this.appendInTxn(e, t, n),
|
|
239
349
|
maxOf: (e, t, r) => this.maxInTxn(e, t, r, n)
|
|
240
350
|
}, {
|
|
@@ -244,10 +354,10 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
244
354
|
prev: e.old,
|
|
245
355
|
traceId: e.traceId,
|
|
246
356
|
subjectId: e.subjectId
|
|
247
|
-
}),
|
|
357
|
+
}), S(e.table)) {
|
|
248
358
|
if (this.changeStrategy === "cdc") {
|
|
249
359
|
let t = (e.op === "delete" ? e.old : e.new)?.id;
|
|
250
|
-
t != null &&
|
|
360
|
+
t != null && E(ee(e.table, e.op, t), {
|
|
251
361
|
...e.traceId === void 0 ? {} : { traceId: e.traceId },
|
|
252
362
|
...e.subjectId === void 0 ? {} : { subjectId: e.subjectId }
|
|
253
363
|
});
|
|
@@ -260,79 +370,94 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
260
370
|
return this.runWithEager(e, null);
|
|
261
371
|
}
|
|
262
372
|
raw(e, t) {
|
|
263
|
-
let n =
|
|
264
|
-
return this.runtime.runPromise(n);
|
|
265
|
-
}
|
|
266
|
-
async runWithEager(e, t) {
|
|
267
|
-
if (!
|
|
268
|
-
let
|
|
269
|
-
if (
|
|
270
|
-
let e = t ?
|
|
271
|
-
return
|
|
272
|
-
} catch (
|
|
273
|
-
if (
|
|
274
|
-
|
|
373
|
+
let n = re(e, this.sql);
|
|
374
|
+
return w("postgres", "raw", () => this.runtime.runPromise(n));
|
|
375
|
+
}
|
|
376
|
+
async runWithEager(e, t, n = null) {
|
|
377
|
+
if (!x(e)) return this.executeQuery(e, t, n);
|
|
378
|
+
let r = n === null ? v(e, this.sql, "postgres") : null;
|
|
379
|
+
if (r !== null) try {
|
|
380
|
+
let e = t ? i.provideService(r.fragment, P, t) : r.fragment, n = await w("postgres", "select", () => this.runtime.runPromise(e));
|
|
381
|
+
return r.decode(n);
|
|
382
|
+
} catch (t) {
|
|
383
|
+
if (t instanceof m) throw t;
|
|
384
|
+
this.reportEagerFallback({
|
|
385
|
+
dialect: "postgres",
|
|
386
|
+
table: e.table,
|
|
387
|
+
reason: "execute-failed",
|
|
388
|
+
error: t
|
|
389
|
+
});
|
|
275
390
|
}
|
|
276
|
-
|
|
391
|
+
else this.reportEagerFallback({
|
|
392
|
+
dialect: "postgres",
|
|
393
|
+
table: e.table,
|
|
394
|
+
reason: "not-compilable"
|
|
395
|
+
});
|
|
396
|
+
return h(await this.executeQuery(e, t, n), e.eager, e.sourceTable ?? D(e.table), (e) => this.executeQuery(e, t, n));
|
|
277
397
|
}
|
|
278
398
|
getInternalRunWithEager() {
|
|
279
399
|
return (e, t) => this.runWithEager(e, t);
|
|
280
400
|
}
|
|
281
|
-
async
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
401
|
+
async queryInNamespace(e, t) {
|
|
402
|
+
return this.runWithEager(t, null, e);
|
|
403
|
+
}
|
|
404
|
+
async localWrite(e, t, n) {
|
|
405
|
+
return w("postgres", e, async () => {
|
|
406
|
+
if (this.changeStrategy !== "cdc") return M(n);
|
|
407
|
+
_(t);
|
|
408
|
+
try {
|
|
409
|
+
return await M(n);
|
|
410
|
+
} finally {
|
|
411
|
+
ae(t);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
289
414
|
}
|
|
290
415
|
insert(e, t) {
|
|
291
|
-
return this.localWrite(e, (n) => this.executeInsert(e, t, null, null, n));
|
|
416
|
+
return this.localWrite("insert", e, (n) => this.executeInsert(e, t, null, null, n));
|
|
292
417
|
}
|
|
293
418
|
insertMany(e, t) {
|
|
294
|
-
return this.localWrite(e, (n) => this.executeInsertMany(e, t, null, null, n));
|
|
419
|
+
return this.localWrite("insert", e, (n) => this.executeInsertMany(e, t, null, null, n));
|
|
295
420
|
}
|
|
296
421
|
patchJson(e, t, n, r) {
|
|
297
|
-
return this.localWrite(e, (i) => this.executePatchJson(e, t, n, r, null, null, i));
|
|
422
|
+
return this.localWrite("update", e, (i) => this.executePatchJson(e, t, n, r, null, null, i));
|
|
298
423
|
}
|
|
299
424
|
update(e, t, n) {
|
|
300
|
-
return this.localWrite(e, (r) => this.executeUpdate(e, t, n, null, null, r));
|
|
425
|
+
return this.localWrite("update", e, (r) => this.executeUpdate(e, t, n, null, null, r));
|
|
301
426
|
}
|
|
302
427
|
delete(e, t) {
|
|
303
|
-
return this.localWrite(e, (n) => this.executeDelete(e, t, null, null, n));
|
|
428
|
+
return this.localWrite("delete", e, (n) => this.executeDelete(e, t, null, null, n));
|
|
304
429
|
}
|
|
305
430
|
async updateMany(e, t, n) {
|
|
306
|
-
return this.localWrite(e, (r) => this.executeUpdateMany(e, t, n, null, null, r));
|
|
431
|
+
return this.localWrite("update", e, (r) => this.executeUpdateMany(e, t, n, null, null, r));
|
|
307
432
|
}
|
|
308
433
|
async deleteMany(e, t) {
|
|
309
|
-
return this.localWrite(e, (n) => this.executeDeleteMany(e, t, null, null, n));
|
|
434
|
+
return this.localWrite("delete", e, (n) => this.executeDeleteMany(e, t, null, null, n));
|
|
310
435
|
}
|
|
311
|
-
async executeUpdateMany(e, t, n,
|
|
312
|
-
let s = this.sql, c =
|
|
436
|
+
async executeUpdateMany(e, t, n, r, a, o) {
|
|
437
|
+
let s = this.sql, c = y(n.where, s), l = s`UPDATE ${s(e)} SET ${s.update(b(t, e, Y))} WHERE ${c} RETURNING *`, u = r ? i.provideService(l, P, r) : l, d = await this.runtime.runPromise(u);
|
|
313
438
|
for (let t of d) await this.routeEvent({
|
|
314
439
|
table: e,
|
|
315
440
|
op: "update",
|
|
316
441
|
old: null,
|
|
317
442
|
new: t
|
|
318
|
-
}, a,
|
|
443
|
+
}, a, r, o);
|
|
319
444
|
return d.length;
|
|
320
445
|
}
|
|
321
|
-
async executeDeleteMany(e, t, n,
|
|
322
|
-
let o = this.sql, s =
|
|
446
|
+
async executeDeleteMany(e, t, n, r, a) {
|
|
447
|
+
let o = this.sql, s = y(t.where, o), c = o`DELETE FROM ${o(e)} WHERE ${s} RETURNING *`, l = n ? i.provideService(c, P, n) : c, u = await this.runtime.runPromise(l);
|
|
323
448
|
for (let t of u) await this.routeEvent({
|
|
324
449
|
table: e,
|
|
325
450
|
op: "delete",
|
|
326
451
|
old: t,
|
|
327
452
|
new: null
|
|
328
|
-
},
|
|
453
|
+
}, r, n, a);
|
|
329
454
|
return u.length;
|
|
330
455
|
}
|
|
331
456
|
upsert(e, t, n) {
|
|
332
|
-
return this.localWrite(e, (r) => this.executeUpsert(e, t, n, null, null, r));
|
|
457
|
+
return this.localWrite("upsert", e, (r) => this.executeUpsert(e, t, n, null, null, r));
|
|
333
458
|
}
|
|
334
459
|
insertIgnore(e, t, n) {
|
|
335
|
-
return this.localWrite(e, (r) => this.executeInsertIgnore(e, t, n, null, null, r));
|
|
460
|
+
return this.localWrite("upsert", e, (r) => this.executeInsertIgnore(e, t, n, null, null, r));
|
|
336
461
|
}
|
|
337
462
|
emitChange(e) {
|
|
338
463
|
this.emitter.emit("change", e);
|
|
@@ -368,28 +493,13 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
368
493
|
return this.executeInsertIgnore.bind(this);
|
|
369
494
|
}
|
|
370
495
|
async transactional(e) {
|
|
371
|
-
this.inflightTxns
|
|
372
|
-
let t = Z(), n = 0, i = r.suspend(() => {
|
|
373
|
-
let i = ++n;
|
|
374
|
-
return this.sql.withTransaction(r.flatMap(r.serviceOption(h), (n) => {
|
|
375
|
-
if (s.isNone(n)) return r.fail(/* @__PURE__ */ Error("PostgresDataStore.transactional: TransactionConnection unexpectedly missing inside withTransaction."));
|
|
376
|
-
let a = new Q(this, n.value);
|
|
377
|
-
return r.tryPromise({
|
|
378
|
-
try: () => t(() => e(a)).then((e) => ({
|
|
379
|
-
result: e,
|
|
380
|
-
view: a,
|
|
381
|
-
attempt: i
|
|
382
|
-
})),
|
|
383
|
-
catch: (e) => e
|
|
384
|
-
});
|
|
385
|
-
}));
|
|
386
|
-
}), a = l.exponential("10 millis").pipe(l.compose(l.recurs(3)), l.whileInput(K)), o = i.pipe(r.retry(a), r.withSpan("store.transactional", { attributes: {
|
|
387
|
-
"db.system": "postgresql",
|
|
388
|
-
"db.operation": "transaction"
|
|
389
|
-
} }));
|
|
496
|
+
this.inflightTxns++;
|
|
390
497
|
try {
|
|
391
|
-
|
|
392
|
-
|
|
498
|
+
return await A({
|
|
499
|
+
...this.txnSpec("PostgresDataStore.transactional", "store.transactional", "transaction"),
|
|
500
|
+
work: e,
|
|
501
|
+
makeView: (e, t) => new Q(this, e, t)
|
|
502
|
+
});
|
|
393
503
|
} finally {
|
|
394
504
|
this.inflightTxns--;
|
|
395
505
|
}
|
|
@@ -403,9 +513,9 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
403
513
|
return this.changeStrategy === "cdc" ? "fleet" : "local";
|
|
404
514
|
}
|
|
405
515
|
injectExternalChange(e) {
|
|
406
|
-
if (!
|
|
516
|
+
if (!S(e.table)) return;
|
|
407
517
|
let t = (e.op === "delete" ? e.old : e.new)?.id;
|
|
408
|
-
|
|
518
|
+
O(e.table, e.op, t, (t) => {
|
|
409
519
|
this.emitter.emit("change", {
|
|
410
520
|
...t,
|
|
411
521
|
...e,
|
|
@@ -420,26 +530,53 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
420
530
|
if (this.inflightTxns > 0) {
|
|
421
531
|
let t = Date.now() + e;
|
|
422
532
|
for (; this.inflightTxns > 0 && Date.now() < t;) await new Promise((e) => setTimeout(e, 25));
|
|
423
|
-
this.inflightTxns > 0 &&
|
|
533
|
+
this.inflightTxns > 0 && X.warn("close: grace period expired with in-flight transactions — forcing dispose", {
|
|
424
534
|
gracePeriodMs: e,
|
|
425
535
|
inflight: this.inflightTxns
|
|
426
536
|
});
|
|
427
537
|
}
|
|
428
|
-
this.cdcFiber &&= (await this.runtime.runPromise(
|
|
538
|
+
this.cdcFiber &&= (await this.runtime.runPromise(a.interrupt(this.cdcFiber)), null), await this.runtime.dispose();
|
|
429
539
|
}
|
|
430
540
|
async ping() {
|
|
431
541
|
await this.runtime.runPromise(this.sql`SELECT 1`);
|
|
432
542
|
}
|
|
543
|
+
readRowAsCdcJson(e, t, n) {
|
|
544
|
+
let r = this.sql, a = e === void 0 || e === "" ? r`${r(t)}` : r`${r(e)}.${r(t)}`;
|
|
545
|
+
return r`
|
|
546
|
+
SELECT row_to_json(t)::text AS ${r("payload")} FROM ${a} t WHERE t.${r("id")} = ${n} LIMIT 1
|
|
547
|
+
`.pipe(i.map((e) => {
|
|
548
|
+
let t = e[0]?.payload;
|
|
549
|
+
return t == null ? null : JSON.parse(t);
|
|
550
|
+
}));
|
|
551
|
+
}
|
|
433
552
|
async startCdcConsumer() {
|
|
434
|
-
let e = (await this.runtime.runPromise(t.PgClient)).listen(this.cdcChannel), n = (e) => {
|
|
553
|
+
let e = (await this.runtime.runPromise(t.PgClient)).listen(this.cdcChannel), n = (e) => i.suspend(() => {
|
|
554
|
+
let t;
|
|
435
555
|
try {
|
|
436
|
-
|
|
437
|
-
this.injectExternalChange(t);
|
|
556
|
+
t = JSON.parse(e);
|
|
438
557
|
} catch (e) {
|
|
439
|
-
|
|
558
|
+
return X.warn("cdc: bad payload", { channel: this.cdcChannel }, e), i.void;
|
|
440
559
|
}
|
|
441
|
-
|
|
442
|
-
|
|
560
|
+
if (t.oversized !== !0) {
|
|
561
|
+
let e = {
|
|
562
|
+
table: t.table,
|
|
563
|
+
op: t.op,
|
|
564
|
+
old: t.old,
|
|
565
|
+
new: t.new
|
|
566
|
+
};
|
|
567
|
+
return i.sync(() => {
|
|
568
|
+
this.injectExternalChange(e);
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
return S(t.table) ? he({
|
|
572
|
+
notification: t,
|
|
573
|
+
fetchRow: ({ schema: e, table: t, key: n }) => this.readRowAsCdcJson(e, t, n),
|
|
574
|
+
tunables: this.cdcRehydrate
|
|
575
|
+
}).pipe(i.map((e) => {
|
|
576
|
+
this.reportOversized(t, e), this.injectExternalChange(e.event);
|
|
577
|
+
})) : i.void;
|
|
578
|
+
});
|
|
579
|
+
this.cdcFiber = this.runtime.runFork(e.pipe(d.runForEach(n)));
|
|
443
580
|
}
|
|
444
581
|
}, Q = class {
|
|
445
582
|
parent;
|
|
@@ -496,14 +633,14 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
496
633
|
this.events.length = 0;
|
|
497
634
|
}
|
|
498
635
|
}
|
|
499
|
-
},
|
|
636
|
+
}, ve = class {
|
|
500
637
|
parent;
|
|
501
638
|
namespace;
|
|
502
639
|
constructor(e, t) {
|
|
503
640
|
this.parent = e, this.namespace = t;
|
|
504
641
|
}
|
|
505
642
|
query(e) {
|
|
506
|
-
return this.parent.
|
|
643
|
+
return this.parent.queryInNamespace(this.namespace, e);
|
|
507
644
|
}
|
|
508
645
|
insert(e, t) {
|
|
509
646
|
return this.parent.runInNamespace(this.namespace, (n) => n.insert(e, t));
|
|
@@ -550,39 +687,39 @@ var R = (e) => e ? { rejectUnauthorized: !1 } : !1, z = /^[A-Za-z_][A-Za-z0-9_]*
|
|
|
550
687
|
return r === void 0 ? Promise.reject(/* @__PURE__ */ Error("PostgresNamespaceView.raw: underlying store has no raw()")) : r(e, t);
|
|
551
688
|
});
|
|
552
689
|
}
|
|
553
|
-
}, $ = (e) => e.__postgresReplicationFriend ?? null,
|
|
690
|
+
}, $ = (e) => e.__postgresReplicationFriend ?? null, ye = (e, t) => {
|
|
554
691
|
let [n, r] = e.split("/"), [i, a] = t.split("/");
|
|
555
692
|
if (!n || !r || !i || !a) throw Error(`postgres LSN compare: invalid format (${e} vs ${t})`);
|
|
556
693
|
let o = parseInt(n, 16), s = parseInt(r, 16), c = parseInt(i, 16);
|
|
557
694
|
return o === c ? s - parseInt(a, 16) : o - c;
|
|
558
|
-
},
|
|
695
|
+
}, be = () => ({
|
|
559
696
|
async capturePrimaryPosition(e) {
|
|
560
697
|
let t = $(e);
|
|
561
698
|
if (t === null) throw Error("postgresReplicationAdapter: primary is not a PostgresDataStore (missing __postgresReplicationFriend). Pass the postgres store directly.");
|
|
562
|
-
return t.runEffect(
|
|
563
|
-
let e = (yield* (yield*
|
|
564
|
-
return typeof e == "string" ? e : yield*
|
|
699
|
+
return t.runEffect(i.gen(function* () {
|
|
700
|
+
let e = (yield* (yield* N)`SELECT pg_current_wal_lsn()::text AS lsn`)[0]?.lsn;
|
|
701
|
+
return typeof e == "string" ? e : yield* i.die("postgres did not return a WAL LSN");
|
|
565
702
|
}));
|
|
566
703
|
},
|
|
567
704
|
async probeReplicaPosition(e) {
|
|
568
705
|
let t = $(e);
|
|
569
706
|
if (t === null) throw Error("postgresReplicationAdapter: replica is not a PostgresDataStore.");
|
|
570
|
-
return t.runEffect(
|
|
571
|
-
let e = (yield* (yield*
|
|
707
|
+
return t.runEffect(i.gen(function* () {
|
|
708
|
+
let e = (yield* (yield* N)`
|
|
572
709
|
SELECT COALESCE(pg_last_wal_replay_lsn()::text, pg_current_wal_lsn()::text) AS lsn
|
|
573
710
|
`)[0]?.lsn;
|
|
574
|
-
return typeof e == "string" ? e : yield*
|
|
711
|
+
return typeof e == "string" ? e : yield* i.die("postgres did not return a replay LSN");
|
|
575
712
|
}));
|
|
576
713
|
},
|
|
577
714
|
compare(e, t) {
|
|
578
|
-
return
|
|
715
|
+
return ye(t, e) >= 0 ? "caught-up" : "behind";
|
|
579
716
|
}
|
|
580
|
-
}),
|
|
717
|
+
}), xe = {
|
|
581
718
|
id: "postgres",
|
|
582
|
-
makeSqlLayer: (e) =>
|
|
583
|
-
makeStore: (e) =>
|
|
719
|
+
makeSqlLayer: (e) => H(e),
|
|
720
|
+
makeStore: (e) => Z(e),
|
|
584
721
|
compileContains: (e, t, n) => n`${e} ILIKE ${`%${t.replace(/[\\%_]/g, (e) => `\\${e}`)}%`} ESCAPE '\\'`,
|
|
585
|
-
retryFilter:
|
|
722
|
+
retryFilter: W
|
|
586
723
|
};
|
|
587
724
|
//#endregion
|
|
588
|
-
export { e as PgClient,
|
|
725
|
+
export { e as PgClient, V as connectionFromConfig, Z as makePostgresDataStore, z as makePostgresSqlLayer, H as makePostgresSqlLayerFromConfig, xe as postgresDialect, be as postgresReplicationAdapter, W as postgresRetryFilter };
|