@rotorsoft/act-pg 1.18.0 → 1.19.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 +6 -6
- package/dist/@types/postgres-store.d.ts.map +1 -1
- package/dist/index.cjs +75 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +75 -20
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { randomUUID } from "crypto";
|
|
3
3
|
import {
|
|
4
4
|
ConcurrencyError,
|
|
5
|
-
dateReviver,
|
|
6
5
|
log,
|
|
7
6
|
SNAP_EVENT,
|
|
8
7
|
StoreError,
|
|
@@ -19,7 +18,7 @@ var logger = log();
|
|
|
19
18
|
var { Pool, types } = pg;
|
|
20
19
|
var JSONB_OID = types.builtins.JSONB;
|
|
21
20
|
var scopedTypes = {
|
|
22
|
-
getTypeParser: ((oid, format) => oid === JSONB_OID ? (val) => JSON.parse(val
|
|
21
|
+
getTypeParser: ((oid, format) => oid === JSONB_OID ? (val) => JSON.parse(val) : types.getTypeParser(
|
|
23
22
|
oid,
|
|
24
23
|
format
|
|
25
24
|
))
|
|
@@ -311,13 +310,36 @@ var PostgresStore = class {
|
|
|
311
310
|
);
|
|
312
311
|
await client.query(
|
|
313
312
|
`CREATE TABLE IF NOT EXISTS ${this._fqc} (
|
|
314
|
-
|
|
313
|
+
key text PRIMARY KEY,
|
|
315
314
|
at int NOT NULL DEFAULT -1,
|
|
316
|
-
|
|
315
|
+
leased_by text,
|
|
316
|
+
leased_until timestamptz
|
|
317
317
|
) TABLESPACE pg_default;`
|
|
318
318
|
);
|
|
319
|
+
await client.query(`
|
|
320
|
+
DO $$
|
|
321
|
+
BEGIN
|
|
322
|
+
IF EXISTS (
|
|
323
|
+
SELECT 1 FROM information_schema.columns
|
|
324
|
+
WHERE table_schema = '${this.config.schema}'
|
|
325
|
+
AND table_name = '${this.config.table}_correlated'
|
|
326
|
+
AND column_name = 'id'
|
|
327
|
+
) THEN
|
|
328
|
+
ALTER TABLE ${this._fqc} ADD COLUMN IF NOT EXISTS key text;
|
|
329
|
+
ALTER TABLE ${this._fqc} ADD COLUMN IF NOT EXISTS leased_by text;
|
|
330
|
+
ALTER TABLE ${this._fqc} ADD COLUMN IF NOT EXISTS leased_until timestamptz;
|
|
331
|
+
UPDATE ${this._fqc} SET key = '' WHERE key IS NULL;
|
|
332
|
+
ALTER TABLE ${this._fqc}
|
|
333
|
+
DROP CONSTRAINT IF EXISTS ${this.config.table}_correlated_singleton;
|
|
334
|
+
ALTER TABLE ${this._fqc}
|
|
335
|
+
DROP CONSTRAINT IF EXISTS ${this.config.table}_correlated_pkey;
|
|
336
|
+
ALTER TABLE ${this._fqc} DROP COLUMN IF EXISTS id;
|
|
337
|
+
ALTER TABLE ${this._fqc} ALTER COLUMN key SET NOT NULL;
|
|
338
|
+
ALTER TABLE ${this._fqc} ADD PRIMARY KEY (key);
|
|
339
|
+
END IF;
|
|
340
|
+
END $$;`);
|
|
319
341
|
await client.query(
|
|
320
|
-
`INSERT INTO ${this._fqc} (
|
|
342
|
+
`INSERT INTO ${this._fqc} (key) VALUES ('') ON CONFLICT (key) DO NOTHING;`
|
|
321
343
|
);
|
|
322
344
|
await client.query(
|
|
323
345
|
`ALTER TABLE ${this._fqs}
|
|
@@ -512,11 +534,7 @@ var PostgresStore = class {
|
|
|
512
534
|
const result = await this._pool.query(sql, values);
|
|
513
535
|
for (const row of result.rows) {
|
|
514
536
|
if (this._resolve_pii_key && typeof row.pii === "string") {
|
|
515
|
-
const decrypted = await decrypt(
|
|
516
|
-
row.pii,
|
|
517
|
-
this._resolve_pii_key,
|
|
518
|
-
dateReviver
|
|
519
|
-
);
|
|
537
|
+
const decrypted = await decrypt(row.pii, this._resolve_pii_key);
|
|
520
538
|
row.pii = decrypted;
|
|
521
539
|
}
|
|
522
540
|
await Promise.resolve(callback(row));
|
|
@@ -596,11 +614,7 @@ var PostgresStore = class {
|
|
|
596
614
|
if (this._resolve_pii_key) {
|
|
597
615
|
for (const row of rows) {
|
|
598
616
|
if (typeof row.pii === "string") {
|
|
599
|
-
const decrypted = await decrypt(
|
|
600
|
-
row.pii,
|
|
601
|
-
this._resolve_pii_key,
|
|
602
|
-
dateReviver
|
|
603
|
-
);
|
|
617
|
+
const decrypted = await decrypt(row.pii, this._resolve_pii_key);
|
|
604
618
|
row.pii = decrypted;
|
|
605
619
|
}
|
|
606
620
|
}
|
|
@@ -782,7 +796,7 @@ var PostgresStore = class {
|
|
|
782
796
|
* @param streams - Streams to register with optional source.
|
|
783
797
|
* @returns subscribed count and current max watermark.
|
|
784
798
|
*/
|
|
785
|
-
async subscribe(streams, correlated_at) {
|
|
799
|
+
async subscribe(streams, correlated_at, correlator) {
|
|
786
800
|
const client = await this._client("subscribe");
|
|
787
801
|
try {
|
|
788
802
|
await client.query("BEGIN");
|
|
@@ -819,20 +833,61 @@ var PostgresStore = class {
|
|
|
819
833
|
[JSON.stringify(streams)]
|
|
820
834
|
);
|
|
821
835
|
}
|
|
822
|
-
|
|
836
|
+
let correlating;
|
|
837
|
+
if (correlator) {
|
|
838
|
+
const { rowCount } = await client.query(
|
|
839
|
+
`INSERT INTO ${this._fqc} (key, at, leased_by, leased_until)
|
|
840
|
+
SELECT $1,
|
|
841
|
+
GREATEST(COALESCE($2::int, -1),
|
|
842
|
+
COALESCE((SELECT at FROM ${this._fqc} WHERE key = ''), -1)),
|
|
843
|
+
$3,
|
|
844
|
+
-- A non-positive millis releases outright rather than
|
|
845
|
+
-- setting an expiry a hair in the future, which would still
|
|
846
|
+
-- refuse a successor asking in the same instant.
|
|
847
|
+
CASE WHEN $4::int > 0
|
|
848
|
+
THEN now() + ($4::int * interval '1 millisecond')
|
|
849
|
+
ELSE NULL END
|
|
850
|
+
ON CONFLICT (key) DO UPDATE
|
|
851
|
+
SET at = GREATEST(${this._fqc}.at, COALESCE($2::int, -1)),
|
|
852
|
+
leased_by = CASE WHEN $4::int > 0 THEN EXCLUDED.leased_by END,
|
|
853
|
+
leased_until = EXCLUDED.leased_until
|
|
854
|
+
WHERE ${this._fqc}.leased_until IS NULL
|
|
855
|
+
OR ${this._fqc}.leased_until < now()
|
|
856
|
+
OR ${this._fqc}.leased_by = EXCLUDED.leased_by`,
|
|
857
|
+
[
|
|
858
|
+
correlator.key,
|
|
859
|
+
correlated_at ?? null,
|
|
860
|
+
correlator.by,
|
|
861
|
+
correlator.millis
|
|
862
|
+
]
|
|
863
|
+
);
|
|
864
|
+
correlating = (rowCount ?? 0) > 0;
|
|
865
|
+
if (!correlating && correlated_at !== void 0)
|
|
866
|
+
await client.query(
|
|
867
|
+
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE key = $2`,
|
|
868
|
+
[correlated_at, correlator.key]
|
|
869
|
+
);
|
|
870
|
+
if (correlated_at !== void 0)
|
|
871
|
+
await client.query(
|
|
872
|
+
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE key = ''`,
|
|
873
|
+
[correlated_at]
|
|
874
|
+
);
|
|
875
|
+
} else if (correlated_at !== void 0)
|
|
823
876
|
await client.query(
|
|
824
|
-
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE
|
|
877
|
+
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE key = ''`,
|
|
825
878
|
[correlated_at]
|
|
826
879
|
);
|
|
827
880
|
const { rows } = await client.query(
|
|
828
881
|
`SELECT (SELECT COALESCE(MAX(at), -1) FROM ${this._fqs}) AS max,
|
|
829
|
-
(SELECT at FROM ${this._fqc} WHERE
|
|
882
|
+
(SELECT at FROM ${this._fqc} WHERE key = $1) AS correlated_at`,
|
|
883
|
+
[correlator?.key ?? ""]
|
|
830
884
|
);
|
|
831
885
|
await client.query("COMMIT");
|
|
832
886
|
return {
|
|
833
887
|
subscribed,
|
|
834
888
|
watermark: rows[0]?.max ?? -1,
|
|
835
|
-
correlated_at: Number(rows[0]?.correlated_at ?? -1)
|
|
889
|
+
correlated_at: Number(rows[0]?.correlated_at ?? -1),
|
|
890
|
+
...correlating === void 0 ? {} : { correlating }
|
|
836
891
|
};
|
|
837
892
|
} catch (error) {
|
|
838
893
|
await client.query("ROLLBACK").catch(() => {
|