@rotorsoft/act-sqlite 1.22.7 → 2.0.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/README.md +4 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/sqlite-store.d.ts +2 -2
- package/dist/@types/sqlite-store.d.ts.map +1 -1
- package/dist/index.cjs +62 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +65 -49
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BlockedLease, Committed, EventMeta, Lease,
|
|
1
|
+
import type { Append, BlockedLease, Committed, EventMeta, Lease, 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
|
|
@@ -141,7 +141,7 @@ export declare class SqliteStore implements Store {
|
|
|
141
141
|
private _begin;
|
|
142
142
|
private _tx;
|
|
143
143
|
dispose(): Promise<void>;
|
|
144
|
-
commit<E extends Schemas>(
|
|
144
|
+
commit<E extends Schemas>(appends: readonly Append<E>[], meta: EventMeta): Promise<Committed<E, keyof E>[]>;
|
|
145
145
|
query<E extends Schemas>(callback: (event: Committed<E, keyof E>) => void, query?: Query): Promise<number>;
|
|
146
146
|
subscribe(streams: SubscribeInput[], correlated_at?: number, correlator?: {
|
|
147
147
|
key: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/sqlite-store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,SAAS,EACT,KAAK,
|
|
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
|
@@ -257,8 +257,9 @@ var SqliteStore = class {
|
|
|
257
257
|
// while a write transaction is open on it: a second one fails at once
|
|
258
258
|
// (`TRANSACTION_ACTIVE` in memory, `SQLITE_BUSY` on a file) instead of
|
|
259
259
|
// waiting. So every statement and every transaction takes its turn here.
|
|
260
|
-
// A turn covers only the database work,
|
|
261
|
-
//
|
|
260
|
+
// A turn covers only the database work, so a `query` callback that writes to
|
|
261
|
+
// the store can't wait on itself. `restore` is the exception: its driver runs
|
|
262
|
+
// inside the turn, because the whole restore is one transaction.
|
|
262
263
|
_turn = Promise.resolve();
|
|
263
264
|
_serial(work) {
|
|
264
265
|
const run = this._turn.then(work);
|
|
@@ -292,53 +293,63 @@ var SqliteStore = class {
|
|
|
292
293
|
async dispose() {
|
|
293
294
|
await this._serial(async () => this.client.close());
|
|
294
295
|
}
|
|
295
|
-
// --- commit: transaction
|
|
296
|
-
async commit(
|
|
296
|
+
// --- commit: one transaction across every append ---
|
|
297
|
+
async commit(appends, meta) {
|
|
298
|
+
(0, import_act.check_appends)(appends);
|
|
299
|
+
if (!appends.length) return [];
|
|
297
300
|
return this._serial(async () => {
|
|
298
301
|
const tx = await this._begin("commit");
|
|
299
|
-
let
|
|
302
|
+
let appending = appends[0];
|
|
303
|
+
let head = -1;
|
|
300
304
|
try {
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
305
|
+
const heads = /* @__PURE__ */ new Map();
|
|
306
|
+
for (const { stream, msgs, expectedVersion } of appends) {
|
|
307
|
+
const row = await tx.execute({
|
|
308
|
+
sql: "SELECT COALESCE(MAX(version), -1) as v FROM events WHERE stream = ?",
|
|
309
|
+
args: [stream]
|
|
310
|
+
});
|
|
311
|
+
const current = Number(row.rows[0].v);
|
|
312
|
+
if (typeof expectedVersion === "number" && current !== expectedVersion)
|
|
313
|
+
throw new import_act.ConcurrencyError(
|
|
314
|
+
stream,
|
|
315
|
+
current,
|
|
316
|
+
msgs,
|
|
317
|
+
expectedVersion
|
|
318
|
+
);
|
|
319
|
+
heads.set(stream, current);
|
|
313
320
|
}
|
|
314
321
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
315
322
|
const committed = [];
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
+
for (const append of appends) {
|
|
324
|
+
appending = append;
|
|
325
|
+
head = heads.get(append.stream);
|
|
326
|
+
let version = head + 1;
|
|
327
|
+
for (const { name, data, pii } of append.msgs) {
|
|
328
|
+
const pii_for_write = await this._stringify_pii_for_write(pii);
|
|
329
|
+
const result = await tx.execute({
|
|
330
|
+
sql: "INSERT INTO events (stream, version, name, data, meta, created, pii) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
331
|
+
args: [
|
|
332
|
+
append.stream,
|
|
333
|
+
version,
|
|
334
|
+
name,
|
|
335
|
+
JSON.stringify(data),
|
|
336
|
+
JSON.stringify(meta),
|
|
337
|
+
now,
|
|
338
|
+
pii_for_write
|
|
339
|
+
]
|
|
340
|
+
});
|
|
341
|
+
committed.push({
|
|
342
|
+
id: Number(result.lastInsertRowid),
|
|
343
|
+
stream: append.stream,
|
|
323
344
|
version,
|
|
345
|
+
created: new Date(now),
|
|
324
346
|
name,
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
committed.push({
|
|
332
|
-
id: Number(result.lastInsertRowid),
|
|
333
|
-
stream,
|
|
334
|
-
version,
|
|
335
|
-
created: new Date(now),
|
|
336
|
-
name,
|
|
337
|
-
data,
|
|
338
|
-
meta,
|
|
339
|
-
...pii == null ? {} : { pii }
|
|
340
|
-
});
|
|
341
|
-
version++;
|
|
347
|
+
data,
|
|
348
|
+
meta,
|
|
349
|
+
...pii == null ? {} : { pii }
|
|
350
|
+
});
|
|
351
|
+
version++;
|
|
352
|
+
}
|
|
342
353
|
}
|
|
343
354
|
await tx.commit();
|
|
344
355
|
return committed;
|
|
@@ -347,10 +358,10 @@ var SqliteStore = class {
|
|
|
347
358
|
if (e instanceof import_act.ConcurrencyError) throw e;
|
|
348
359
|
if (is_unique_violation(e))
|
|
349
360
|
throw new import_act.ConcurrencyError(
|
|
350
|
-
stream,
|
|
351
|
-
|
|
352
|
-
msgs,
|
|
353
|
-
expectedVersion ?? -1
|
|
361
|
+
appending.stream,
|
|
362
|
+
head,
|
|
363
|
+
appending.msgs,
|
|
364
|
+
appending.expectedVersion ?? -1
|
|
354
365
|
);
|
|
355
366
|
throw new import_act.StoreError("commit", { cause: e });
|
|
356
367
|
}
|
|
@@ -423,8 +434,8 @@ var SqliteStore = class {
|
|
|
423
434
|
// targeting the same stream. Operator overrides go
|
|
424
435
|
// through `prioritize()` instead.
|
|
425
436
|
async subscribe(streams, correlated_at, correlator) {
|
|
426
|
-
for (const { source } of streams) {
|
|
427
|
-
if (source !== void 0 && !(0, import_act.is_literal_source)(source))
|
|
437
|
+
for (const { stream, source } of streams) {
|
|
438
|
+
if (source !== void 0 && !(0, import_act.is_literal_source)(source, stream))
|
|
428
439
|
streamPatternToGlob(source);
|
|
429
440
|
}
|
|
430
441
|
return this._tx("subscribe", async (tx) => {
|
|
@@ -558,7 +569,7 @@ var SqliteStore = class {
|
|
|
558
569
|
priority: Number(row.priority),
|
|
559
570
|
lane: row.lane
|
|
560
571
|
})).sort((a, b) => b.priority - a.priority || a.at - b.at);
|
|
561
|
-
const fair =
|
|
572
|
+
const fair = (0, import_act.fair_slots)(lagging);
|
|
562
573
|
const priority_slice = candidates.slice(0, lagging - fair);
|
|
563
574
|
const picked = new Set(priority_slice.map((c) => c.stream));
|
|
564
575
|
const fair_slice = [...candidates].sort((a, b) => a.at - b.at).filter((c) => !picked.has(c.stream)).slice(0, fair);
|
|
@@ -765,7 +776,7 @@ var SqliteStore = class {
|
|
|
765
776
|
}
|
|
766
777
|
// --- query_streams: read-only introspection with filters ---
|
|
767
778
|
async query_streams(callback, query) {
|
|
768
|
-
const limit = query?.limit ??
|
|
779
|
+
const limit = query?.limit ?? import_act.DEFAULT_QUERY_STREAMS_LIMIT;
|
|
769
780
|
const { clause, args } = this._filter_clause(query ?? {});
|
|
770
781
|
let sql = `SELECT stream, source, at, retry, blocked, error, leased_by, leased_until, priority, lane, deferred_at, correlated_at FROM streams WHERE ${clause}`;
|
|
771
782
|
if (query?.after !== void 0) {
|
|
@@ -1080,6 +1091,8 @@ var SqliteStore = class {
|
|
|
1080
1091
|
* new sequence is dense from 1. `created` is preserved verbatim
|
|
1081
1092
|
* from the source.
|
|
1082
1093
|
*/
|
|
1094
|
+
// The driver runs inside this store's turn, so it must read from another
|
|
1095
|
+
// store: a call on this one would wait for the restore to end, forever.
|
|
1083
1096
|
async restore(driver) {
|
|
1084
1097
|
return this._serial(async () => {
|
|
1085
1098
|
const tx = await this._begin("restore");
|