effect-cqrs 0.1.0 → 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/README.md +34 -6
- package/dist/Aggregate.d.ts +47 -6
- package/dist/Aggregate.d.ts.map +1 -1
- package/dist/Aggregate.js +45 -1
- package/dist/Aggregate.js.map +1 -1
- package/dist/AggregateService.d.ts +83 -11
- package/dist/AggregateService.d.ts.map +1 -1
- package/dist/AggregateService.js +261 -35
- package/dist/AggregateService.js.map +1 -1
- package/dist/Causation.d.ts +34 -0
- package/dist/Causation.d.ts.map +1 -0
- package/dist/Causation.js +32 -0
- package/dist/Causation.js.map +1 -0
- package/dist/EventStore.d.ts +22 -0
- package/dist/EventStore.d.ts.map +1 -1
- package/dist/EventStore.js +30 -10
- package/dist/EventStore.js.map +1 -1
- package/dist/EventVersions.d.ts +64 -0
- package/dist/EventVersions.d.ts.map +1 -0
- package/dist/EventVersions.js +55 -0
- package/dist/EventVersions.js.map +1 -0
- package/dist/Fixture.d.ts +40 -5
- package/dist/Fixture.d.ts.map +1 -1
- package/dist/Fixture.js +44 -3
- package/dist/Fixture.js.map +1 -1
- package/dist/Metadata.d.ts +42 -0
- package/dist/Metadata.d.ts.map +1 -0
- package/dist/Metadata.js +39 -0
- package/dist/Metadata.js.map +1 -0
- package/dist/PostgresEventStore.d.ts.map +1 -1
- package/dist/PostgresEventStore.js +22 -13
- package/dist/PostgresEventStore.js.map +1 -1
- package/dist/Saga.d.ts +105 -0
- package/dist/Saga.d.ts.map +1 -0
- package/dist/Saga.js +97 -0
- package/dist/Saga.js.map +1 -0
- package/dist/SqliteEventStore.d.ts.map +1 -1
- package/dist/SqliteEventStore.js +32 -13
- package/dist/SqliteEventStore.js.map +1 -1
- package/dist/ViewModel.d.ts.map +1 -1
- package/dist/ViewModel.js +3 -1
- package/dist/ViewModel.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/src/Aggregate.ts +81 -9
- package/src/AggregateService.ts +418 -55
- package/src/Causation.ts +48 -0
- package/src/EventStore.ts +47 -10
- package/src/EventVersions.ts +104 -0
- package/src/Fixture.ts +92 -7
- package/src/Metadata.ts +52 -0
- package/src/PostgresEventStore.ts +24 -13
- package/src/Saga.ts +176 -0
- package/src/SqliteEventStore.ts +43 -13
- package/src/ViewModel.ts +3 -1
- package/src/index.ts +4 -0
package/README.md
CHANGED
|
@@ -89,6 +89,19 @@ event, several, or `[]` to record nothing. It can use services, fail with typed
|
|
|
89
89
|
errors, and may run more than once, so it should only decide. Projections and
|
|
90
90
|
handlers must not mutate the state, which is kept between commands.
|
|
91
91
|
|
|
92
|
+
When an event's schema changes, the stored events keep their old shape. The aggregate
|
|
93
|
+
declares the older shapes and how each becomes the next, and they are upcast as they
|
|
94
|
+
are read:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const Todo = Aggregate.make<TodoState>()({
|
|
98
|
+
// ...
|
|
99
|
+
versions: {
|
|
100
|
+
TodoCreated: EventVersions.from(TodoCreatedV1).next(TodoEvent.cases.TodoCreated, (v1) => ({ ...v1, dueDate: null }))
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
92
105
|
## Run commands
|
|
93
106
|
|
|
94
107
|
```ts
|
|
@@ -116,7 +129,18 @@ state and decides again, up to `maxRetries` times (5 by default), then fails wit
|
|
|
116
129
|
`ConcurrencyConflict`.
|
|
117
130
|
|
|
118
131
|
The service remembers the state of recent aggregates (`stateCacheSize`, 10,000 by
|
|
119
|
-
default), so a command only reads the events it hasn't seen.
|
|
132
|
+
default), so a command only reads the events it hasn't seen. With
|
|
133
|
+
`snapshots: { every, schema, version }` it also saves states through a `KeyValueStore`
|
|
134
|
+
from `effect/persistence`, so a restart replays only what came after the last one.
|
|
135
|
+
|
|
136
|
+
Every event records a `correlationId` and a `causationId`. A command a view model runs
|
|
137
|
+
gets the handled event as its cause, so a chain of reactions can be traced back to the
|
|
138
|
+
request that started it. `Causation.withCausation` sets the ids from outside.
|
|
139
|
+
|
|
140
|
+
Commands can also carry metadata, a JSON object for what the domain doesn't decide on,
|
|
141
|
+
such as the software version or the user who sent them. It is recorded on every event they
|
|
142
|
+
write. `Metadata.layer({ appVersion })` sets it for the whole application and
|
|
143
|
+
`Metadata.withMetadata` adds to it per request.
|
|
120
144
|
|
|
121
145
|
## Project into view models
|
|
122
146
|
|
|
@@ -203,6 +227,10 @@ it.effect("rejects deleting twice", () =>
|
|
|
203
227
|
library works.
|
|
204
228
|
- Yielding the chain gives `{ events, state, version, fixture }` for the last
|
|
205
229
|
command, if you prefer plain assertions.
|
|
230
|
+
- `givenEvents` also takes events in an older schema version, built with
|
|
231
|
+
`Aggregate.historical(Todo, "TodoCreated", 1, { ... })`, to test upcasting.
|
|
232
|
+
- `checkInvariants({ invariant })` runs random command sequences generated from the
|
|
233
|
+
payload schemas and reports the shortest one that breaks the predicate.
|
|
206
234
|
|
|
207
235
|
`it.effect` runs on a test clock stopped at zero, so timestamps need no mocking: an
|
|
208
236
|
event created by `DateTime.now` has `DateTime.makeUnsafe(0)` until
|
|
@@ -292,8 +320,8 @@ store, so `replay` is for rebuilding, not for recovery.
|
|
|
292
320
|
point to wire into your own HTTP or RPC layer.
|
|
293
321
|
- **SQLite, PostgreSQL and memory only.** There are no adapters for MongoDB or MySQL.
|
|
294
322
|
- **No code generator.** There is no equivalent of `cqrs generate`.
|
|
295
|
-
- **
|
|
296
|
-
each stream is replayed the first time it is used
|
|
297
|
-
|
|
298
|
-
- **
|
|
299
|
-
|
|
323
|
+
- **Snapshots are opt-in.** Without `snapshots`, recent state is only kept in memory, so
|
|
324
|
+
after a restart each stream is replayed the first time it is used. A changed state
|
|
325
|
+
needs a new snapshot `version` by hand.
|
|
326
|
+
- **Event upcasts are pure.** Older event shapes declared with `EventVersions` are
|
|
327
|
+
upcast on read, but an upcast can't read a service or fail with its own error.
|
package/dist/Aggregate.d.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* An aggregate is plain data. {@link AggregateService} gives it a store to run
|
|
6
6
|
* against, and `Fixture` runs it in tests.
|
|
7
7
|
*/
|
|
8
|
-
import type
|
|
8
|
+
import { type DateTime, type Effect, Schema } from "effect";
|
|
9
|
+
import * as EventVersions from "./EventVersions.ts";
|
|
9
10
|
export interface Tagged {
|
|
10
11
|
readonly _tag: string;
|
|
11
12
|
}
|
|
@@ -25,6 +26,12 @@ export interface EventMeta {
|
|
|
25
26
|
readonly version: number;
|
|
26
27
|
readonly position: number;
|
|
27
28
|
readonly timestamp: DateTime.Utc;
|
|
29
|
+
/** Shared by everything that follows from one original request, see `Causation`. */
|
|
30
|
+
readonly correlationId: string | null;
|
|
31
|
+
/** What directly caused the command that recorded the event. */
|
|
32
|
+
readonly causationId: string | null;
|
|
33
|
+
/** What the command carried beside its payload, such as the software version, see `Metadata`. */
|
|
34
|
+
readonly metadata: Schema.JsonObject;
|
|
28
35
|
}
|
|
29
36
|
export interface CommandContext {
|
|
30
37
|
readonly aggregateId: string;
|
|
@@ -50,19 +57,29 @@ export interface AnyCommand {
|
|
|
50
57
|
readonly payload: PayloadSchema;
|
|
51
58
|
readonly handler: CommandHandler<any, any, any, any, any>;
|
|
52
59
|
}
|
|
53
|
-
|
|
60
|
+
/**
|
|
61
|
+
* The older shapes of some events, keyed by tag. Each history has to end in the
|
|
62
|
+
* event's current shape.
|
|
63
|
+
*/
|
|
64
|
+
export type Versions<Event extends Tagged> = {
|
|
65
|
+
readonly [Tag in Event["_tag"]]?: EventVersions.Any<Extract<Event, {
|
|
66
|
+
readonly _tag: Tag;
|
|
67
|
+
}>>;
|
|
68
|
+
};
|
|
69
|
+
export interface Aggregate<Name extends string, State, Events extends EventSchema<any>, Commands extends Record<string, AnyCommand>, V extends Versions<Events["Type"]> = {}> {
|
|
54
70
|
readonly name: Name;
|
|
55
71
|
readonly events: Events;
|
|
56
72
|
readonly initial: State;
|
|
57
73
|
readonly projection: Projection<State, Events["Type"]>;
|
|
58
74
|
readonly commands: Commands;
|
|
75
|
+
readonly versions: V;
|
|
59
76
|
/** Returns a new aggregate that also accepts this command. */
|
|
60
77
|
command<const CommandName extends string, Payload extends PayloadSchema, E = never, R = never>(name: CommandName, options: {
|
|
61
78
|
readonly payload: Payload;
|
|
62
79
|
readonly handler: CommandHandler<State, Payload["Type"], Events["Type"], E, R>;
|
|
63
|
-
}): Aggregate<Name, State, Events, Commands & Record<CommandName, Command<Payload, State, Events["Type"], E, R
|
|
80
|
+
}): Aggregate<Name, State, Events, Commands & Record<CommandName, Command<Payload, State, Events["Type"], E, R>>, V>;
|
|
64
81
|
}
|
|
65
|
-
export type Any = Aggregate<string, any, EventSchema<any>, Record<string, AnyCommand
|
|
82
|
+
export type Any = Aggregate<string, any, EventSchema<any>, Record<string, AnyCommand>, any>;
|
|
66
83
|
export type Name<A extends Any> = A["name"];
|
|
67
84
|
export type State<A extends Any> = A["initial"];
|
|
68
85
|
export type Event<A extends Any> = A["events"]["Type"];
|
|
@@ -75,12 +92,36 @@ export type Context<A extends Any> = A["commands"][CommandName<A>] extends Comma
|
|
|
75
92
|
* The state is given explicitly, `Aggregate.make<State>()({ ... })`, so that the
|
|
76
93
|
* projection's return values are checked against it rather than widened.
|
|
77
94
|
*/
|
|
78
|
-
export declare const make: <State>() => <const Name extends string, Events extends EventSchema<any
|
|
95
|
+
export declare const make: <State>() => <const Name extends string, Events extends EventSchema<any>, const V extends Versions<Events["Type"]> = {}>(options: {
|
|
79
96
|
readonly name: Name;
|
|
80
97
|
readonly events: Events;
|
|
81
98
|
readonly initial: State;
|
|
82
99
|
readonly projection: Projection<State, Events["Type"]>;
|
|
83
|
-
|
|
100
|
+
/** Older shapes of events already in the store, see `EventVersions`. */
|
|
101
|
+
readonly versions?: V | undefined;
|
|
102
|
+
}) => Aggregate<Name, State, Events, {}, V>;
|
|
84
103
|
/** Folds one event into the state. */
|
|
85
104
|
export declare const evolve: <A extends Any>(aggregate: A, state: State<A>, event: Event<A>, meta: EventMeta) => State<A>;
|
|
105
|
+
/** The schema version new events with this tag are written with. */
|
|
106
|
+
export declare const schemaVersion: (aggregate: Any, tag: string) => number;
|
|
107
|
+
/**
|
|
108
|
+
* An event as it was stored in the past, in an older version of its schema.
|
|
109
|
+
* Construct one directly to replay JSON taken from a database.
|
|
110
|
+
*/
|
|
111
|
+
export declare class Historical {
|
|
112
|
+
readonly type: string;
|
|
113
|
+
readonly schemaVersion: number;
|
|
114
|
+
readonly payload: Schema.Json;
|
|
115
|
+
constructor(options: {
|
|
116
|
+
readonly type: string;
|
|
117
|
+
readonly schemaVersion: number;
|
|
118
|
+
readonly payload: Schema.Json;
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Encodes an event in an older version of its schema, as code from that time
|
|
123
|
+
* would have stored it. The value is checked against that version, so a test
|
|
124
|
+
* can't seed a shape that never existed.
|
|
125
|
+
*/
|
|
126
|
+
export declare const historical: <A extends Any, const Tag extends keyof A["versions"] & string, const Version extends number>(aggregate: A, tag: Tag, version: Version, value: EventVersions.SchemaAt<NonNullable<A["versions"][Tag]>, Version>["Type"]) => Historical;
|
|
86
127
|
//# sourceMappingURL=Aggregate.d.ts.map
|
package/dist/Aggregate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Aggregate.d.ts","sourceRoot":"","sources":["../src/Aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"Aggregate.d.ts","sourceRoot":"","sources":["../src/Aggregate.ts"],"names":[],"mappings":"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"}
|
package/dist/Aggregate.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The write side of the domain: a schema of events, a projection that folds them
|
|
3
|
+
* into state, and commands that inspect that state and decide on new events.
|
|
4
|
+
*
|
|
5
|
+
* An aggregate is plain data. {@link AggregateService} gives it a store to run
|
|
6
|
+
* against, and `Fixture` runs it in tests.
|
|
7
|
+
*/
|
|
8
|
+
import { Predicate, Schema } from "effect";
|
|
9
|
+
import * as EventVersions from "./EventVersions.js";
|
|
1
10
|
const build = (definition) => ({
|
|
2
11
|
...definition,
|
|
3
12
|
command: (name, options) => build({
|
|
@@ -9,7 +18,42 @@ const build = (definition) => ({
|
|
|
9
18
|
* The state is given explicitly, `Aggregate.make<State>()({ ... })`, so that the
|
|
10
19
|
* projection's return values are checked against it rather than widened.
|
|
11
20
|
*/
|
|
12
|
-
export const make = () => (options) => build({ ...options, commands: {} });
|
|
21
|
+
export const make = () => (options) => build({ ...options, versions: options.versions ?? {}, commands: {} });
|
|
13
22
|
/** Folds one event into the state. */
|
|
14
23
|
export const evolve = (aggregate, state, event, meta) => aggregate.projection[event._tag](state, event, meta);
|
|
24
|
+
/** The schema version new events with this tag are written with. */
|
|
25
|
+
export const schemaVersion = (aggregate, tag) => EventVersions.current(aggregate.versions[tag]);
|
|
26
|
+
/**
|
|
27
|
+
* An event as it was stored in the past, in an older version of its schema.
|
|
28
|
+
* Construct one directly to replay JSON taken from a database.
|
|
29
|
+
*/
|
|
30
|
+
export class Historical {
|
|
31
|
+
type;
|
|
32
|
+
schemaVersion;
|
|
33
|
+
payload;
|
|
34
|
+
constructor(options) {
|
|
35
|
+
this.type = options.type;
|
|
36
|
+
this.schemaVersion = options.schemaVersion;
|
|
37
|
+
this.payload = options.payload;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Encodes an event in an older version of its schema, as code from that time
|
|
42
|
+
* would have stored it. The value is checked against that version, so a test
|
|
43
|
+
* can't seed a shape that never existed.
|
|
44
|
+
*/
|
|
45
|
+
export const historical = (aggregate, tag, version, value) => {
|
|
46
|
+
const versions = aggregate.versions[tag];
|
|
47
|
+
const schema = versions?.schemas[version - 1];
|
|
48
|
+
if (schema === undefined) {
|
|
49
|
+
throw new Error(`${aggregate.name} has no version ${version} of ${tag}`);
|
|
50
|
+
}
|
|
51
|
+
const payload = Schema.encodeSync(Schema.toCodecJson(schema))(value);
|
|
52
|
+
return new Historical({
|
|
53
|
+
type: tag,
|
|
54
|
+
schemaVersion: version,
|
|
55
|
+
// Events were always stored with their tag, whatever the schema of the time said.
|
|
56
|
+
payload: Predicate.isObject(payload) ? { ...payload, _tag: tag } : payload
|
|
57
|
+
});
|
|
58
|
+
};
|
|
15
59
|
//# sourceMappingURL=Aggregate.js.map
|
package/dist/Aggregate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Aggregate.js","sourceRoot":"","sources":["../src/Aggregate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Aggregate.js","sourceRoot":"","sources":["../src/Aggregate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAA8B,SAAS,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACtE,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AA2GnD,MAAM,KAAK,GAAG,CAOZ,UAGC,EAC4C,EAAE,CAAC,CAAC;IACjD,GAAG,UAAU;IACb,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CACzB,KAAK,CAAC;QACJ,GAAG,UAAU;QACb,QAAQ,EAAE,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAS;KAC7D,CAAC;CACL,CAAC,CAAA;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,GAAU,EAAE,CAChC,CAA4G,OAO3G,EAAyC,EAAE,CAC1C,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAK,EAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAA;AAE9E,sCAAsC;AACtC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAgB,SAAY,EAAE,KAAe,EAAE,KAAe,EAAE,IAAe,EAAY,EAAE,CAChH,SAAS,CAAC,UAA8F,CAAC,KAAK,CAAC,IAAI,CAAE,CACpH,KAAK,EACL,KAAK,EACL,IAAI,CACL,CAAA;AAEH,oEAAoE;AACpE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAc,EAAE,GAAW,EAAU,EAAE,CACnE,aAAa,CAAC,OAAO,CAAE,SAAS,CAAC,QAA0D,CAAC,GAAG,CAAC,CAAC,CAAA;AAEnG;;;GAGG;AACH,MAAM,OAAO,UAAU;IACZ,IAAI,CAAQ;IACZ,aAAa,CAAQ;IACrB,OAAO,CAAa;IAC7B,YAAY,OAAiG;QAC3G,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QACxB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAA;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;IAChC,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAKxB,SAAY,EACZ,GAAQ,EACR,OAAgB,EAChB,KAA+E,EACnE,EAAE;IACd,MAAM,QAAQ,GAAI,SAAS,CAAC,QAA0D,CAAC,GAAG,CAAC,CAAA;IAC3F,MAAM,MAAM,GAAG,QAAQ,EAAE,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,CAAA;IAC7C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,CAAC,IAAI,mBAAmB,OAAO,OAAO,GAAG,EAAE,CAAC,CAAA;IAC1E,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAgB,CAAA;IACnF,OAAO,IAAI,UAAU,CAAC;QACpB,IAAI,EAAE,GAAG;QACT,aAAa,EAAE,OAAO;QACtB,kFAAkF;QAClF,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,GAAI,OAAkB,EAAE,IAAI,EAAE,GAAG,EAAiB,CAAC,CAAC,CAAC,OAAO;KACtG,CAAC,CAAA;AACJ,CAAC,CAAA"}
|
|
@@ -2,20 +2,22 @@
|
|
|
2
2
|
* Runs an aggregate against the {@link EventStore}: the `command`, `read-model`
|
|
3
3
|
* and `history` actions of moleculer-cqrs, as a typed service.
|
|
4
4
|
*/
|
|
5
|
-
import { type DateTime, Effect, Schema } from "effect";
|
|
5
|
+
import { Cause, type DateTime, Effect, Schema, type Scope } from "effect";
|
|
6
|
+
import { KeyValueStore } from "effect/persistence";
|
|
6
7
|
import * as Aggregate from "./Aggregate.ts";
|
|
7
8
|
import { ConcurrencyConflict, EventStore, type EventStoreError, type StoredEvent } from "./EventStore.ts";
|
|
9
|
+
import { Metadata } from "./Metadata.ts";
|
|
8
10
|
declare const UnknownCommand_base: Schema.Class<UnknownCommand, Schema.TaggedStruct<"UnknownCommand", {
|
|
9
11
|
readonly aggregateName: Schema.String;
|
|
10
12
|
readonly type: Schema.String;
|
|
11
|
-
}>,
|
|
13
|
+
}>, Cause.YieldableError>;
|
|
12
14
|
export declare class UnknownCommand extends UnknownCommand_base {
|
|
13
15
|
}
|
|
14
16
|
declare const InvalidCommand_base: Schema.Class<InvalidCommand, Schema.TaggedStruct<"InvalidCommand", {
|
|
15
17
|
readonly aggregateName: Schema.String;
|
|
16
18
|
readonly type: Schema.String;
|
|
17
19
|
readonly message: Schema.String;
|
|
18
|
-
}>,
|
|
20
|
+
}>, Cause.YieldableError>;
|
|
19
21
|
export declare class InvalidCommand extends InvalidCommand_base {
|
|
20
22
|
}
|
|
21
23
|
declare const EventDecodeError_base: Schema.Class<EventDecodeError, Schema.TaggedStruct<"EventDecodeError", {
|
|
@@ -23,9 +25,13 @@ declare const EventDecodeError_base: Schema.Class<EventDecodeError, Schema.Tagge
|
|
|
23
25
|
readonly aggregateId: Schema.String;
|
|
24
26
|
readonly version: Schema.Int;
|
|
25
27
|
readonly type: Schema.String;
|
|
28
|
+
readonly schemaVersion: Schema.Int;
|
|
26
29
|
readonly message: Schema.String;
|
|
27
|
-
}>,
|
|
28
|
-
/**
|
|
30
|
+
}>, Cause.YieldableError>;
|
|
31
|
+
/**
|
|
32
|
+
* A stored event doesn't match the schema of its version, or was written in a
|
|
33
|
+
* version the aggregate doesn't declare. Old shapes are declared with `EventVersions`.
|
|
34
|
+
*/
|
|
29
35
|
export declare class EventDecodeError extends EventDecodeError_base {
|
|
30
36
|
}
|
|
31
37
|
export type ReadError = EventStoreError | EventDecodeError;
|
|
@@ -39,11 +45,16 @@ export interface CommandResult<Event> {
|
|
|
39
45
|
/** The store position of the last event, to pass to `ViewModels.caughtUp`. */
|
|
40
46
|
readonly position: number;
|
|
41
47
|
readonly events: ReadonlyArray<Event>;
|
|
48
|
+
/** Recorded on the events, see `Causation`. */
|
|
49
|
+
readonly correlationId: string;
|
|
42
50
|
}
|
|
43
51
|
export interface HistoryEntry<Event> {
|
|
44
52
|
readonly version: number;
|
|
45
53
|
readonly timestamp: DateTime.Utc;
|
|
46
54
|
readonly type: string;
|
|
55
|
+
readonly correlationId: string | null;
|
|
56
|
+
readonly causationId: string | null;
|
|
57
|
+
readonly metadata: Metadata;
|
|
47
58
|
readonly payload?: Event;
|
|
48
59
|
}
|
|
49
60
|
export interface AggregateService<A extends Aggregate.Any> {
|
|
@@ -65,18 +76,79 @@ export interface AggregateService<A extends Aggregate.Any> {
|
|
|
65
76
|
readonly finishTime?: DateTime.Utc | undefined;
|
|
66
77
|
}) => Effect.Effect<ReadonlyArray<HistoryEntry<Aggregate.Event<A>>>, ReadError>;
|
|
67
78
|
}
|
|
68
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Decodes a stored event with the schema of the aggregate it belongs to. An
|
|
81
|
+
* event stored in an older version is upcast to the current one on the way.
|
|
82
|
+
*/
|
|
69
83
|
export declare const makeEventDecoder: <A extends Aggregate.Any>(aggregate: A) => (stored: StoredEvent) => Effect.Effect<Aggregate.Event<A>, EventDecodeError>;
|
|
70
|
-
/** Encodes events into the JSON form the store keeps. */
|
|
84
|
+
/** Encodes events into the JSON form the store keeps, in the current version of their schema. */
|
|
71
85
|
export declare const makeEventEncoder: <A extends Aggregate.Any>(aggregate: A) => (event: Aggregate.Event<A>) => Effect.Effect<{
|
|
72
86
|
type: any;
|
|
73
87
|
payload: Schema.Json;
|
|
88
|
+
schemaVersion: number;
|
|
74
89
|
}, never, never>;
|
|
75
|
-
|
|
90
|
+
/** Saves the state of each aggregate every so often, so a cold start replays only what came after. */
|
|
91
|
+
export interface SnapshotOptions<State> {
|
|
92
|
+
/** How many events to fold after a snapshot before saving the next one. */
|
|
93
|
+
readonly every: number;
|
|
94
|
+
/** How the state is stored. It is encoded as JSON. */
|
|
95
|
+
readonly schema: Schema.Codec<State, any, never, never>;
|
|
96
|
+
/**
|
|
97
|
+
* Part of every key. Change it whenever the state or the projection changes,
|
|
98
|
+
* so that snapshots of the old state are ignored and rebuilt from the log.
|
|
99
|
+
* Defaults to `1`.
|
|
100
|
+
*/
|
|
101
|
+
readonly version?: string | number | undefined;
|
|
102
|
+
}
|
|
103
|
+
export interface Options {
|
|
76
104
|
/** How many times a command is re-decided after losing a race. Defaults to 5. */
|
|
77
|
-
readonly maxRetries?: number;
|
|
105
|
+
readonly maxRetries?: number | undefined;
|
|
78
106
|
/** How many aggregates keep their state in memory between commands. Defaults to 10,000. */
|
|
79
|
-
readonly stateCacheSize?: number;
|
|
80
|
-
}
|
|
107
|
+
readonly stateCacheSize?: number | undefined;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The names of the metrics every aggregate service records through Effect's
|
|
111
|
+
* `Metric` module. Each series carries an `aggregate` attribute with the
|
|
112
|
+
* aggregate's name. Read them with `Metric.snapshot`, or send them on with an
|
|
113
|
+
* exporter such as `OtlpMetrics` from `effect/observability`.
|
|
114
|
+
*/
|
|
115
|
+
export declare const MetricNames: {
|
|
116
|
+
/**
|
|
117
|
+
* Timer: how long a command took, including its wait for an earlier command on
|
|
118
|
+
* the same stream, by `command` and `outcome`. The outcome is `success`, the tag
|
|
119
|
+
* of the error, `defect` or `interrupted`. A payload that doesn't decode, or a
|
|
120
|
+
* type the aggregate doesn't know, fails before this point and isn't recorded.
|
|
121
|
+
*/
|
|
122
|
+
readonly commandDuration: "cqrs_command_duration";
|
|
123
|
+
/**
|
|
124
|
+
* Counter: where loading the current state found a state to start from, by
|
|
125
|
+
* `source`: `memory`, `snapshot`, or `replay` when it starts from the first event.
|
|
126
|
+
*/
|
|
127
|
+
readonly stateLoads: "cqrs_state_loads_total";
|
|
128
|
+
/** Histogram: how many events a load read from the store on top of that state. */
|
|
129
|
+
readonly eventsReplayed: "cqrs_events_replayed";
|
|
130
|
+
/** Gauge: how many states are remembered in memory. */
|
|
131
|
+
readonly stateCacheSize: "cqrs_state_cache_size";
|
|
132
|
+
/** Counter: states dropped from memory to make room for others, see `stateCacheSize`. */
|
|
133
|
+
readonly stateCacheEvictions: "cqrs_state_cache_evictions_total";
|
|
134
|
+
/** Counter: snapshots saved, by `result`: `success` or `failure`. */
|
|
135
|
+
readonly snapshotSaves: "cqrs_snapshot_saves_total";
|
|
136
|
+
/** Counter: snapshots that couldn't be read, so the stream was replayed instead. */
|
|
137
|
+
readonly snapshotReadFailures: "cqrs_snapshot_read_failures_total";
|
|
138
|
+
/** Counter: appends that lost a race with a writer in another process. Each is retried until `maxRetries` runs out. */
|
|
139
|
+
readonly concurrencyConflicts: "cqrs_concurrency_conflicts_total";
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Builds the service for one aggregate. With `snapshots` it saves states through
|
|
143
|
+
* a `KeyValueStore` from `effect/persistence`, which has layers for memory, files,
|
|
144
|
+
* SQL and the browser's `localStorage`. Saves run in the background, and closing
|
|
145
|
+
* the scope waits for the ones still running.
|
|
146
|
+
*/
|
|
147
|
+
export declare const make: {
|
|
148
|
+
<A extends Aggregate.Any>(aggregate: A, options: Options & {
|
|
149
|
+
readonly snapshots: SnapshotOptions<Aggregate.State<A>>;
|
|
150
|
+
}): Effect.Effect<AggregateService<A>, never, EventStore | KeyValueStore.KeyValueStore | Scope.Scope | Aggregate.Context<A>>;
|
|
151
|
+
<A extends Aggregate.Any>(aggregate: A, options?: Options): Effect.Effect<AggregateService<A>, never, EventStore | Aggregate.Context<A>>;
|
|
152
|
+
};
|
|
81
153
|
export {};
|
|
82
154
|
//# sourceMappingURL=AggregateService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AggregateService.d.ts","sourceRoot":"","sources":["../src/AggregateService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"AggregateService.d.ts","sourceRoot":"","sources":["../src/AggregateService.ts"],"names":[],"mappings":"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"}
|