@rotorsoft/act-sqlite 1.17.0 → 1.19.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/sqlite-store.d.ts +6 -6
- package/dist/@types/sqlite-store.d.ts.map +1 -1
- package/dist/index.cjs +83 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +83 -19
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BlockedLease, Committed, EventMeta, Lease, Message, Query, QueryStatsOptions, QueryStreams, QueryStreamsResult, Schemas, Store, StreamFilter, StreamPosition, StreamStats, SubscribeInput } from "@rotorsoft/act";
|
|
1
|
+
import type { BlockedLease, Committed, EventMeta, Lease, Message, Query, QueryStatsOptions, QueryStreams, QueryStreamsResult, Schemas, Store, StreamFilter, StreamPosition, StreamStats, SubscribeInput, SubscribeResult } from "@rotorsoft/act";
|
|
2
2
|
import { type Encryption } from "@rotorsoft/act-crypto";
|
|
3
3
|
/**
|
|
4
4
|
* SQLite store configuration
|
|
@@ -159,11 +159,11 @@ export declare class SqliteStore implements Store {
|
|
|
159
159
|
dispose(): Promise<void>;
|
|
160
160
|
commit<E extends Schemas>(stream: string, msgs: Message<E, keyof E>[], meta: EventMeta, expectedVersion?: number): Promise<Committed<E, keyof E>[]>;
|
|
161
161
|
query<E extends Schemas>(callback: (event: Committed<E, keyof E>) => void, query?: Query): Promise<number>;
|
|
162
|
-
subscribe(streams: SubscribeInput[], correlated_at?: number
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}>;
|
|
162
|
+
subscribe(streams: SubscribeInput[], correlated_at?: number, correlator?: {
|
|
163
|
+
key: string;
|
|
164
|
+
by: string;
|
|
165
|
+
millis: number;
|
|
166
|
+
}): Promise<SubscribeResult>;
|
|
167
167
|
claim(lagging: number, leading: number, by: string, millis: number, lane?: string): Promise<Lease[]>;
|
|
168
168
|
ack(leases: Lease[]): Promise<Lease[]>;
|
|
169
169
|
block(leases: BlockedLease[]): Promise<BlockedLease[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/sqlite-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,KAAK,EACL,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,OAAO,EACP,KAAK,EACL,YAAY,EACZ,cAAc,EACd,WAAW,EACX,cAAc,
|
|
1
|
+
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/sqlite-store.ts"],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -215,14 +215,38 @@ var SqliteStore = class {
|
|
|
215
215
|
SET correlated_at = (SELECT COALESCE(MAX(id), -1) FROM events)
|
|
216
216
|
WHERE correlated_at IS NULL`
|
|
217
217
|
);
|
|
218
|
-
await this.client.execute(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
218
|
+
const correlated_columns = await this.client.execute(
|
|
219
|
+
"PRAGMA table_info(correlated)"
|
|
220
|
+
);
|
|
221
|
+
const legacy = correlated_columns.rows.some((r) => r.name === "id");
|
|
222
|
+
if (legacy) {
|
|
223
|
+
await this.client.execute(`
|
|
224
|
+
CREATE TABLE IF NOT EXISTS correlated_keyed (
|
|
225
|
+
key TEXT PRIMARY KEY,
|
|
226
|
+
at INTEGER NOT NULL DEFAULT -1,
|
|
227
|
+
leased_by TEXT,
|
|
228
|
+
leased_until INTEGER
|
|
229
|
+
)
|
|
230
|
+
`);
|
|
231
|
+
await this.client.execute(
|
|
232
|
+
"INSERT OR IGNORE INTO correlated_keyed (key, at) SELECT '', at FROM correlated WHERE id = 0"
|
|
233
|
+
);
|
|
234
|
+
await this.client.execute("DROP TABLE correlated");
|
|
235
|
+
await this.client.execute(
|
|
236
|
+
"ALTER TABLE correlated_keyed RENAME TO correlated"
|
|
237
|
+
);
|
|
238
|
+
} else {
|
|
239
|
+
await this.client.execute(`
|
|
240
|
+
CREATE TABLE IF NOT EXISTS correlated (
|
|
241
|
+
key TEXT PRIMARY KEY,
|
|
242
|
+
at INTEGER NOT NULL DEFAULT -1,
|
|
243
|
+
leased_by TEXT,
|
|
244
|
+
leased_until INTEGER
|
|
245
|
+
)
|
|
246
|
+
`);
|
|
247
|
+
}
|
|
224
248
|
await this.client.execute(
|
|
225
|
-
"INSERT OR IGNORE INTO correlated (
|
|
249
|
+
"INSERT OR IGNORE INTO correlated (key) VALUES ('')"
|
|
226
250
|
);
|
|
227
251
|
await this.client.execute(
|
|
228
252
|
"CREATE INDEX IF NOT EXISTS idx_streams_claim ON streams(blocked, priority DESC, at)"
|
|
@@ -380,7 +404,7 @@ var SqliteStore = class {
|
|
|
380
404
|
// plus a UPDATE pass to keep the *max* priority across reactions
|
|
381
405
|
// targeting the same stream (ACT-102). Operator overrides go
|
|
382
406
|
// through `prioritize()` instead.
|
|
383
|
-
async subscribe(streams, correlated_at) {
|
|
407
|
+
async subscribe(streams, correlated_at, correlator) {
|
|
384
408
|
for (const { source } of streams) {
|
|
385
409
|
if (source !== void 0 && !(0, import_act.is_literal_source)(source))
|
|
386
410
|
streamPatternToGlob(source);
|
|
@@ -420,19 +444,64 @@ var SqliteStore = class {
|
|
|
420
444
|
const wm = await tx.execute(
|
|
421
445
|
"SELECT COALESCE(MAX(at), -1) as w FROM streams"
|
|
422
446
|
);
|
|
423
|
-
|
|
447
|
+
let correlating;
|
|
448
|
+
if (correlator) {
|
|
449
|
+
const now = Date.now();
|
|
450
|
+
const taken = await tx.execute({
|
|
451
|
+
sql: `INSERT INTO correlated (key, at, leased_by, leased_until)
|
|
452
|
+
SELECT ?,
|
|
453
|
+
MAX(COALESCE(?, -1),
|
|
454
|
+
COALESCE((SELECT at FROM correlated WHERE key = ''), -1)),
|
|
455
|
+
?, ?
|
|
456
|
+
ON CONFLICT (key) DO UPDATE
|
|
457
|
+
SET at = MAX(correlated.at, COALESCE(?, -1)),
|
|
458
|
+
leased_by = excluded.leased_by,
|
|
459
|
+
leased_until = excluded.leased_until
|
|
460
|
+
WHERE correlated.leased_until IS NULL
|
|
461
|
+
OR correlated.leased_until < ?
|
|
462
|
+
OR correlated.leased_by = excluded.leased_by`,
|
|
463
|
+
args: [
|
|
464
|
+
correlator.key,
|
|
465
|
+
correlated_at ?? null,
|
|
466
|
+
correlator.by,
|
|
467
|
+
// `millis <= 0` releases outright rather than setting an expiry a
|
|
468
|
+
// hair in the future, which would still refuse a successor asking
|
|
469
|
+
// in the same instant.
|
|
470
|
+
correlator.millis > 0 ? now + correlator.millis : null,
|
|
471
|
+
correlated_at ?? null,
|
|
472
|
+
now
|
|
473
|
+
]
|
|
474
|
+
});
|
|
475
|
+
correlating = taken.rowsAffected > 0;
|
|
476
|
+
if (!correlating && correlated_at !== void 0)
|
|
477
|
+
await tx.execute({
|
|
478
|
+
sql: "UPDATE correlated SET at = MAX(at, ?) WHERE key = ?",
|
|
479
|
+
args: [correlated_at, correlator.key]
|
|
480
|
+
});
|
|
481
|
+
if (correlated_at !== void 0)
|
|
482
|
+
await tx.execute({
|
|
483
|
+
sql: "UPDATE correlated SET at = MAX(at, ?) WHERE key = ''",
|
|
484
|
+
args: [correlated_at]
|
|
485
|
+
});
|
|
486
|
+
} else if (correlated_at !== void 0)
|
|
424
487
|
await tx.execute({
|
|
425
|
-
sql: "UPDATE correlated SET at = MAX(at, ?) WHERE
|
|
488
|
+
sql: "UPDATE correlated SET at = MAX(at, ?) WHERE key = ''",
|
|
426
489
|
args: [correlated_at]
|
|
427
490
|
});
|
|
428
|
-
const cp = await tx.execute(
|
|
491
|
+
const cp = await tx.execute({
|
|
492
|
+
sql: "SELECT at FROM correlated WHERE key = ?",
|
|
493
|
+
args: [correlator?.key ?? ""]
|
|
494
|
+
});
|
|
429
495
|
await tx.commit();
|
|
430
496
|
return {
|
|
431
497
|
subscribed,
|
|
432
498
|
watermark: Number(wm.rows[0].w),
|
|
433
|
-
// `seed()` always inserts the
|
|
434
|
-
//
|
|
435
|
-
|
|
499
|
+
// `seed()` always inserts the shared row, and a correlator's row is
|
|
500
|
+
// created by the upsert above — or already existed, which is why the
|
|
501
|
+
// lease was refused. Either way this read cannot come back empty, so
|
|
502
|
+
// there is no defensive fallback to leave untested.
|
|
503
|
+
correlated_at: Number(cp.rows[0].at),
|
|
504
|
+
...correlating === void 0 ? {} : { correlating }
|
|
436
505
|
};
|
|
437
506
|
} catch (e) {
|
|
438
507
|
await tx.rollback();
|
|
@@ -1086,11 +1155,6 @@ var SqliteStore = class {
|
|
|
1086
1155
|
sql: "DELETE FROM events WHERE stream = ?",
|
|
1087
1156
|
args: [stream]
|
|
1088
1157
|
});
|
|
1089
|
-
if (snapshot === void 0)
|
|
1090
|
-
await tx.execute({
|
|
1091
|
-
sql: "DELETE FROM streams WHERE stream = ?",
|
|
1092
|
-
args: [stream]
|
|
1093
|
-
});
|
|
1094
1158
|
const event_name = snapshot !== void 0 ? "__snapshot__" : "__tombstone__";
|
|
1095
1159
|
const event_meta = meta ?? { correlation: "", causation: {} };
|
|
1096
1160
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|