@rotorsoft/act-pg 1.13.18 → 1.14.0
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 +4 -1
- package/dist/@types/postgres-store.d.ts.map +1 -1
- package/dist/index.cjs +36 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +36 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -84,6 +84,8 @@ var PostgresStore = class {
|
|
|
84
84
|
config;
|
|
85
85
|
_fqt;
|
|
86
86
|
_fqs;
|
|
87
|
+
/** Correlate checkpoint table (#1484) — one row, id 0. */
|
|
88
|
+
_fqc;
|
|
87
89
|
/**
|
|
88
90
|
* Per-instance writer identifier embedded in every NOTIFY payload. The
|
|
89
91
|
* `notify()` LISTEN handler skips payloads where `by === this._by`,
|
|
@@ -170,6 +172,7 @@ var PostgresStore = class {
|
|
|
170
172
|
this._pool = new Pool({ ...poolConfig, types: scopedTypes });
|
|
171
173
|
this._fqt = `"${this.config.schema}"."${this.config.table}"`;
|
|
172
174
|
this._fqs = `"${this.config.schema}"."${this.config.table}_streams"`;
|
|
175
|
+
this._fqc = `"${this.config.schema}"."${this.config.table}_correlated"`;
|
|
173
176
|
this._channel = notify_channel(this.config.schema, this.config.table);
|
|
174
177
|
if (this.config.notify) {
|
|
175
178
|
this.notify = this._subscribe_notifications.bind(this);
|
|
@@ -306,6 +309,16 @@ var PostgresStore = class {
|
|
|
306
309
|
deferred_at timestamptz
|
|
307
310
|
) TABLESPACE pg_default;`
|
|
308
311
|
);
|
|
312
|
+
await client.query(
|
|
313
|
+
`CREATE TABLE IF NOT EXISTS ${this._fqc} (
|
|
314
|
+
id int PRIMARY KEY DEFAULT 0,
|
|
315
|
+
at bigint NOT NULL DEFAULT -1,
|
|
316
|
+
CONSTRAINT ${this.config.table}_correlated_singleton CHECK (id = 0)
|
|
317
|
+
) TABLESPACE pg_default;`
|
|
318
|
+
);
|
|
319
|
+
await client.query(
|
|
320
|
+
`INSERT INTO ${this._fqc} (id) VALUES (0) ON CONFLICT (id) DO NOTHING;`
|
|
321
|
+
);
|
|
309
322
|
await client.query(
|
|
310
323
|
`ALTER TABLE ${this._fqs}
|
|
311
324
|
ADD COLUMN IF NOT EXISTS priority int NOT NULL DEFAULT 0;`
|
|
@@ -391,7 +404,7 @@ var PostgresStore = class {
|
|
|
391
404
|
WHERE schema_name = '${this.config.schema}'
|
|
392
405
|
) THEN
|
|
393
406
|
EXECUTE 'DROP TABLE IF EXISTS ${this._fqt}';
|
|
394
|
-
EXECUTE 'DROP TABLE IF EXISTS ${this._fqs}';
|
|
407
|
+
EXECUTE 'DROP TABLE IF EXISTS ${this._fqc}, ${this._fqs}';
|
|
395
408
|
IF '${this.config.schema}' <> 'public' THEN
|
|
396
409
|
EXECUTE 'DROP SCHEMA "${this.config.schema}" CASCADE';
|
|
397
410
|
END IF;
|
|
@@ -650,13 +663,16 @@ var PostgresStore = class {
|
|
|
650
663
|
AND (deferred_at IS NULL OR deferred_at <= NOW())
|
|
651
664
|
),
|
|
652
665
|
available AS (
|
|
653
|
-
--
|
|
654
|
-
|
|
655
|
-
|
|
666
|
+
-- Every arm below is watermark-agnostic (#1446): a fresh
|
|
667
|
+
-- subscription sits at -1, and e.id > s.at already answers
|
|
668
|
+
-- correctly there, since the first event has a greater id.
|
|
669
|
+
-- There used to be a fourth arm claiming at < 0 unconditionally,
|
|
670
|
+
-- which handed out an empty lease and a no-op ack for every
|
|
671
|
+
-- subscription with no matching events yet.
|
|
656
672
|
-- Source-less subscription: any non-snapshot event past the
|
|
657
673
|
-- watermark counts, so the id index alone answers it.
|
|
658
674
|
SELECT stream, source, at, priority, lane FROM eligible s
|
|
659
|
-
WHERE s.
|
|
675
|
+
WHERE s.source IS NULL
|
|
660
676
|
AND EXISTS (
|
|
661
677
|
SELECT 1 FROM ${this._fqt} e
|
|
662
678
|
WHERE e.id > s.at AND e.name <> '${SNAP_EVENT}' LIMIT 1
|
|
@@ -665,7 +681,7 @@ var PostgresStore = class {
|
|
|
665
681
|
-- Literal source (no regex metacharacter): exact equality, so
|
|
666
682
|
-- "s1" never claims "s12", and (stream, id) is usable.
|
|
667
683
|
SELECT stream, source, at, priority, lane FROM eligible s
|
|
668
|
-
WHERE s.
|
|
684
|
+
WHERE s.source IS NOT NULL
|
|
669
685
|
AND s.source !~ '${SOURCE_METACHARACTER_CLASS}'
|
|
670
686
|
AND EXISTS (
|
|
671
687
|
SELECT 1 FROM ${this._fqt} e
|
|
@@ -678,7 +694,7 @@ var PostgresStore = class {
|
|
|
678
694
|
-- it anchors. Unavoidably a scan \u2014 but only for the subscriptions
|
|
679
695
|
-- that actually declare a pattern.
|
|
680
696
|
SELECT stream, source, at, priority, lane FROM eligible s
|
|
681
|
-
WHERE s.
|
|
697
|
+
WHERE s.source IS NOT NULL
|
|
682
698
|
AND s.source ~ '${SOURCE_METACHARACTER_CLASS}'
|
|
683
699
|
AND EXISTS (
|
|
684
700
|
SELECT 1 FROM ${this._fqt} e
|
|
@@ -780,7 +796,7 @@ var PostgresStore = class {
|
|
|
780
796
|
* @param streams - Streams to register with optional source.
|
|
781
797
|
* @returns subscribed count and current max watermark.
|
|
782
798
|
*/
|
|
783
|
-
async subscribe(streams) {
|
|
799
|
+
async subscribe(streams, correlated_at) {
|
|
784
800
|
const client = await this._client("subscribe");
|
|
785
801
|
try {
|
|
786
802
|
await client.query("BEGIN");
|
|
@@ -821,11 +837,21 @@ var PostgresStore = class {
|
|
|
821
837
|
[JSON.stringify(streams)]
|
|
822
838
|
);
|
|
823
839
|
}
|
|
840
|
+
if (correlated_at !== void 0)
|
|
841
|
+
await client.query(
|
|
842
|
+
`UPDATE ${this._fqc} SET at = GREATEST(at, $1::bigint) WHERE id = 0`,
|
|
843
|
+
[correlated_at]
|
|
844
|
+
);
|
|
824
845
|
const { rows } = await client.query(
|
|
825
|
-
`SELECT COALESCE(MAX(at), -1)
|
|
846
|
+
`SELECT (SELECT COALESCE(MAX(at), -1) FROM ${this._fqs}) AS max,
|
|
847
|
+
(SELECT at FROM ${this._fqc} WHERE id = 0) AS correlated_at`
|
|
826
848
|
);
|
|
827
849
|
await client.query("COMMIT");
|
|
828
|
-
return {
|
|
850
|
+
return {
|
|
851
|
+
subscribed,
|
|
852
|
+
watermark: rows[0]?.max ?? -1,
|
|
853
|
+
correlated_at: Number(rows[0]?.correlated_at ?? -1)
|
|
854
|
+
};
|
|
829
855
|
} catch (error) {
|
|
830
856
|
await client.query("ROLLBACK").catch(() => {
|
|
831
857
|
});
|