@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.
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-store.d.ts","sourceRoot":"","sources":["../../src/postgres-store.ts"],"names":[],"mappings":"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"}
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
- FROM ${this._fqt}
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.rowCount ? last.rows[0].version : -1;
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 committed = [];
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
- const sql = `
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
- VALUES($1, $2, $3, $4, $5, $6) RETURNING *`;
465
- const pii_for_write = this._resolve_pii_key && pii != null ? JSON.stringify(await (0, import_act_crypto.encrypt)(pii, this._resolve_pii_key)) : pii ?? null;
466
- const vals = [name, data, pii_for_write, stream, version, meta];
467
- try {
468
- const { rows } = await client.query(sql, vals);
469
- const row = rows.at(0);
470
- if (this._resolve_pii_key && typeof row.pii === "string") {
471
- const decrypted = await (0, import_act_crypto.decrypt)(row.pii, this._resolve_pii_key);
472
- row.pii = decrypted;
473
- }
474
- committed.push(row);
475
- } catch (error) {
476
- if (error?.code === PG_UNIQUE_VIOLATION) {
477
- throw new import_act.ConcurrencyError(
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
- * @param targets - Streams to truncate with optional snapshot state and meta.
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 streams = targets.map((t) => t.stream);
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(`DELETE FROM ${this._fqs} WHERE stream = ANY($1)`, [
1239
- streams
1257
+ await client.query("SELECT pg_advisory_xact_lock(hashtext($1))", [
1258
+ this._fqt
1240
1259
  ]);
1241
1260
  const result = /* @__PURE__ */ new Map();
1242
- for (const { stream, snapshot, meta } of targets) {
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) {