@godspeedai/cognate-store-sqlite 0.1.2 → 0.2.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/package.json +2 -2
- package/src/index.ts +33 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godspeedai/cognate-store-sqlite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Authoritative DurableStore on bun:sqlite (spec §13).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,6 +22,6 @@
|
|
|
22
22
|
".": "./src/index.ts"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@godspeedai/cognate-events": "^0.
|
|
25
|
+
"@godspeedai/cognate-events": "^0.2.0"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
OutboxSettlement,
|
|
16
16
|
ProjectionCheckpoint,
|
|
17
17
|
ProjectionCommit,
|
|
18
|
+
ProjectionSnapshot,
|
|
18
19
|
Json,
|
|
19
20
|
} from "@godspeedai/cognate-events";
|
|
20
21
|
import { migrate } from "./schema.ts";
|
|
@@ -313,6 +314,15 @@ export function openSqliteStore(options: SqliteStoreOptions): DurableStore {
|
|
|
313
314
|
db.query("DELETE FROM payloads WHERE event_id = ?").run(eventId);
|
|
314
315
|
db.query("UPDATE events SET erasure_reason = ?, erasure_at = ? WHERE event_id = ?").run(reason, erasedAt, eventId);
|
|
315
316
|
|
|
317
|
+
// Idempotency results are derived copies: a stored result may quote the erased payload (the
|
|
318
|
+
// continuation-transition shape) or fold earlier events of the same stream (the updateState
|
|
319
|
+
// shape). Erasure tombstones such results so replay can never re-disclose the content.
|
|
320
|
+
db.query(
|
|
321
|
+
`UPDATE idempotency SET result = ?
|
|
322
|
+
WHERE EXISTS (SELECT 1 FROM json_each(idempotency.event_ids) je WHERE je.value = ?)
|
|
323
|
+
OR EXISTS (SELECT 1 FROM json_each(idempotency.event_ids) je JOIN events e ON e.event_id = je.value WHERE e.stream_id = ?)`,
|
|
324
|
+
).run(JSON.stringify({ __erased: { reason, erasedAt } }), eventId, original.stream_id);
|
|
325
|
+
|
|
316
326
|
ensureStream("$erasures");
|
|
317
327
|
const sequence = streamVersionRow("$erasures") + 1;
|
|
318
328
|
const tombstone = insertEventRow(
|
|
@@ -472,6 +482,29 @@ export function openSqliteStore(options: SqliteStoreOptions): DurableStore {
|
|
|
472
482
|
return rows.map((row) => ({ key: row.key, value: JSON.parse(row.value) as Json }));
|
|
473
483
|
},
|
|
474
484
|
|
|
485
|
+
async readProjectionSnapshot(name: string): Promise<ProjectionSnapshot> {
|
|
486
|
+
assertOpen();
|
|
487
|
+
// One statement, one snapshot: the checkpoint can never be ahead of the rows it is returned
|
|
488
|
+
// with, even with another process folding concurrently (DEBT-021).
|
|
489
|
+
const row = db
|
|
490
|
+
.query(
|
|
491
|
+
`SELECT
|
|
492
|
+
(SELECT json_object('name', name, 'version', version, 'position', position, 'status', status,
|
|
493
|
+
'error_position', error_position, 'error_event_id', error_event_id, 'error_message', error_message)
|
|
494
|
+
FROM projection_checkpoints WHERE name = ?1) AS checkpoint,
|
|
495
|
+
(SELECT json_group_array(json_object('key', ordered.key, 'value', json(ordered.value)))
|
|
496
|
+
FROM (SELECT key, value FROM projection_state WHERE name = ?1 ORDER BY key) AS ordered) AS rows`,
|
|
497
|
+
)
|
|
498
|
+
.get(name) as Row;
|
|
499
|
+
const checkpoint = row.checkpoint ? JSON.parse(row.checkpoint as string) : undefined;
|
|
500
|
+
return {
|
|
501
|
+
checkpoint: checkpoint
|
|
502
|
+
? { ...checkpoint, error: checkpoint.error_event_id != null ? { position: checkpoint.error_position, eventId: checkpoint.error_event_id, message: checkpoint.error_message } : null }
|
|
503
|
+
: undefined,
|
|
504
|
+
rows: (JSON.parse(row.rows as string) as { key: string; value: Json }[]).map((entry) => ({ key: entry.key, value: entry.value })),
|
|
505
|
+
};
|
|
506
|
+
},
|
|
507
|
+
|
|
475
508
|
async resetProjection(name: string): Promise<void> {
|
|
476
509
|
assertOpen();
|
|
477
510
|
const txn = db.transaction((n: string): void => {
|