@godspeedai/cognate-projections 0.1.0 → 0.1.2
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 +70 -19
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,21 +1,72 @@
|
|
|
1
1
|
# @godspeedai/cognate-projections
|
|
2
2
|
|
|
3
|
-
Checkpointed, idempotent, rebuildable projections over the durable event log
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
3
|
+
Checkpointed, idempotent, rebuildable projections over the Cognate durable event log. A projection is a deterministic derivation from events; `ProjectionRunner` keeps its derived state and its checkpoint in sync, batch by batch, and never skips a failing event.
|
|
4
|
+
|
|
5
|
+
**When to use this package:** you want a read model or index derived from committed events — counts, listings, per-tenant views — that survives restarts, can be rebuilt from scratch, and stays consistent under concurrent writers. The
|
|
6
|
+
[`@godspeedai/cognate-runtime-bun`](https://www.npmjs.com/package/@godspeedai/cognate-runtime-bun)
|
|
7
|
+
runtime uses this package to keep registered projections current; you can also run a `ProjectionRunner` directly over any
|
|
8
|
+
[`@godspeedai/cognate-events`](https://www.npmjs.com/package/@godspeedai/cognate-events) store.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
bun add @godspeedai/cognate-projections
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires [Bun](https://bun.sh) >= 1.4.0. Needs a store implementing the
|
|
17
|
+
[`@godspeedai/cognate-events`](https://www.npmjs.com/package/@godspeedai/cognate-events) `DurableStore`
|
|
18
|
+
contract — for example [`@godspeedai/cognate-store-sqlite`](https://www.npmjs.com/package/@godspeedai/cognate-store-sqlite)
|
|
19
|
+
or [`@godspeedai/cognate-store-memory`](https://www.npmjs.com/package/@godspeedai/cognate-store-memory).
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { ProjectionRunner } from "@godspeedai/cognate-projections";
|
|
25
|
+
import type { Projection } from "@godspeedai/cognate-projections";
|
|
26
|
+
|
|
27
|
+
const ledger: Projection = {
|
|
28
|
+
name: "ledger",
|
|
29
|
+
version: "1", // bump to force a rebuild rather than reinterpret old state
|
|
30
|
+
apply(event, state) {
|
|
31
|
+
const count = (state.get(`count:${event.eventType}`) as number | undefined) ?? 0;
|
|
32
|
+
const total = (state.get("total") as number | undefined) ?? 0;
|
|
33
|
+
const amount = (event.payload as { amount?: number }).amount ?? 0;
|
|
34
|
+
return [
|
|
35
|
+
{ key: `count:${event.eventType}`, value: count + 1 },
|
|
36
|
+
{ key: "total", value: total + amount },
|
|
37
|
+
];
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const runner = new ProjectionRunner(store, ledger);
|
|
42
|
+
const result = await runner.catchUp();
|
|
43
|
+
// { status: "ok", position: <last applied store position>, applied: 3 }
|
|
44
|
+
|
|
45
|
+
const total = await store.readProjection("ledger", "total");
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`apply` returns the keys it wants to write (`value: null` deletes a key) and may read state written earlier in the same batch through `state.get`.
|
|
49
|
+
|
|
50
|
+
## How the runner behaves
|
|
51
|
+
|
|
52
|
+
- **Checkpointed and idempotent.** Each batch's writes and its checkpoint commit atomically through one `commitProjection` call, guarded by the previous position. Running `catchUp()` twice applies each event exactly once.
|
|
53
|
+
- **Failures stop the world — correctly.** On an apply error the runner commits the successful prefix, records the error at the failing event, and returns `{ status: "error", ... }`. `catchUp()` keeps returning that stored error until you clear it with `retry()`, which reattempts from the checkpoint. The failing event is never skipped.
|
|
54
|
+
- **Version changes require rebuilds.** A stored checkpoint whose version differs from the projection's own yields `{ status: "rebuild_required" }`; `rebuild()` deletes the derived state and replays from position 0.
|
|
55
|
+
- **Live mode.** `start()` follows committed events as they happen; `stop()` unsubscribes after the in-flight run finishes. All runs — live, `catchUp`, `retry`, `rebuild` — are serialized so they never overlap. `waitFor(position)` resolves once the checkpoint reaches a given store position.
|
|
56
|
+
- **Concurrent runners are safe.** Two runners racing on one projection resolve through the store's checkpoint conflict: the loser re-reads the checkpoint and continues from it without double-applying.
|
|
57
|
+
|
|
58
|
+
## Limitations
|
|
59
|
+
|
|
60
|
+
- Projections are derived state: nothing here is authoritative, and `rebuild()` will happily delete and recompute everything. Never store the only copy of data in a projection.
|
|
61
|
+
- `apply` must be deterministic given the event and the state — no clock, randomness, or network. Record nondeterministic inputs as events first.
|
|
62
|
+
|
|
63
|
+
## Related packages
|
|
64
|
+
|
|
65
|
+
- [`@godspeedai/cognate-events`](https://www.npmjs.com/package/@godspeedai/cognate-events) — the event log and checkpoint API this package builds on.
|
|
66
|
+
- [`@godspeedai/cognate-store-sqlite`](https://www.npmjs.com/package/@godspeedai/cognate-store-sqlite) — the durable store to project over.
|
|
67
|
+
- [`@godspeedai/cognate-runtime-bun`](https://www.npmjs.com/package/@godspeedai/cognate-runtime-bun) — keeps registered projections current automatically; public ones are readable through the service and the client.
|
|
68
|
+
- [`@godspeedai/cognate`](https://www.npmjs.com/package/@godspeedai/cognate) — the SDK umbrella.
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godspeedai/cognate-projections",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Checkpointed, idempotent, rebuildable projections over the durable event log (spec §11).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
".": "./src/index.ts"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@godspeedai/cognate-events": "^0.1.
|
|
25
|
+
"@godspeedai/cognate-events": "^0.1.2"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@godspeedai/cognate-store-memory": "workspace:*",
|