@rotorsoft/act-pg 1.12.0 → 1.13.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/dist/.tsbuildinfo +1 -1
- package/dist/@types/postgres-store.d.ts +8 -1
- package/dist/@types/postgres-store.d.ts.map +1 -1
- package/dist/index.cjs +96 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +96 -51
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-store.d.ts","sourceRoot":"","sources":["../../src/postgres-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,SAAS,EACT,KAAK,EAEL,OAAO,EACP,cAAc,EACd,KAAK,EACL,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,MAAM,EACN,OAAO,EACP,KAAK,EACL,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAQxB,OAAO,EAEL,KAAK,UAAU,EAGhB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;AAUpB,KAAK,MAAM,GAAG,QAAQ,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,cAAc,CAAC,EAAE,UAAU,CAAC;CAC7B,CAAC,GACA,EAAE,CAAC,UAAU,CAAC;AA2EhB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2GG;AACH,qBAAa,aAAc,YAAW,KAAK;IACzC,OAAO,CAAC,KAAK,CAAC;IACd,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,IAAI,CAAS;IACrB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAwB;IAC5C;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,8DAA8D;IAC9D,OAAO,CAAC,cAAc,CAA4B;IAClD;;;;;OAKG;IACH,OAAO,CAAC,eAAe,CAA+C;IACtE;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,CAAC,YAAY,EAAE,iBAAiB,KAAK,IAAI,KAC/C,OAAO,CAAC,cAAc,CAAC,CAAC;IAE7B;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsC;IAEvE;;;OAGG;gBACS,MAAM,GAAE,OAAO,CAAC,MAAM,CAAM;IAyBxC;;;;;;;OAOG;YACW,OAAO;IAQrB;;;;OAIG;IACG,OAAO;IAKb;;;;;;OAMG;YACW,gBAAgB;IAe9B;;;;OAIG;IACG,IAAI;IAuIV;;;OAGG;IACG,IAAI;IAoBV;;;;;;;;;OASG;IACG,KAAK,CAAC,CAAC,SAAS,OAAO,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,EAChD,KAAK,CAAC,EAAE,KAAK;IAgGf;;;;;;;;;OASG;IACG,MAAM,CAAC,CAAC,SAAS,OAAO,EAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,EAC3B,IAAI,EAAE,SAAS,EACf,eAAe,CAAC,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"postgres-store.d.ts","sourceRoot":"","sources":["../../src/postgres-store.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -439,16 +439,13 @@ var PostgresStore = class {
|
|
|
439
439
|
async commit(stream, msgs, meta, expectedVersion) {
|
|
440
440
|
if (msgs.length === 0) return [];
|
|
441
441
|
const client = await this._client("commit");
|
|
442
|
-
let version = -1;
|
|
443
442
|
try {
|
|
444
|
-
await client.query("BEGIN");
|
|
445
443
|
const last = await client.query(
|
|
446
|
-
`SELECT version
|
|
447
|
-
|
|
448
|
-
WHERE stream=$1 ORDER BY version DESC LIMIT 1`,
|
|
444
|
+
`SELECT version FROM ${this._fqt}
|
|
445
|
+
WHERE stream=$1 ORDER BY version DESC LIMIT 1`,
|
|
449
446
|
[stream]
|
|
450
447
|
);
|
|
451
|
-
version = last.
|
|
448
|
+
let version = last.rows.at(0)?.version ?? -1;
|
|
452
449
|
if (typeof expectedVersion === "number" && version !== expectedVersion)
|
|
453
450
|
throw new import_act.ConcurrencyError(
|
|
454
451
|
stream,
|
|
@@ -456,52 +453,69 @@ var PostgresStore = class {
|
|
|
456
453
|
msgs,
|
|
457
454
|
expectedVersion
|
|
458
455
|
);
|
|
459
|
-
const
|
|
456
|
+
const base_version = version;
|
|
457
|
+
const names = [];
|
|
458
|
+
const datas = [];
|
|
459
|
+
const piis = [];
|
|
460
|
+
const versions = [];
|
|
460
461
|
for (const { name, data, pii } of msgs) {
|
|
461
462
|
version++;
|
|
462
|
-
|
|
463
|
+
names.push(name);
|
|
464
|
+
datas.push(JSON.stringify(data));
|
|
465
|
+
piis.push(
|
|
466
|
+
this._resolve_pii_key && pii != null ? JSON.stringify(await (0, import_act_crypto.encrypt)(pii, this._resolve_pii_key)) : pii != null ? JSON.stringify(pii) : null
|
|
467
|
+
);
|
|
468
|
+
versions.push(version);
|
|
469
|
+
}
|
|
470
|
+
const insert_select = msgs.length === 1 ? `SELECT $1, $2::jsonb, $3::jsonb, $5, $4::int, $6 FROM l` : `SELECT u.name, u.data::jsonb, u.pii::jsonb, $5, u.version, $6
|
|
471
|
+
FROM l, unnest($1::text[], $2::text[], $3::text[], $4::int[])
|
|
472
|
+
WITH ORDINALITY AS u(name, data, pii, version, ord)
|
|
473
|
+
ORDER BY u.ord`;
|
|
474
|
+
const notify_ctes = this.config.notify ? `,
|
|
475
|
+
payload AS (
|
|
476
|
+
SELECT json_build_object(
|
|
477
|
+
'stream', $5::text,
|
|
478
|
+
'events', json_agg(json_build_object('id', ins.id, 'name', ins.name) ORDER BY ins.version),
|
|
479
|
+
'by', $9::text
|
|
480
|
+
)::text AS p
|
|
481
|
+
FROM ins
|
|
482
|
+
),
|
|
483
|
+
n AS (
|
|
484
|
+
SELECT pg_notify($8, payload.p) FROM payload
|
|
485
|
+
WHERE octet_length(payload.p) < $10
|
|
486
|
+
)` : "";
|
|
487
|
+
const final_select = this.config.notify ? "SELECT ins.* FROM ins LEFT JOIN n ON true ORDER BY ins.version" : "SELECT * FROM ins ORDER BY version";
|
|
488
|
+
const sql = `WITH l AS (SELECT pg_advisory_xact_lock(hashtext($7))),
|
|
489
|
+
ins AS (
|
|
463
490
|
INSERT INTO ${this._fqt}(name, data, pii, stream, version, meta)
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
stream,
|
|
479
|
-
version - 1,
|
|
480
|
-
msgs,
|
|
481
|
-
expectedVersion ?? -1
|
|
482
|
-
);
|
|
491
|
+
${insert_select}
|
|
492
|
+
RETURNING *
|
|
493
|
+
)${notify_ctes}
|
|
494
|
+
${final_select}`;
|
|
495
|
+
const base_params = msgs.length === 1 ? [names[0], datas[0], piis[0], versions[0], stream, meta, this._fqt] : [names, datas, piis, versions, stream, meta, this._fqt];
|
|
496
|
+
const params = this.config.notify ? [...base_params, this._channel, this._by, NOTIFY_MAX_PAYLOAD_BYTES] : base_params;
|
|
497
|
+
try {
|
|
498
|
+
const { rows } = await client.query(sql, params);
|
|
499
|
+
if (this._resolve_pii_key) {
|
|
500
|
+
for (const row of rows) {
|
|
501
|
+
if (typeof row.pii === "string") {
|
|
502
|
+
const decrypted = await (0, import_act_crypto.decrypt)(row.pii, this._resolve_pii_key);
|
|
503
|
+
row.pii = decrypted;
|
|
504
|
+
}
|
|
483
505
|
}
|
|
484
|
-
throw error;
|
|
485
506
|
}
|
|
507
|
+
return rows;
|
|
508
|
+
} catch (error) {
|
|
509
|
+
if (error?.code === PG_UNIQUE_VIOLATION) {
|
|
510
|
+
throw new import_act.ConcurrencyError(
|
|
511
|
+
stream,
|
|
512
|
+
base_version,
|
|
513
|
+
msgs,
|
|
514
|
+
expectedVersion ?? -1
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
throw error;
|
|
486
518
|
}
|
|
487
|
-
if (this.config.notify) {
|
|
488
|
-
const payload = JSON.stringify({
|
|
489
|
-
stream,
|
|
490
|
-
events: committed.map((c) => ({ id: c.id, name: c.name })),
|
|
491
|
-
by: this._by
|
|
492
|
-
});
|
|
493
|
-
if (Buffer.byteLength(payload, "utf8") < NOTIFY_MAX_PAYLOAD_BYTES)
|
|
494
|
-
await client.query(`SELECT pg_notify($1, $2)`, [
|
|
495
|
-
this._channel,
|
|
496
|
-
payload
|
|
497
|
-
]);
|
|
498
|
-
}
|
|
499
|
-
await client.query("COMMIT");
|
|
500
|
-
return committed;
|
|
501
|
-
} catch (error) {
|
|
502
|
-
await client.query("ROLLBACK").catch(() => {
|
|
503
|
-
});
|
|
504
|
-
throw error;
|
|
505
519
|
} finally {
|
|
506
520
|
client.release();
|
|
507
521
|
}
|
|
@@ -1226,20 +1240,30 @@ var PostgresStore = class {
|
|
|
1226
1240
|
}
|
|
1227
1241
|
/**
|
|
1228
1242
|
* Atomically truncates streams and seeds each with a snapshot or tombstone.
|
|
1229
|
-
*
|
|
1243
|
+
* Windowed targets (`before` set) prune the prefix below the closest safe
|
|
1244
|
+
* `__snapshot__` instead — no seed, subscriptions untouched, no-op when no
|
|
1245
|
+
* snapshot qualifies.
|
|
1246
|
+
* @param targets - Streams to truncate with optional snapshot state and meta,
|
|
1247
|
+
* or a `before`/`max_id` boundary for a windowed prefix delete.
|
|
1230
1248
|
* @returns Map keyed by stream name, each entry with `deleted` count and `committed` event.
|
|
1231
1249
|
*/
|
|
1232
1250
|
async truncate(targets) {
|
|
1233
1251
|
if (!targets.length) return /* @__PURE__ */ new Map();
|
|
1234
|
-
const
|
|
1252
|
+
const full = targets.filter((t) => t.before === void 0);
|
|
1253
|
+
const windowed = targets.filter((t) => t.before !== void 0);
|
|
1235
1254
|
const client = await this._client("truncate");
|
|
1236
1255
|
try {
|
|
1237
1256
|
await client.query("BEGIN");
|
|
1238
|
-
await client.query(
|
|
1239
|
-
|
|
1257
|
+
await client.query("SELECT pg_advisory_xact_lock(hashtext($1))", [
|
|
1258
|
+
this._fqt
|
|
1240
1259
|
]);
|
|
1241
1260
|
const result = /* @__PURE__ */ new Map();
|
|
1242
|
-
|
|
1261
|
+
if (full.length) {
|
|
1262
|
+
await client.query(`DELETE FROM ${this._fqs} WHERE stream = ANY($1)`, [
|
|
1263
|
+
full.map((t) => t.stream)
|
|
1264
|
+
]);
|
|
1265
|
+
}
|
|
1266
|
+
for (const { stream, snapshot, meta } of full) {
|
|
1243
1267
|
const { rowCount } = await client.query(
|
|
1244
1268
|
`DELETE FROM ${this._fqt} WHERE stream = $1`,
|
|
1245
1269
|
[stream]
|
|
@@ -1260,6 +1284,27 @@ var PostgresStore = class {
|
|
|
1260
1284
|
committed: rows[0]
|
|
1261
1285
|
});
|
|
1262
1286
|
}
|
|
1287
|
+
for (const { stream, before, max_id } of windowed) {
|
|
1288
|
+
const { rows } = await client.query(
|
|
1289
|
+
`SELECT id, stream, version, name, data, created, meta
|
|
1290
|
+
FROM ${this._fqt}
|
|
1291
|
+
WHERE stream = $1 AND name = $2 AND created < $3
|
|
1292
|
+
AND ($4::int IS NULL OR id <= $4)
|
|
1293
|
+
ORDER BY id DESC LIMIT 1`,
|
|
1294
|
+
[stream, import_act.SNAP_EVENT, before, max_id ?? null]
|
|
1295
|
+
);
|
|
1296
|
+
if (!rows.length) continue;
|
|
1297
|
+
const boundary = rows[0];
|
|
1298
|
+
const { rowCount } = await client.query(
|
|
1299
|
+
`DELETE FROM ${this._fqt} WHERE stream = $1 AND id < $2`,
|
|
1300
|
+
[stream, boundary.id]
|
|
1301
|
+
);
|
|
1302
|
+
result.set(stream, {
|
|
1303
|
+
deleted: rowCount ?? 0,
|
|
1304
|
+
committed: boundary,
|
|
1305
|
+
before
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1263
1308
|
await client.query("COMMIT");
|
|
1264
1309
|
return result;
|
|
1265
1310
|
} catch (error) {
|