@rotorsoft/act-sqlite 1.22.4 → 1.22.5
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 +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/sqlite-store.d.ts +11 -5
- package/dist/@types/sqlite-store.d.ts.map +1 -1
- package/dist/index.cjs +149 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +152 -137
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -102,11 +102,14 @@ export declare function streamPatternToGlob(input: string): string;
|
|
|
102
102
|
* Provides persistent event storage using SQLite via `@libsql/client`.
|
|
103
103
|
* All write operations use transactions for ACID guarantees.
|
|
104
104
|
*
|
|
105
|
-
* SQLite is a single-writer store
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
105
|
+
* SQLite is a single-writer store. The store runs its statements and
|
|
106
|
+
* transactions one at a time on its one connection, so concurrent calls
|
|
107
|
+
* from one process wait their turn. A second connection to the same file
|
|
108
|
+
* (another process, another `SqliteStore`) still fails with `SQLITE_BUSY`,
|
|
109
|
+
* so it does not support competing consumers the way PostgreSQL's
|
|
110
|
+
* `FOR UPDATE SKIP LOCKED` does (the TCK leaves `concurrent_claim` off for
|
|
111
|
+
* this reason). The intended model is one store, and one drain worker, per
|
|
112
|
+
* database file.
|
|
110
113
|
*
|
|
111
114
|
* **`Store.notify` is intentionally not implemented.** The notify hook is
|
|
112
115
|
* a cross-process wake-up signal that lets a horizontally-scaled Act
|
|
@@ -132,6 +135,9 @@ export declare class SqliteStore implements Store {
|
|
|
132
135
|
private _parse_pii_from_read;
|
|
133
136
|
seed(): Promise<void>;
|
|
134
137
|
drop(): Promise<void>;
|
|
138
|
+
private _turn;
|
|
139
|
+
private _serial;
|
|
140
|
+
private _exec;
|
|
135
141
|
private _tx;
|
|
136
142
|
dispose(): Promise<void>;
|
|
137
143
|
commit<E extends Schemas>(stream: string, msgs: Message<E, keyof E>[], meta: EventMeta, expectedVersion?: number): Promise<Committed<E, keyof E>[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../src/sqlite-store.ts"],"names":[],"mappings":"
|
|
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
|
@@ -135,8 +135,8 @@ var SqliteStore = class {
|
|
|
135
135
|
return parsed;
|
|
136
136
|
}
|
|
137
137
|
async seed() {
|
|
138
|
-
await this.
|
|
139
|
-
await this.
|
|
138
|
+
await this._exec("PRAGMA journal_mode=WAL");
|
|
139
|
+
await this._exec(`
|
|
140
140
|
CREATE TABLE IF NOT EXISTS events (
|
|
141
141
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
142
142
|
stream TEXT NOT NULL,
|
|
@@ -150,22 +150,22 @@ var SqliteStore = class {
|
|
|
150
150
|
)
|
|
151
151
|
`);
|
|
152
152
|
try {
|
|
153
|
-
await this.
|
|
153
|
+
await this._exec("ALTER TABLE events ADD COLUMN pii TEXT");
|
|
154
154
|
} catch {
|
|
155
155
|
}
|
|
156
|
-
await this.
|
|
156
|
+
await this._exec(
|
|
157
157
|
"CREATE INDEX IF NOT EXISTS idx_events_stream ON events(stream)"
|
|
158
158
|
);
|
|
159
|
-
await this.
|
|
159
|
+
await this._exec(
|
|
160
160
|
"CREATE INDEX IF NOT EXISTS idx_events_name ON events(name)"
|
|
161
161
|
);
|
|
162
|
-
await this.
|
|
162
|
+
await this._exec(
|
|
163
163
|
"CREATE INDEX IF NOT EXISTS idx_events_snapshot ON events(stream, id) WHERE name = '__snapshot__'"
|
|
164
164
|
);
|
|
165
|
-
await this.
|
|
165
|
+
await this._exec(
|
|
166
166
|
"CREATE INDEX IF NOT EXISTS idx_events_stream_id ON events(stream, id) WHERE name <> '__snapshot__'"
|
|
167
167
|
);
|
|
168
|
-
await this.
|
|
168
|
+
await this._exec(`
|
|
169
169
|
CREATE TABLE IF NOT EXISTS streams (
|
|
170
170
|
stream TEXT PRIMARY KEY,
|
|
171
171
|
source TEXT,
|
|
@@ -182,40 +182,36 @@ var SqliteStore = class {
|
|
|
182
182
|
)
|
|
183
183
|
`);
|
|
184
184
|
try {
|
|
185
|
-
await this.
|
|
185
|
+
await this._exec(
|
|
186
186
|
"ALTER TABLE streams ADD COLUMN priority INTEGER NOT NULL DEFAULT 0"
|
|
187
187
|
);
|
|
188
188
|
} catch {
|
|
189
189
|
}
|
|
190
190
|
try {
|
|
191
|
-
await this.
|
|
192
|
-
"ALTER TABLE streams ADD COLUMN deferred_at TEXT"
|
|
193
|
-
);
|
|
191
|
+
await this._exec("ALTER TABLE streams ADD COLUMN deferred_at TEXT");
|
|
194
192
|
} catch {
|
|
195
193
|
}
|
|
196
194
|
try {
|
|
197
|
-
await this.
|
|
195
|
+
await this._exec(
|
|
198
196
|
"ALTER TABLE streams ADD COLUMN lane TEXT NOT NULL DEFAULT 'default'"
|
|
199
197
|
);
|
|
200
198
|
} catch {
|
|
201
199
|
}
|
|
202
200
|
try {
|
|
203
|
-
await this.
|
|
204
|
-
"ALTER TABLE streams ADD COLUMN correlated_at INTEGER"
|
|
205
|
-
);
|
|
201
|
+
await this._exec("ALTER TABLE streams ADD COLUMN correlated_at INTEGER");
|
|
206
202
|
} catch {
|
|
207
203
|
}
|
|
208
|
-
await this.
|
|
204
|
+
await this._exec(
|
|
209
205
|
`UPDATE streams
|
|
210
206
|
SET correlated_at = (SELECT COALESCE(MAX(id), -1) FROM events)
|
|
211
207
|
WHERE correlated_at IS NULL`
|
|
212
208
|
);
|
|
213
|
-
const correlated_columns = await this.
|
|
209
|
+
const correlated_columns = await this._exec(
|
|
214
210
|
"PRAGMA table_info(correlated)"
|
|
215
211
|
);
|
|
216
212
|
const legacy = correlated_columns.rows.some((r) => r.name === "id");
|
|
217
213
|
if (legacy) {
|
|
218
|
-
await this.
|
|
214
|
+
await this._exec(`
|
|
219
215
|
CREATE TABLE IF NOT EXISTS correlated_keyed (
|
|
220
216
|
key TEXT PRIMARY KEY,
|
|
221
217
|
at INTEGER NOT NULL DEFAULT -1,
|
|
@@ -223,15 +219,13 @@ var SqliteStore = class {
|
|
|
223
219
|
leased_until INTEGER
|
|
224
220
|
)
|
|
225
221
|
`);
|
|
226
|
-
await this.
|
|
222
|
+
await this._exec(
|
|
227
223
|
"INSERT OR IGNORE INTO correlated_keyed (key, at) SELECT '', at FROM correlated WHERE id = 0"
|
|
228
224
|
);
|
|
229
|
-
await this.
|
|
230
|
-
await this.
|
|
231
|
-
"ALTER TABLE correlated_keyed RENAME TO correlated"
|
|
232
|
-
);
|
|
225
|
+
await this._exec("DROP TABLE correlated");
|
|
226
|
+
await this._exec("ALTER TABLE correlated_keyed RENAME TO correlated");
|
|
233
227
|
} else {
|
|
234
|
-
await this.
|
|
228
|
+
await this._exec(`
|
|
235
229
|
CREATE TABLE IF NOT EXISTS correlated (
|
|
236
230
|
key TEXT PRIMARY KEY,
|
|
237
231
|
at INTEGER NOT NULL DEFAULT -1,
|
|
@@ -240,104 +234,121 @@ var SqliteStore = class {
|
|
|
240
234
|
)
|
|
241
235
|
`);
|
|
242
236
|
}
|
|
243
|
-
await this.
|
|
244
|
-
|
|
245
|
-
);
|
|
246
|
-
await this.client.execute(
|
|
237
|
+
await this._exec("INSERT OR IGNORE INTO correlated (key) VALUES ('')");
|
|
238
|
+
await this._exec(
|
|
247
239
|
"CREATE INDEX IF NOT EXISTS idx_streams_claim ON streams(blocked, priority DESC, at)"
|
|
248
240
|
);
|
|
249
|
-
await this.
|
|
241
|
+
await this._exec(
|
|
250
242
|
"CREATE INDEX IF NOT EXISTS idx_streams_correlated_at ON streams(lane, priority DESC, at) WHERE blocked = 0 AND at < correlated_at"
|
|
251
243
|
);
|
|
252
|
-
await this.
|
|
244
|
+
await this._exec(
|
|
253
245
|
"CREATE INDEX IF NOT EXISTS idx_streams_correlated_at_any_lane ON streams(priority DESC, at) WHERE blocked = 0 AND at < correlated_at"
|
|
254
246
|
);
|
|
255
|
-
await this.
|
|
247
|
+
await this._exec(
|
|
256
248
|
"CREATE INDEX IF NOT EXISTS idx_streams_lane ON streams(lane)"
|
|
257
249
|
);
|
|
258
250
|
}
|
|
259
251
|
async drop() {
|
|
260
|
-
await this.
|
|
261
|
-
await this.
|
|
262
|
-
await this.
|
|
252
|
+
await this._exec("DROP TABLE IF EXISTS events");
|
|
253
|
+
await this._exec("DROP TABLE IF EXISTS streams");
|
|
254
|
+
await this._exec("DROP TABLE IF EXISTS correlated");
|
|
263
255
|
}
|
|
264
|
-
// One
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
256
|
+
// One connection serves the whole store, and it can't run a statement
|
|
257
|
+
// while a write transaction is open on it: a second one fails at once
|
|
258
|
+
// (`TRANSACTION_ACTIVE` in memory, `SQLITE_BUSY` on a file) instead of
|
|
259
|
+
// waiting. So every statement and every transaction takes its turn here.
|
|
260
|
+
// A turn covers only the database work, never a caller's callback, so a
|
|
261
|
+
// callback that writes to the store can't wait on itself.
|
|
262
|
+
_turn = Promise.resolve();
|
|
263
|
+
_serial(work) {
|
|
264
|
+
const run = this._turn.then(work);
|
|
265
|
+
this._turn = run.catch(() => void 0);
|
|
266
|
+
return run;
|
|
267
|
+
}
|
|
268
|
+
// One statement, in its turn.
|
|
269
|
+
_exec(stmt) {
|
|
270
|
+
return this._serial(() => this.client.execute(stmt));
|
|
271
|
+
}
|
|
272
|
+
// One write transaction, in its turn: any failure rolls back and throws a {@link StoreError} naming the operation.
|
|
273
|
+
_tx(operation, work) {
|
|
274
|
+
return this._serial(async () => {
|
|
275
|
+
const tx = await this.client.transaction("write");
|
|
276
|
+
try {
|
|
277
|
+
const result = await work(tx);
|
|
278
|
+
await tx.commit();
|
|
279
|
+
return result;
|
|
280
|
+
} catch (e) {
|
|
281
|
+
await tx.rollback();
|
|
282
|
+
throw new import_act.StoreError(operation, { cause: e });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
275
285
|
}
|
|
276
286
|
async dispose() {
|
|
277
|
-
await
|
|
278
|
-
this.client.close();
|
|
287
|
+
await this._serial(async () => this.client.close());
|
|
279
288
|
}
|
|
280
289
|
// --- commit: transaction + optimistic concurrency ---
|
|
281
290
|
async commit(stream, msgs, meta, expectedVersion) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
291
|
+
return this._serial(async () => {
|
|
292
|
+
const tx = await this.client.transaction("write");
|
|
293
|
+
let current_version = -1;
|
|
294
|
+
try {
|
|
295
|
+
const version_row = await tx.execute({
|
|
296
|
+
sql: "SELECT COALESCE(MAX(version), -1) as v FROM events WHERE stream = ?",
|
|
297
|
+
args: [stream]
|
|
298
|
+
});
|
|
299
|
+
current_version = Number(version_row.rows[0].v);
|
|
300
|
+
if (typeof expectedVersion === "number" && current_version !== expectedVersion) {
|
|
301
|
+
throw new import_act.ConcurrencyError(
|
|
302
|
+
stream,
|
|
303
|
+
current_version,
|
|
304
|
+
msgs,
|
|
305
|
+
expectedVersion
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
309
|
+
const committed = [];
|
|
310
|
+
let version = current_version + 1;
|
|
311
|
+
for (const { name, data, pii } of msgs) {
|
|
312
|
+
const pii_for_write = await this._stringify_pii_for_write(pii);
|
|
313
|
+
const result = await tx.execute({
|
|
314
|
+
sql: "INSERT INTO events (stream, version, name, data, meta, created, pii) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
315
|
+
args: [
|
|
316
|
+
stream,
|
|
317
|
+
version,
|
|
318
|
+
name,
|
|
319
|
+
JSON.stringify(data),
|
|
320
|
+
JSON.stringify(meta),
|
|
321
|
+
now,
|
|
322
|
+
pii_for_write
|
|
323
|
+
]
|
|
324
|
+
});
|
|
325
|
+
committed.push({
|
|
326
|
+
id: Number(result.lastInsertRowid),
|
|
306
327
|
stream,
|
|
307
328
|
version,
|
|
329
|
+
created: new Date(now),
|
|
308
330
|
name,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
331
|
+
data,
|
|
332
|
+
meta,
|
|
333
|
+
...pii == null ? {} : { pii }
|
|
334
|
+
});
|
|
335
|
+
version++;
|
|
336
|
+
}
|
|
337
|
+
await tx.commit();
|
|
338
|
+
return committed;
|
|
339
|
+
} catch (e) {
|
|
340
|
+
await tx.rollback();
|
|
341
|
+
if (e instanceof import_act.ConcurrencyError) throw e;
|
|
342
|
+
if (is_unique_violation(e))
|
|
343
|
+
throw new import_act.ConcurrencyError(
|
|
344
|
+
stream,
|
|
345
|
+
current_version,
|
|
346
|
+
msgs,
|
|
347
|
+
expectedVersion ?? -1
|
|
348
|
+
);
|
|
349
|
+
throw new import_act.StoreError("commit", { cause: e });
|
|
326
350
|
}
|
|
327
|
-
|
|
328
|
-
return committed;
|
|
329
|
-
} catch (e) {
|
|
330
|
-
await tx.rollback();
|
|
331
|
-
if (e instanceof import_act.ConcurrencyError) throw e;
|
|
332
|
-
if (is_unique_violation(e))
|
|
333
|
-
throw new import_act.ConcurrencyError(
|
|
334
|
-
stream,
|
|
335
|
-
current_version,
|
|
336
|
-
msgs,
|
|
337
|
-
expectedVersion ?? -1
|
|
338
|
-
);
|
|
339
|
-
throw new import_act.StoreError("commit", { cause: e });
|
|
340
|
-
}
|
|
351
|
+
});
|
|
341
352
|
}
|
|
342
353
|
// --- query: read-only, no transaction needed ---
|
|
343
354
|
async query(callback, query) {
|
|
@@ -387,7 +398,7 @@ var SqliteStore = class {
|
|
|
387
398
|
sql += " LIMIT ?";
|
|
388
399
|
args.push(query.limit);
|
|
389
400
|
}
|
|
390
|
-
const result = await this.
|
|
401
|
+
const result = await this._exec({ sql, args });
|
|
391
402
|
let count = 0;
|
|
392
403
|
for (const row of result.rows) {
|
|
393
404
|
const pii_value = query?.with_pii === false ? null : await this._parse_pii_from_read(row.pii);
|
|
@@ -758,8 +769,8 @@ var SqliteStore = class {
|
|
|
758
769
|
sql += " ORDER BY stream LIMIT ?";
|
|
759
770
|
args.push(limit);
|
|
760
771
|
const [streamsResult, maxResult] = await Promise.all([
|
|
761
|
-
this.
|
|
762
|
-
this.
|
|
772
|
+
this._exec({ sql, args }),
|
|
773
|
+
this._exec("SELECT COALESCE(MAX(id), -1) AS m FROM events")
|
|
763
774
|
]);
|
|
764
775
|
let count = 0;
|
|
765
776
|
for (const row of streamsResult.rows) {
|
|
@@ -891,8 +902,8 @@ var SqliteStore = class {
|
|
|
891
902
|
)` : null;
|
|
892
903
|
const tail_args = limit !== void 0 ? [...args, ...args, limit] : [...args, ...args];
|
|
893
904
|
const [headRes, tailRes] = await Promise.all([
|
|
894
|
-
this.
|
|
895
|
-
tail_sql ? this.
|
|
905
|
+
this._exec({ sql: head_sql, args: head_args }),
|
|
906
|
+
tail_sql ? this._exec({ sql: tail_sql, args: tail_args }) : null
|
|
896
907
|
]);
|
|
897
908
|
const out = /* @__PURE__ */ new Map();
|
|
898
909
|
for (const row of headRes.rows) {
|
|
@@ -954,7 +965,7 @@ var SqliteStore = class {
|
|
|
954
965
|
ORDER BY h.stream
|
|
955
966
|
`;
|
|
956
967
|
const full_args = limit !== void 0 ? [...args, limit] : args;
|
|
957
|
-
const res = await this.
|
|
968
|
+
const res = await this._exec({ sql, args: full_args });
|
|
958
969
|
const out = /* @__PURE__ */ new Map();
|
|
959
970
|
for (const row of res.rows) {
|
|
960
971
|
const r = row;
|
|
@@ -1064,33 +1075,35 @@ var SqliteStore = class {
|
|
|
1064
1075
|
* from the source.
|
|
1065
1076
|
*/
|
|
1066
1077
|
async restore(driver) {
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1078
|
+
return this._serial(async () => {
|
|
1079
|
+
const tx = await this.client.transaction("write");
|
|
1080
|
+
try {
|
|
1081
|
+
await tx.execute("DELETE FROM events");
|
|
1082
|
+
await tx.execute("DELETE FROM streams");
|
|
1083
|
+
await tx.execute("UPDATE correlated SET at = -1");
|
|
1084
|
+
await tx.execute("DELETE FROM sqlite_sequence WHERE name = 'events'");
|
|
1085
|
+
await driver(async (event) => {
|
|
1086
|
+
const pii_for_write = await this._stringify_pii_for_write(event.pii);
|
|
1087
|
+
const ins = await tx.execute({
|
|
1088
|
+
sql: "INSERT INTO events (stream, version, name, data, meta, created, pii) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
1089
|
+
args: [
|
|
1090
|
+
event.stream,
|
|
1091
|
+
event.version,
|
|
1092
|
+
event.name,
|
|
1093
|
+
JSON.stringify(event.data),
|
|
1094
|
+
JSON.stringify(event.meta),
|
|
1095
|
+
event.created.toISOString(),
|
|
1096
|
+
pii_for_write
|
|
1097
|
+
]
|
|
1098
|
+
});
|
|
1099
|
+
return Number(ins.lastInsertRowid);
|
|
1086
1100
|
});
|
|
1087
|
-
|
|
1088
|
-
})
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
}
|
|
1101
|
+
await tx.commit();
|
|
1102
|
+
} catch (error) {
|
|
1103
|
+
await tx.rollback();
|
|
1104
|
+
throw error;
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1094
1107
|
}
|
|
1095
1108
|
/**
|
|
1096
1109
|
* Wipe the sensitive-data payload for every event on the stream — the
|
|
@@ -1110,7 +1123,7 @@ var SqliteStore = class {
|
|
|
1110
1123
|
* @returns Count of events whose `pii` was set to `NULL`
|
|
1111
1124
|
*/
|
|
1112
1125
|
async forget_pii(stream) {
|
|
1113
|
-
const r = await this.
|
|
1126
|
+
const r = await this._exec({
|
|
1114
1127
|
sql: "UPDATE events SET pii = NULL WHERE stream = ? AND pii IS NOT NULL",
|
|
1115
1128
|
args: [stream]
|
|
1116
1129
|
});
|