@rotorsoft/act-pg 1.13.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.map +1 -1
- package/dist/index.cjs +63 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +63 -46
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -413,16 +413,13 @@ var PostgresStore = class {
|
|
|
413
413
|
async commit(stream, msgs, meta, expectedVersion) {
|
|
414
414
|
if (msgs.length === 0) return [];
|
|
415
415
|
const client = await this._client("commit");
|
|
416
|
-
let version = -1;
|
|
417
416
|
try {
|
|
418
|
-
await client.query("BEGIN");
|
|
419
417
|
const last = await client.query(
|
|
420
|
-
`SELECT version
|
|
421
|
-
|
|
422
|
-
WHERE stream=$1 ORDER BY version DESC LIMIT 1`,
|
|
418
|
+
`SELECT version FROM ${this._fqt}
|
|
419
|
+
WHERE stream=$1 ORDER BY version DESC LIMIT 1`,
|
|
423
420
|
[stream]
|
|
424
421
|
);
|
|
425
|
-
version = last.
|
|
422
|
+
let version = last.rows.at(0)?.version ?? -1;
|
|
426
423
|
if (typeof expectedVersion === "number" && version !== expectedVersion)
|
|
427
424
|
throw new ConcurrencyError(
|
|
428
425
|
stream,
|
|
@@ -430,52 +427,69 @@ var PostgresStore = class {
|
|
|
430
427
|
msgs,
|
|
431
428
|
expectedVersion
|
|
432
429
|
);
|
|
433
|
-
const
|
|
430
|
+
const base_version = version;
|
|
431
|
+
const names = [];
|
|
432
|
+
const datas = [];
|
|
433
|
+
const piis = [];
|
|
434
|
+
const versions = [];
|
|
434
435
|
for (const { name, data, pii } of msgs) {
|
|
435
436
|
version++;
|
|
436
|
-
|
|
437
|
+
names.push(name);
|
|
438
|
+
datas.push(JSON.stringify(data));
|
|
439
|
+
piis.push(
|
|
440
|
+
this._resolve_pii_key && pii != null ? JSON.stringify(await encrypt(pii, this._resolve_pii_key)) : pii != null ? JSON.stringify(pii) : null
|
|
441
|
+
);
|
|
442
|
+
versions.push(version);
|
|
443
|
+
}
|
|
444
|
+
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
|
|
445
|
+
FROM l, unnest($1::text[], $2::text[], $3::text[], $4::int[])
|
|
446
|
+
WITH ORDINALITY AS u(name, data, pii, version, ord)
|
|
447
|
+
ORDER BY u.ord`;
|
|
448
|
+
const notify_ctes = this.config.notify ? `,
|
|
449
|
+
payload AS (
|
|
450
|
+
SELECT json_build_object(
|
|
451
|
+
'stream', $5::text,
|
|
452
|
+
'events', json_agg(json_build_object('id', ins.id, 'name', ins.name) ORDER BY ins.version),
|
|
453
|
+
'by', $9::text
|
|
454
|
+
)::text AS p
|
|
455
|
+
FROM ins
|
|
456
|
+
),
|
|
457
|
+
n AS (
|
|
458
|
+
SELECT pg_notify($8, payload.p) FROM payload
|
|
459
|
+
WHERE octet_length(payload.p) < $10
|
|
460
|
+
)` : "";
|
|
461
|
+
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";
|
|
462
|
+
const sql = `WITH l AS (SELECT pg_advisory_xact_lock(hashtext($7))),
|
|
463
|
+
ins AS (
|
|
437
464
|
INSERT INTO ${this._fqt}(name, data, pii, stream, version, meta)
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
stream,
|
|
453
|
-
version - 1,
|
|
454
|
-
msgs,
|
|
455
|
-
expectedVersion ?? -1
|
|
456
|
-
);
|
|
465
|
+
${insert_select}
|
|
466
|
+
RETURNING *
|
|
467
|
+
)${notify_ctes}
|
|
468
|
+
${final_select}`;
|
|
469
|
+
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];
|
|
470
|
+
const params = this.config.notify ? [...base_params, this._channel, this._by, NOTIFY_MAX_PAYLOAD_BYTES] : base_params;
|
|
471
|
+
try {
|
|
472
|
+
const { rows } = await client.query(sql, params);
|
|
473
|
+
if (this._resolve_pii_key) {
|
|
474
|
+
for (const row of rows) {
|
|
475
|
+
if (typeof row.pii === "string") {
|
|
476
|
+
const decrypted = await decrypt(row.pii, this._resolve_pii_key);
|
|
477
|
+
row.pii = decrypted;
|
|
478
|
+
}
|
|
457
479
|
}
|
|
458
|
-
throw error;
|
|
459
480
|
}
|
|
481
|
+
return rows;
|
|
482
|
+
} catch (error) {
|
|
483
|
+
if (error?.code === PG_UNIQUE_VIOLATION) {
|
|
484
|
+
throw new ConcurrencyError(
|
|
485
|
+
stream,
|
|
486
|
+
base_version,
|
|
487
|
+
msgs,
|
|
488
|
+
expectedVersion ?? -1
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
throw error;
|
|
460
492
|
}
|
|
461
|
-
if (this.config.notify) {
|
|
462
|
-
const payload = JSON.stringify({
|
|
463
|
-
stream,
|
|
464
|
-
events: committed.map((c) => ({ id: c.id, name: c.name })),
|
|
465
|
-
by: this._by
|
|
466
|
-
});
|
|
467
|
-
if (Buffer.byteLength(payload, "utf8") < NOTIFY_MAX_PAYLOAD_BYTES)
|
|
468
|
-
await client.query(`SELECT pg_notify($1, $2)`, [
|
|
469
|
-
this._channel,
|
|
470
|
-
payload
|
|
471
|
-
]);
|
|
472
|
-
}
|
|
473
|
-
await client.query("COMMIT");
|
|
474
|
-
return committed;
|
|
475
|
-
} catch (error) {
|
|
476
|
-
await client.query("ROLLBACK").catch(() => {
|
|
477
|
-
});
|
|
478
|
-
throw error;
|
|
479
493
|
} finally {
|
|
480
494
|
client.release();
|
|
481
495
|
}
|
|
@@ -1214,6 +1228,9 @@ var PostgresStore = class {
|
|
|
1214
1228
|
const client = await this._client("truncate");
|
|
1215
1229
|
try {
|
|
1216
1230
|
await client.query("BEGIN");
|
|
1231
|
+
await client.query("SELECT pg_advisory_xact_lock(hashtext($1))", [
|
|
1232
|
+
this._fqt
|
|
1233
|
+
]);
|
|
1217
1234
|
const result = /* @__PURE__ */ new Map();
|
|
1218
1235
|
if (full.length) {
|
|
1219
1236
|
await client.query(`DELETE FROM ${this._fqs} WHERE stream = ANY($1)`, [
|