@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BlockedLease, Committed, EventMeta, Lease, Message, NotifyDisposer, Query, QueryStatsOptions, QueryStreams, QueryStreamsResult, Schema, Schemas, Store, StoreNotification, StreamFilter, StreamPosition, StreamStats, SubscribeInput } from "@rotorsoft/act";
|
|
1
|
+
import type { BlockedLease, Committed, EventMeta, Lease, Message, NotifyDisposer, Query, QueryStatsOptions, QueryStreams, QueryStreamsResult, Schema, Schemas, Store, StoreNotification, StreamFilter, StreamPosition, StreamStats, SubscribeInput, SubscribeResult } from "@rotorsoft/act";
|
|
2
2
|
import { type Encryption } from "@rotorsoft/act-crypto";
|
|
3
3
|
import pg from "pg";
|
|
4
4
|
type Config = Readonly<{
|
|
@@ -326,11 +326,11 @@ export declare class PostgresStore implements Store {
|
|
|
326
326
|
* @param streams - Streams to register with optional source.
|
|
327
327
|
* @returns subscribed count and current max watermark.
|
|
328
328
|
*/
|
|
329
|
-
subscribe(streams: SubscribeInput[], correlated_at?: number
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}>;
|
|
329
|
+
subscribe(streams: SubscribeInput[], correlated_at?: number, correlator?: {
|
|
330
|
+
key: string;
|
|
331
|
+
by: string;
|
|
332
|
+
millis: number;
|
|
333
|
+
}): Promise<SubscribeResult>;
|
|
334
334
|
/**
|
|
335
335
|
* Acknowledge and release leases after processing, updating stream positions.
|
|
336
336
|
*
|
|
@@ -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,EACX,cAAc,
|
|
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
|
@@ -43,7 +43,7 @@ var logger = (0, import_act.log)();
|
|
|
43
43
|
var { Pool, types } = import_pg.default;
|
|
44
44
|
var JSONB_OID = types.builtins.JSONB;
|
|
45
45
|
var scopedTypes = {
|
|
46
|
-
getTypeParser: ((oid, format) => oid === JSONB_OID ? (val) => JSON.parse(val
|
|
46
|
+
getTypeParser: ((oid, format) => oid === JSONB_OID ? (val) => JSON.parse(val) : types.getTypeParser(
|
|
47
47
|
oid,
|
|
48
48
|
format
|
|
49
49
|
))
|
|
@@ -335,13 +335,36 @@ var PostgresStore = class {
|
|
|
335
335
|
);
|
|
336
336
|
await client.query(
|
|
337
337
|
`CREATE TABLE IF NOT EXISTS ${this._fqc} (
|
|
338
|
-
|
|
338
|
+
key text PRIMARY KEY,
|
|
339
339
|
at int NOT NULL DEFAULT -1,
|
|
340
|
-
|
|
340
|
+
leased_by text,
|
|
341
|
+
leased_until timestamptz
|
|
341
342
|
) TABLESPACE pg_default;`
|
|
342
343
|
);
|
|
344
|
+
await client.query(`
|
|
345
|
+
DO $$
|
|
346
|
+
BEGIN
|
|
347
|
+
IF EXISTS (
|
|
348
|
+
SELECT 1 FROM information_schema.columns
|
|
349
|
+
WHERE table_schema = '${this.config.schema}'
|
|
350
|
+
AND table_name = '${this.config.table}_correlated'
|
|
351
|
+
AND column_name = 'id'
|
|
352
|
+
) THEN
|
|
353
|
+
ALTER TABLE ${this._fqc} ADD COLUMN IF NOT EXISTS key text;
|
|
354
|
+
ALTER TABLE ${this._fqc} ADD COLUMN IF NOT EXISTS leased_by text;
|
|
355
|
+
ALTER TABLE ${this._fqc} ADD COLUMN IF NOT EXISTS leased_until timestamptz;
|
|
356
|
+
UPDATE ${this._fqc} SET key = '' WHERE key IS NULL;
|
|
357
|
+
ALTER TABLE ${this._fqc}
|
|
358
|
+
DROP CONSTRAINT IF EXISTS ${this.config.table}_correlated_singleton;
|
|
359
|
+
ALTER TABLE ${this._fqc}
|
|
360
|
+
DROP CONSTRAINT IF EXISTS ${this.config.table}_correlated_pkey;
|
|
361
|
+
ALTER TABLE ${this._fqc} DROP COLUMN IF EXISTS id;
|
|
362
|
+
ALTER TABLE ${this._fqc} ALTER COLUMN key SET NOT NULL;
|
|
363
|
+
ALTER TABLE ${this._fqc} ADD PRIMARY KEY (key);
|
|
364
|
+
END IF;
|
|
365
|
+
END $$;`);
|
|
343
366
|
await client.query(
|
|
344
|
-
`INSERT INTO ${this._fqc} (
|
|
367
|
+
`INSERT INTO ${this._fqc} (key) VALUES ('') ON CONFLICT (key) DO NOTHING;`
|
|
345
368
|
);
|
|
346
369
|
await client.query(
|
|
347
370
|
`ALTER TABLE ${this._fqs}
|
|
@@ -536,11 +559,7 @@ var PostgresStore = class {
|
|
|
536
559
|
const result = await this._pool.query(sql, values);
|
|
537
560
|
for (const row of result.rows) {
|
|
538
561
|
if (this._resolve_pii_key && typeof row.pii === "string") {
|
|
539
|
-
const decrypted = await (0, import_act_crypto.decrypt)(
|
|
540
|
-
row.pii,
|
|
541
|
-
this._resolve_pii_key,
|
|
542
|
-
import_act.dateReviver
|
|
543
|
-
);
|
|
562
|
+
const decrypted = await (0, import_act_crypto.decrypt)(row.pii, this._resolve_pii_key);
|
|
544
563
|
row.pii = decrypted;
|
|
545
564
|
}
|
|
546
565
|
await Promise.resolve(callback(row));
|
|
@@ -620,11 +639,7 @@ var PostgresStore = class {
|
|
|
620
639
|
if (this._resolve_pii_key) {
|
|
621
640
|
for (const row of rows) {
|
|
622
641
|
if (typeof row.pii === "string") {
|
|
623
|
-
const decrypted = await (0, import_act_crypto.decrypt)(
|
|
624
|
-
row.pii,
|
|
625
|
-
this._resolve_pii_key,
|
|
626
|
-
import_act.dateReviver
|
|
627
|
-
);
|
|
642
|
+
const decrypted = await (0, import_act_crypto.decrypt)(row.pii, this._resolve_pii_key);
|
|
628
643
|
row.pii = decrypted;
|
|
629
644
|
}
|
|
630
645
|
}
|
|
@@ -806,7 +821,7 @@ var PostgresStore = class {
|
|
|
806
821
|
* @param streams - Streams to register with optional source.
|
|
807
822
|
* @returns subscribed count and current max watermark.
|
|
808
823
|
*/
|
|
809
|
-
async subscribe(streams, correlated_at) {
|
|
824
|
+
async subscribe(streams, correlated_at, correlator) {
|
|
810
825
|
const client = await this._client("subscribe");
|
|
811
826
|
try {
|
|
812
827
|
await client.query("BEGIN");
|
|
@@ -843,20 +858,61 @@ var PostgresStore = class {
|
|
|
843
858
|
[JSON.stringify(streams)]
|
|
844
859
|
);
|
|
845
860
|
}
|
|
846
|
-
|
|
861
|
+
let correlating;
|
|
862
|
+
if (correlator) {
|
|
863
|
+
const { rowCount } = await client.query(
|
|
864
|
+
`INSERT INTO ${this._fqc} (key, at, leased_by, leased_until)
|
|
865
|
+
SELECT $1,
|
|
866
|
+
GREATEST(COALESCE($2::int, -1),
|
|
867
|
+
COALESCE((SELECT at FROM ${this._fqc} WHERE key = ''), -1)),
|
|
868
|
+
$3,
|
|
869
|
+
-- A non-positive millis releases outright rather than
|
|
870
|
+
-- setting an expiry a hair in the future, which would still
|
|
871
|
+
-- refuse a successor asking in the same instant.
|
|
872
|
+
CASE WHEN $4::int > 0
|
|
873
|
+
THEN now() + ($4::int * interval '1 millisecond')
|
|
874
|
+
ELSE NULL END
|
|
875
|
+
ON CONFLICT (key) DO UPDATE
|
|
876
|
+
SET at = GREATEST(${this._fqc}.at, COALESCE($2::int, -1)),
|
|
877
|
+
leased_by = CASE WHEN $4::int > 0 THEN EXCLUDED.leased_by END,
|
|
878
|
+
leased_until = EXCLUDED.leased_until
|
|
879
|
+
WHERE ${this._fqc}.leased_until IS NULL
|
|
880
|
+
OR ${this._fqc}.leased_until < now()
|
|
881
|
+
OR ${this._fqc}.leased_by = EXCLUDED.leased_by`,
|
|
882
|
+
[
|
|
883
|
+
correlator.key,
|
|
884
|
+
correlated_at ?? null,
|
|
885
|
+
correlator.by,
|
|
886
|
+
correlator.millis
|
|
887
|
+
]
|
|
888
|
+
);
|
|
889
|
+
correlating = (rowCount ?? 0) > 0;
|
|
890
|
+
if (!correlating && correlated_at !== void 0)
|
|
891
|
+
await client.query(
|
|
892
|
+
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE key = $2`,
|
|
893
|
+
[correlated_at, correlator.key]
|
|
894
|
+
);
|
|
895
|
+
if (correlated_at !== void 0)
|
|
896
|
+
await client.query(
|
|
897
|
+
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE key = ''`,
|
|
898
|
+
[correlated_at]
|
|
899
|
+
);
|
|
900
|
+
} else if (correlated_at !== void 0)
|
|
847
901
|
await client.query(
|
|
848
|
-
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE
|
|
902
|
+
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::int) WHERE key = ''`,
|
|
849
903
|
[correlated_at]
|
|
850
904
|
);
|
|
851
905
|
const { rows } = await client.query(
|
|
852
906
|
`SELECT (SELECT COALESCE(MAX(at), -1) FROM ${this._fqs}) AS max,
|
|
853
|
-
(SELECT at FROM ${this._fqc} WHERE
|
|
907
|
+
(SELECT at FROM ${this._fqc} WHERE key = $1) AS correlated_at`,
|
|
908
|
+
[correlator?.key ?? ""]
|
|
854
909
|
);
|
|
855
910
|
await client.query("COMMIT");
|
|
856
911
|
return {
|
|
857
912
|
subscribed,
|
|
858
913
|
watermark: rows[0]?.max ?? -1,
|
|
859
|
-
correlated_at: Number(rows[0]?.correlated_at ?? -1)
|
|
914
|
+
correlated_at: Number(rows[0]?.correlated_at ?? -1),
|
|
915
|
+
...correlating === void 0 ? {} : { correlating }
|
|
860
916
|
};
|
|
861
917
|
} catch (error) {
|
|
862
918
|
await client.query("ROLLBACK").catch(() => {
|