@requence/event-sourcing 1.0.3 → 1.1.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 +1 -1
- package/dist/{chunk-8pchcyvm.js → chunk-04wqxaqs.js} +28 -18
- package/dist/chunk-04wqxaqs.js.map +10 -0
- package/dist/{chunk-3t1vzbab.js → chunk-263c07sn.js} +3 -2
- package/dist/{chunk-3t1vzbab.js.map → chunk-263c07sn.js.map} +3 -3
- package/dist/{chunk-x90g388y.js → chunk-2fe8jjdc.js} +1 -1
- package/dist/{chunk-qdczt68t.js → chunk-391m4mfp.js} +14 -2
- package/dist/chunk-391m4mfp.js.map +10 -0
- package/dist/{chunk-9psg50cb.js → chunk-6yrb30rx.js} +1 -1
- package/dist/{chunk-pmfzjavb.js → chunk-8qn1nqnh.js} +1 -1
- package/dist/{chunk-6n3jfg84.js → chunk-r601d5jm.js} +18 -18
- package/dist/{chunk-6n3jfg84.js.map → chunk-r601d5jm.js.map} +1 -1
- package/dist/{chunk-13wtyj2h.js → chunk-smy8mxvr.js} +37 -23
- package/dist/chunk-smy8mxvr.js.map +10 -0
- package/dist/{chunk-8ev7sb2v.js → chunk-th14wxh8.js} +7 -7
- package/dist/{chunk-8ev7sb2v.js.map → chunk-th14wxh8.js.map} +1 -1
- package/dist/{chunk-zf3x573k.js → chunk-yn2sjcg3.js} +36 -11
- package/dist/chunk-yn2sjcg3.js.map +10 -0
- package/dist/createAggregateRoot.js +9 -9
- package/dist/createCheckpointApi.d.ts +37 -2
- package/dist/createCheckpointApi.d.ts.map +1 -1
- package/dist/createCheckpointApi.js +2 -2
- package/dist/createEventStore.js +11 -11
- package/dist/createProcessManager.d.ts.map +1 -1
- package/dist/createProcessManager.js +4 -4
- package/dist/createProjection.js +5 -5
- package/dist/drizzle/index.d.ts.map +1 -1
- package/dist/drizzle/index.js +34 -28
- package/dist/drizzle/index.js.map +3 -3
- package/dist/drizzle/postgres.d.ts +17 -0
- package/dist/drizzle/postgres.d.ts.map +1 -1
- package/dist/drizzle/postgres.js +1 -1
- package/dist/errors.d.ts +6 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -3
- package/dist/errors.js.map +1 -1
- package/dist/index.js +25 -23
- package/dist/index.js.map +1 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +21 -16
- package/dist/memory/index.js.map +3 -3
- package/dist/refresh.js +2 -2
- package/dist/replay.js +2 -2
- package/dist/snapshotGenerator.js +2 -2
- package/dist/tests/setup.d.ts +1 -0
- package/dist/tests/setup.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/createCheckpointApi.ts +86 -10
- package/src/createEventStore.ts +23 -4
- package/src/createProcessManager.ts +71 -32
- package/src/drizzle/index.ts +19 -4
- package/src/drizzle/postgres.ts +3 -0
- package/src/errors.ts +12 -0
- package/src/memory/index.ts +10 -2
- package/src/tests/eventStore.spec.ts +28 -0
- package/src/tests/processManagerMultiInstance.spec.ts +86 -3
- package/src/tests/setup.ts +12 -2
- package/dist/chunk-13wtyj2h.js.map +0 -10
- package/dist/chunk-8pchcyvm.js.map +0 -10
- package/dist/chunk-qdczt68t.js.map +0 -10
- package/dist/chunk-zf3x573k.js.map +0 -10
- /package/dist/{chunk-x90g388y.js.map → chunk-2fe8jjdc.js.map} +0 -0
- /package/dist/{chunk-9psg50cb.js.map → chunk-6yrb30rx.js.map} +0 -0
- /package/dist/{chunk-pmfzjavb.js.map → chunk-8qn1nqnh.js.map} +0 -0
package/dist/errors.d.ts
CHANGED
|
@@ -6,6 +6,12 @@ export declare class ConcurrencyError extends Error {
|
|
|
6
6
|
id: string;
|
|
7
7
|
}, expectedVersion: number, actualVersion: number);
|
|
8
8
|
}
|
|
9
|
+
export declare class CheckpointConcurrencyError extends Error {
|
|
10
|
+
readonly checkpointType: 'projection' | 'processManager';
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly expectedVersion: number | null;
|
|
13
|
+
constructor(checkpointType: 'projection' | 'processManager', name: string, expectedVersion: number | null);
|
|
14
|
+
}
|
|
9
15
|
export declare class ValidationError extends Error {
|
|
10
16
|
readonly zodError: z.ZodError;
|
|
11
17
|
constructor(message: string, zodError: z.ZodError);
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAA;AAEtB,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAErE,qBAAa,gBAAiB,SAAQ,KAAK;gBAEvC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EACxC,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM;CAMxB;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBADpC,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,CAAC,CAAC,QAAQ;CAIvC;AAED,qBAAa,oBAAqB,SAAQ,eAAe;CAAG;AAE5D,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,qBAAa,YAAY,CAAC,CAAC,SAAS,KAAK,CAAE,SAAQ,KAAK;aAEpC,iBAAiB,EAAE,MAAM;aACzB,WAAW,EAAE,MAAM;aACnB,QAAQ,EAAE,MAAM;aAChB,aAAa,EAAE,CAAC;gBAHhB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,yBAA0B,SAAQ,KAAK;aAGhC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;aAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;gBAFvC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;CAI1C;AAED,qBAAa,mBAAoB,SAAQ,KAAK;CAAG;AAEjD,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAE7C,qBAAa,oCAAoC,CAC/C,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,UAAU,EAAE,MAAM;aAClB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,wCAAwC,CACnD,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,cAAc,EAAE,MAAM;aACtB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAA;AAEtB,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAErE,qBAAa,gBAAiB,SAAQ,KAAK;gBAEvC,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EACxC,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM;CAMxB;AAED,qBAAa,0BAA2B,SAAQ,KAAK;aAEjC,cAAc,EAAE,YAAY,GAAG,gBAAgB;aAC/C,IAAI,EAAE,MAAM;aACZ,eAAe,EAAE,MAAM,GAAG,IAAI;gBAF9B,cAAc,EAAE,YAAY,GAAG,gBAAgB,EAC/C,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,GAAG,IAAI;CAMjD;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBADpC,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,CAAC,CAAC,QAAQ;CAIvC;AAED,qBAAa,oBAAqB,SAAQ,eAAe;CAAG;AAE5D,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,qBAAa,YAAY,CAAC,CAAC,SAAS,KAAK,CAAE,SAAQ,KAAK;aAEpC,iBAAiB,EAAE,MAAM;aACzB,WAAW,EAAE,MAAM;aACnB,QAAQ,EAAE,MAAM;aAChB,aAAa,EAAE,CAAC;gBAHhB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,yBAA0B,SAAQ,KAAK;aAGhC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;aAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;gBAFvC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EAClD,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;CAI1C;AAED,qBAAa,mBAAoB,SAAQ,KAAK;CAAG;AAEjD,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAE7C,qBAAa,oCAAoC,CAC/C,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,UAAU,EAAE,MAAM;aAClB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC;AAED,qBAAa,wCAAwC,CACnD,CAAC,SAAS,KAAK,CACf,SAAQ,KAAK;aAEK,cAAc,EAAE,MAAM;aACtB,YAAY,EAAE,MAAM;aACpB,KAAK,EAAE,eAAe;aACtB,aAAa,EAAE,CAAC;gBAHhB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,CAAC;CAMnC"}
|
package/dist/errors.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CheckpointConcurrencyError,
|
|
2
3
|
CommandError,
|
|
3
4
|
ConcurrencyError,
|
|
4
5
|
EventValidationError,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
RefreshingSkipError,
|
|
10
11
|
ReplaySkipError,
|
|
11
12
|
ValidationError
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-391m4mfp.js";
|
|
13
14
|
export {
|
|
14
15
|
ValidationError,
|
|
15
16
|
ReplaySkipError,
|
|
@@ -20,7 +21,8 @@ export {
|
|
|
20
21
|
InfiniteLoopError,
|
|
21
22
|
EventValidationError,
|
|
22
23
|
ConcurrencyError,
|
|
23
|
-
CommandError
|
|
24
|
+
CommandError,
|
|
25
|
+
CheckpointConcurrencyError
|
|
24
26
|
};
|
|
25
27
|
|
|
26
|
-
//# debugId=
|
|
28
|
+
//# debugId=1EBB5F2728E5435464756E2164756E21
|
package/dist/errors.js.map
CHANGED
package/dist/index.js
CHANGED
|
@@ -4,35 +4,37 @@ import {
|
|
|
4
4
|
} from "./chunk-jd4q8fcf.js";
|
|
5
5
|
import {
|
|
6
6
|
createEventStore
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import {
|
|
9
|
-
getEventListenerInfo,
|
|
10
|
-
isInsideEventListener
|
|
11
|
-
} from "./chunk-24xjphpk.js";
|
|
12
|
-
import"./chunk-ty9bhdvx.js";
|
|
7
|
+
} from "./chunk-04wqxaqs.js";
|
|
13
8
|
import"./chunk-gq80tgvf.js";
|
|
14
9
|
import {
|
|
15
10
|
createAggregateRoot
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import"./chunk-z388cd25.js";
|
|
18
|
-
import {
|
|
19
|
-
getProjectionInfo,
|
|
20
|
-
isInsideProjection
|
|
21
|
-
} from "./chunk-8ev7sb2v.js";
|
|
11
|
+
} from "./chunk-r601d5jm.js";
|
|
22
12
|
import {
|
|
23
13
|
getProcessManagerInfo,
|
|
24
14
|
isInsideProcessManager
|
|
25
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-smy8mxvr.js";
|
|
26
16
|
import"./chunk-6q8mr1sg.js";
|
|
27
|
-
import"./chunk-pmfzjavb.js";
|
|
28
|
-
import {
|
|
29
|
-
skipReplay
|
|
30
|
-
} from "./chunk-x90g388y.js";
|
|
31
|
-
import"./chunk-zf3x573k.js";
|
|
32
17
|
import {
|
|
33
18
|
skipRefreshing
|
|
34
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-6yrb30rx.js";
|
|
20
|
+
import"./chunk-tfy01fah.js";
|
|
35
21
|
import {
|
|
22
|
+
getProjectionInfo,
|
|
23
|
+
isInsideProjection
|
|
24
|
+
} from "./chunk-th14wxh8.js";
|
|
25
|
+
import"./chunk-yn2sjcg3.js";
|
|
26
|
+
import"./chunk-8qn1nqnh.js";
|
|
27
|
+
import"./chunk-ty9bhdvx.js";
|
|
28
|
+
import"./chunk-z388cd25.js";
|
|
29
|
+
import {
|
|
30
|
+
getEventListenerInfo,
|
|
31
|
+
isInsideEventListener
|
|
32
|
+
} from "./chunk-24xjphpk.js";
|
|
33
|
+
import {
|
|
34
|
+
skipReplay
|
|
35
|
+
} from "./chunk-2fe8jjdc.js";
|
|
36
|
+
import {
|
|
37
|
+
CheckpointConcurrencyError,
|
|
36
38
|
CommandError,
|
|
37
39
|
ConcurrencyError,
|
|
38
40
|
EventValidationError,
|
|
@@ -43,8 +45,7 @@ import {
|
|
|
43
45
|
RefreshingSkipError,
|
|
44
46
|
ReplaySkipError,
|
|
45
47
|
ValidationError
|
|
46
|
-
} from "./chunk-
|
|
47
|
-
import"./chunk-tfy01fah.js";
|
|
48
|
+
} from "./chunk-391m4mfp.js";
|
|
48
49
|
export {
|
|
49
50
|
skipReplay,
|
|
50
51
|
skipRefreshing,
|
|
@@ -67,7 +68,8 @@ export {
|
|
|
67
68
|
InfiniteLoopError,
|
|
68
69
|
EventValidationError,
|
|
69
70
|
ConcurrencyError,
|
|
70
|
-
CommandError
|
|
71
|
+
CommandError,
|
|
72
|
+
CheckpointConcurrencyError
|
|
71
73
|
};
|
|
72
74
|
|
|
73
|
-
//# debugId=
|
|
75
|
+
//# debugId=6C4703510F84795D64756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAWjE,OAAO,KAAK,EACV,UAAU,EACV,0CAA0C,EAC1C,cAAc,EACd,UAAU,EACX,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,MAAM,MAAM,gBAAgB,GAAG,CAC7B,MAAM,EAAE,eAAe,EAAE,KACtB,YAAY,CAAC,IAAI,CAAC,CAAA;AAEvB,UAAU,sBAAsB,CAAC,IAAI,SAAS,gBAAgB;IAC5D,cAAc,EAAE,IAAI,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,0CAA0C,CAAC,IAAI,CAAC,CAAC,kBAAkB,CAAC,CAAA;IACvF,kBAAkB,CAAC,EAAE,UAAU,CAAA;IAC/B,uBAAuB,CAAC,EAAE,UAAU,CAAA;IACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACpC;AAED,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EAAE,EACpE,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,QAAQ,GACT,EAAE,sBAAsB,CAAC,IAAI,CAAC,GAAG,UAAU,CAC1C,cAAc,CAAC,IAAI,CAAC,EACpB,IAAI,EACJ,IAAI,CACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/memory/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAWjE,OAAO,KAAK,EACV,UAAU,EACV,0CAA0C,EAC1C,cAAc,EACd,UAAU,EACX,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,MAAM,MAAM,gBAAgB,GAAG,CAC7B,MAAM,EAAE,eAAe,EAAE,KACtB,YAAY,CAAC,IAAI,CAAC,CAAA;AAEvB,UAAU,sBAAsB,CAAC,IAAI,SAAS,gBAAgB;IAC5D,cAAc,EAAE,IAAI,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,0CAA0C,CAAC,IAAI,CAAC,CAAC,kBAAkB,CAAC,CAAA;IACvF,kBAAkB,CAAC,EAAE,UAAU,CAAA;IAC/B,uBAAuB,CAAC,EAAE,UAAU,CAAA;IACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACpC;AAED,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EAAE,EACpE,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,QAAQ,GACT,EAAE,sBAAsB,CAAC,IAAI,CAAC,GAAG,UAAU,CAC1C,cAAc,CAAC,IAAI,CAAC,EACpB,IAAI,EACJ,IAAI,CACL,CA0LA"}
|
package/dist/memory/index.js
CHANGED
|
@@ -4,25 +4,25 @@ import {
|
|
|
4
4
|
} from "../chunk-jd4q8fcf.js";
|
|
5
5
|
import {
|
|
6
6
|
createEventStore
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import"../chunk-24xjphpk.js";
|
|
9
|
-
import"../chunk-ty9bhdvx.js";
|
|
7
|
+
} from "../chunk-04wqxaqs.js";
|
|
10
8
|
import"../chunk-gq80tgvf.js";
|
|
11
9
|
import {
|
|
12
10
|
createAggregateRoot
|
|
13
|
-
} from "../chunk-
|
|
14
|
-
import"../chunk-
|
|
15
|
-
import"../chunk-8ev7sb2v.js";
|
|
16
|
-
import"../chunk-13wtyj2h.js";
|
|
11
|
+
} from "../chunk-r601d5jm.js";
|
|
12
|
+
import"../chunk-smy8mxvr.js";
|
|
17
13
|
import"../chunk-6q8mr1sg.js";
|
|
18
|
-
import"../chunk-
|
|
19
|
-
import"../chunk-
|
|
20
|
-
import"../chunk-
|
|
21
|
-
import"../chunk-
|
|
14
|
+
import"../chunk-6yrb30rx.js";
|
|
15
|
+
import"../chunk-tfy01fah.js";
|
|
16
|
+
import"../chunk-th14wxh8.js";
|
|
17
|
+
import"../chunk-yn2sjcg3.js";
|
|
18
|
+
import"../chunk-8qn1nqnh.js";
|
|
19
|
+
import"../chunk-ty9bhdvx.js";
|
|
20
|
+
import"../chunk-z388cd25.js";
|
|
21
|
+
import"../chunk-24xjphpk.js";
|
|
22
|
+
import"../chunk-2fe8jjdc.js";
|
|
22
23
|
import {
|
|
23
24
|
ConcurrencyError
|
|
24
|
-
} from "../chunk-
|
|
25
|
-
import"../chunk-tfy01fah.js";
|
|
25
|
+
} from "../chunk-391m4mfp.js";
|
|
26
26
|
|
|
27
27
|
// src/memory/index.ts
|
|
28
28
|
function createEventStore2({
|
|
@@ -102,7 +102,7 @@ function createEventStore2({
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
|
-
upsert(checkpoint) {
|
|
105
|
+
upsert(checkpoint, expectedVersion) {
|
|
106
106
|
let persisted;
|
|
107
107
|
for (const c of checkpoints) {
|
|
108
108
|
if (c.type === checkpoint.type && c.name === checkpoint.name) {
|
|
@@ -111,11 +111,16 @@ function createEventStore2({
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
if (persisted) {
|
|
114
|
+
if (expectedVersion === null || persisted.version !== expectedVersion) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
114
117
|
persisted.lastEventPosition = checkpoint.lastEventPosition;
|
|
115
118
|
persisted.metadata = checkpoint.metadata;
|
|
119
|
+
persisted.version = checkpoint.version;
|
|
116
120
|
} else {
|
|
117
|
-
checkpoints.add(checkpoint);
|
|
121
|
+
checkpoints.add({ ...checkpoint });
|
|
118
122
|
}
|
|
123
|
+
return true;
|
|
119
124
|
},
|
|
120
125
|
delete(type, name) {
|
|
121
126
|
for (const checkpoint of checkpoints) {
|
|
@@ -175,4 +180,4 @@ export {
|
|
|
175
180
|
createAggregateRoot
|
|
176
181
|
};
|
|
177
182
|
|
|
178
|
-
//# debugId=
|
|
183
|
+
//# debugId=DB351FF2D489173564756E2164756E21
|
package/dist/memory/index.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/memory/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { AnyAggregateRoot } from '../createAggregateRoot.ts'\nimport type { Checkpoint } from '../createCheckpointApi.ts'\nimport {\n type AggregateRootSnapshot,\n ConcurrencyError,\n type Event,\n type ProjectionSnapshot,\n createEventStore as createBaseEventStore,\n isStreamEvents,\n isStreamId,\n} from '../index.ts'\nimport type {\n EventStore,\n EventStoreParamsWithAggregateRootSnapshots,\n EventsFromRoot,\n OnProgress,\n} from '../createEventStore.ts'\nimport type { BaseOutputEvent, MaybePromise } from '../utilityTypes.js'\n\nexport { createAggregateRoot } from '../index.ts'\n\nexport type OnEventsAppended = (\n events: BaseOutputEvent[],\n) => MaybePromise<void>\n\ninterface MemoryEventStoreParams<Root extends AnyAggregateRoot> {\n aggregateRoots: Root[]\n autoInit?: boolean\n postProcessEvent?: EventStoreParamsWithAggregateRootSnapshots<Root>['postProcessEvent']\n onProjectionReplay?: OnProgress\n onProcessManagerRefresh?: OnProgress\n onEventsAppended?: OnEventsAppended\n}\n\nexport function createEventStore<const Root extends AnyAggregateRoot>({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n onEventsAppended,\n autoInit,\n}: MemoryEventStoreParams<Root>): EventStore<\n EventsFromRoot<Root>,\n Root,\n true\n> {\n const events: Event[] = []\n const checkpoints = new Set<Checkpoint>()\n const aggregateRootSnapshots = new Map<string, AggregateRootSnapshot>()\n const projectionSnapshots = new Set<ProjectionSnapshot>()\n const projectionAppliedCount = new Map<string, number>()\n\n return createBaseEventStore({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n autoInit,\n\n async *loadEvents(select, range) {\n let streamTypes: string[] | null = null\n let streamIds: string[] | null = null\n let eventTypes: string[] | null = null\n\n if (select) {\n const selects = Array.isArray(select) ? select : [select]\n streamTypes = selects.map((select) => select.stream)\n streamIds = selects\n .map((select) => (isStreamId(select) ? select.id : null))\n .filter(Boolean) as string[]\n eventTypes = selects.flatMap((select) =>\n isStreamEvents(select) ? select.events : [],\n )\n }\n\n const filteredEvents = events.filter((event) => {\n if (streamTypes?.length && !streamTypes.includes(event.streamType)) {\n return false\n }\n\n if (streamIds?.length && !streamIds.includes(event.streamId)) {\n return false\n }\n\n if (eventTypes?.length && !eventTypes.includes(event.type)) {\n return false\n }\n\n if (range?.from && event.position < range.from) {\n return false\n }\n\n if (range?.to && event.position > range.to) {\n return false\n }\n\n return true\n })\n\n for (const event of filteredEvents) {\n yield event\n }\n },\n\n appendEvents({ id, stream }, newEvents, expectedVersion) {\n const lastEvent = events.findLast(\n (e) => e.streamId === id && e.streamType === stream,\n )\n\n const currentVersion = lastEvent?.streamVersion ?? 0\n\n if (currentVersion !== expectedVersion) {\n throw new ConcurrencyError(\n { id, stream },\n expectedVersion,\n currentVersion,\n )\n }\n\n const extendedEvents: Event[] = newEvents.map((event, index) => ({\n ...event,\n createdAt: new Date(),\n position: events.length + index,\n streamId: id,\n streamType: stream,\n streamVersion: expectedVersion + index + 1,\n }))\n\n events.push(...extendedEvents)\n onEventsAppended?.(extendedEvents)\n return extendedEvents\n },\n\n checkpoint: {\n get(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n return checkpoint\n }\n }\n },\n upsert(checkpoint) {\n let persisted: Checkpoint | undefined\n for (const c of checkpoints) {\n if (c.type === checkpoint.type && c.name === checkpoint.name) {\n persisted = c\n break\n }\n }\n\n if (persisted) {\n persisted.lastEventPosition = checkpoint.lastEventPosition\n persisted.metadata = checkpoint.metadata\n } else {\n checkpoints.add(checkpoint)\n }\n },\n delete(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n checkpoints.delete(checkpoint)\n }\n }\n },\n },\n\n projectionSnapshot: {\n put(snapshot) {\n projectionSnapshots.add(snapshot)\n },\n get(select) {\n return Array.from(projectionSnapshots)\n .toReversed()\n .find(\n (snapshot) =>\n snapshot.projectionId === select.id &&\n snapshot.projectionType === select.projection,\n )\n },\n delete(target, fromPosition) {\n for (const snapshot of projectionSnapshots) {\n if (target.id && snapshot.projectionId !== target.id) {\n continue\n }\n\n if (snapshot.projectionType !== target.projection) {\n continue\n }\n\n if (fromPosition && snapshot.lastEventPosition < fromPosition) {\n continue\n }\n\n projectionSnapshots.delete(snapshot)\n }\n },\n incrementAppliedCount(select) {\n const key = `${select.projection}-${select.id}`\n const nextCount = (projectionAppliedCount.get(key) ?? 0) + 1\n projectionAppliedCount.set(key, nextCount)\n return nextCount\n },\n },\n\n aggregateRootSnapshot: {\n put(snapshot) {\n aggregateRootSnapshots.set(\n `${snapshot.streamType}:${snapshot.streamId}`,\n snapshot,\n )\n },\n get(select) {\n return aggregateRootSnapshots.get(`${select.stream}:${select.id}`)\n },\n delete(target, fromStreamVersion) {\n const key = `${target.stream}:${target.id}`\n const snapshot = aggregateRootSnapshots.get(key)\n if (snapshot && snapshot.streamVersion > fromStreamVersion) {\n aggregateRootSnapshots.delete(key)\n }\n },\n },\n }) as any\n}\n"
|
|
5
|
+
"import type { AnyAggregateRoot } from '../createAggregateRoot.ts'\nimport type { Checkpoint } from '../createCheckpointApi.ts'\nimport {\n type AggregateRootSnapshot,\n ConcurrencyError,\n type Event,\n type ProjectionSnapshot,\n createEventStore as createBaseEventStore,\n isStreamEvents,\n isStreamId,\n} from '../index.ts'\nimport type {\n EventStore,\n EventStoreParamsWithAggregateRootSnapshots,\n EventsFromRoot,\n OnProgress,\n} from '../createEventStore.ts'\nimport type { BaseOutputEvent, MaybePromise } from '../utilityTypes.js'\n\nexport { createAggregateRoot } from '../index.ts'\n\nexport type OnEventsAppended = (\n events: BaseOutputEvent[],\n) => MaybePromise<void>\n\ninterface MemoryEventStoreParams<Root extends AnyAggregateRoot> {\n aggregateRoots: Root[]\n autoInit?: boolean\n postProcessEvent?: EventStoreParamsWithAggregateRootSnapshots<Root>['postProcessEvent']\n onProjectionReplay?: OnProgress\n onProcessManagerRefresh?: OnProgress\n onEventsAppended?: OnEventsAppended\n}\n\nexport function createEventStore<const Root extends AnyAggregateRoot>({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n onEventsAppended,\n autoInit,\n}: MemoryEventStoreParams<Root>): EventStore<\n EventsFromRoot<Root>,\n Root,\n true\n> {\n const events: Event[] = []\n const checkpoints = new Set<Checkpoint>()\n const aggregateRootSnapshots = new Map<string, AggregateRootSnapshot>()\n const projectionSnapshots = new Set<ProjectionSnapshot>()\n const projectionAppliedCount = new Map<string, number>()\n\n return createBaseEventStore({\n aggregateRoots,\n postProcessEvent,\n onProjectionReplay,\n onProcessManagerRefresh,\n autoInit,\n\n async *loadEvents(select, range) {\n let streamTypes: string[] | null = null\n let streamIds: string[] | null = null\n let eventTypes: string[] | null = null\n\n if (select) {\n const selects = Array.isArray(select) ? select : [select]\n streamTypes = selects.map((select) => select.stream)\n streamIds = selects\n .map((select) => (isStreamId(select) ? select.id : null))\n .filter(Boolean) as string[]\n eventTypes = selects.flatMap((select) =>\n isStreamEvents(select) ? select.events : [],\n )\n }\n\n const filteredEvents = events.filter((event) => {\n if (streamTypes?.length && !streamTypes.includes(event.streamType)) {\n return false\n }\n\n if (streamIds?.length && !streamIds.includes(event.streamId)) {\n return false\n }\n\n if (eventTypes?.length && !eventTypes.includes(event.type)) {\n return false\n }\n\n if (range?.from && event.position < range.from) {\n return false\n }\n\n if (range?.to && event.position > range.to) {\n return false\n }\n\n return true\n })\n\n for (const event of filteredEvents) {\n yield event\n }\n },\n\n appendEvents({ id, stream }, newEvents, expectedVersion) {\n const lastEvent = events.findLast(\n (e) => e.streamId === id && e.streamType === stream,\n )\n\n const currentVersion = lastEvent?.streamVersion ?? 0\n\n if (currentVersion !== expectedVersion) {\n throw new ConcurrencyError(\n { id, stream },\n expectedVersion,\n currentVersion,\n )\n }\n\n const extendedEvents: Event[] = newEvents.map((event, index) => ({\n ...event,\n createdAt: new Date(),\n position: events.length + index,\n streamId: id,\n streamType: stream,\n streamVersion: expectedVersion + index + 1,\n }))\n\n events.push(...extendedEvents)\n onEventsAppended?.(extendedEvents)\n return extendedEvents\n },\n\n checkpoint: {\n get(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n return checkpoint\n }\n }\n },\n upsert(checkpoint, expectedVersion) {\n let persisted: Checkpoint | undefined\n for (const c of checkpoints) {\n if (c.type === checkpoint.type && c.name === checkpoint.name) {\n persisted = c\n break\n }\n }\n\n if (persisted) {\n // Compare-and-swap: reject the write when another writer advanced the\n // checkpoint, or when the caller expected to create a fresh one.\n if (expectedVersion === null || persisted.version !== expectedVersion) {\n return false\n }\n persisted.lastEventPosition = checkpoint.lastEventPosition\n persisted.metadata = checkpoint.metadata\n persisted.version = checkpoint.version\n } else {\n checkpoints.add({ ...checkpoint })\n }\n\n return true\n },\n delete(type, name) {\n for (const checkpoint of checkpoints) {\n if (checkpoint.type === type && checkpoint.name === name) {\n checkpoints.delete(checkpoint)\n }\n }\n },\n },\n\n projectionSnapshot: {\n put(snapshot) {\n projectionSnapshots.add(snapshot)\n },\n get(select) {\n return Array.from(projectionSnapshots)\n .toReversed()\n .find(\n (snapshot) =>\n snapshot.projectionId === select.id &&\n snapshot.projectionType === select.projection,\n )\n },\n delete(target, fromPosition) {\n for (const snapshot of projectionSnapshots) {\n if (target.id && snapshot.projectionId !== target.id) {\n continue\n }\n\n if (snapshot.projectionType !== target.projection) {\n continue\n }\n\n if (fromPosition && snapshot.lastEventPosition < fromPosition) {\n continue\n }\n\n projectionSnapshots.delete(snapshot)\n }\n },\n incrementAppliedCount(select) {\n const key = `${select.projection}-${select.id}`\n const nextCount = (projectionAppliedCount.get(key) ?? 0) + 1\n projectionAppliedCount.set(key, nextCount)\n return nextCount\n },\n },\n\n aggregateRootSnapshot: {\n put(snapshot) {\n aggregateRootSnapshots.set(\n `${snapshot.streamType}:${snapshot.streamId}`,\n snapshot,\n )\n },\n get(select) {\n return aggregateRootSnapshots.get(`${select.stream}:${select.id}`)\n },\n delete(target, fromStreamVersion) {\n const key = `${target.stream}:${target.id}`\n const snapshot = aggregateRootSnapshots.get(key)\n if (snapshot && snapshot.streamVersion > fromStreamVersion) {\n aggregateRootSnapshots.delete(key)\n }\n },\n },\n }) as any\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCO,SAAS,iBAAqD;AAAA,EACnE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,GAKA;AAAA,EACA,MAAM,SAAkB,CAAC;AAAA,EACzB,MAAM,cAAc,IAAI;AAAA,EACxB,MAAM,yBAAyB,IAAI;AAAA,EACnC,MAAM,sBAAsB,IAAI;AAAA,EAChC,MAAM,yBAAyB,IAAI;AAAA,EAEnC,OAAO,iBAAqB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,WAEO,UAAU,CAAC,QAAQ,OAAO;AAAA,MAC/B,IAAI,cAA+B;AAAA,MACnC,IAAI,YAA6B;AAAA,MACjC,IAAI,aAA8B;AAAA,MAElC,IAAI,QAAQ;AAAA,QACV,MAAM,UAAU,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAAA,QACxD,cAAc,QAAQ,IAAI,CAAC,YAAW,QAAO,MAAM;AAAA,QACnD,YAAY,QACT,IAAI,CAAC,YAAY,WAAW,OAAM,IAAI,QAAO,KAAK,IAAK,EACvD,OAAO,OAAO;AAAA,QACjB,aAAa,QAAQ,QAAQ,CAAC,YAC5B,eAAe,OAAM,IAAI,QAAO,SAAS,CAAC,CAC5C;AAAA,MACF;AAAA,MAEA,MAAM,iBAAiB,OAAO,OAAO,CAAC,UAAU;AAAA,QAC9C,IAAI,aAAa,UAAU,CAAC,YAAY,SAAS,MAAM,UAAU,GAAG;AAAA,UAClE,OAAO;AAAA,QACT;AAAA,QAEA,IAAI,WAAW,UAAU,CAAC,UAAU,SAAS,MAAM,QAAQ,GAAG;AAAA,UAC5D,OAAO;AAAA,QACT;AAAA,QAEA,IAAI,YAAY,UAAU,CAAC,WAAW,SAAS,MAAM,IAAI,GAAG;AAAA,UAC1D,OAAO;AAAA,QACT;AAAA,QAEA,IAAI,OAAO,QAAQ,MAAM,WAAW,MAAM,MAAM;AAAA,UAC9C,OAAO;AAAA,QACT;AAAA,QAEA,IAAI,OAAO,MAAM,MAAM,WAAW,MAAM,IAAI;AAAA,UAC1C,OAAO;AAAA,QACT;AAAA,QAEA,OAAO;AAAA,OACR;AAAA,MAED,WAAW,SAAS,gBAAgB;AAAA,QAClC,MAAM;AAAA,MACR;AAAA;AAAA,IAGF,YAAY,GAAG,IAAI,UAAU,WAAW,iBAAiB;AAAA,MACvD,MAAM,YAAY,OAAO,SACvB,CAAC,MAAM,EAAE,aAAa,MAAM,EAAE,eAAe,MAC/C;AAAA,MAEA,MAAM,iBAAiB,WAAW,iBAAiB;AAAA,MAEnD,IAAI,mBAAmB,iBAAiB;AAAA,QACtC,MAAM,IAAI,iBACR,EAAE,IAAI,OAAO,GACb,iBACA,cACF;AAAA,MACF;AAAA,MAEA,MAAM,iBAA0B,UAAU,IAAI,CAAC,OAAO,WAAW;AAAA,WAC5D;AAAA,QACH,WAAW,IAAI;AAAA,QACf,UAAU,OAAO,SAAS;AAAA,QAC1B,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,eAAe,kBAAkB,QAAQ;AAAA,MAC3C,EAAE;AAAA,MAEF,OAAO,KAAK,GAAG,cAAc;AAAA,MAC7B,mBAAmB,cAAc;AAAA,MACjC,OAAO;AAAA;AAAA,IAGT,YAAY;AAAA,MACV,GAAG,CAAC,MAAM,MAAM;AAAA,QACd,WAAW,cAAc,aAAa;AAAA,UACpC,IAAI,WAAW,SAAS,QAAQ,WAAW,SAAS,MAAM;AAAA,YACxD,OAAO;AAAA,UACT;AAAA,QACF;AAAA;AAAA,MAEF,MAAM,CAAC,YAAY;AAAA,
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "DB351FF2D489173564756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/refresh.js
CHANGED
package/dist/replay.js
CHANGED
package/dist/tests/setup.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export declare function setupEventStore<const Root extends AnyAggregateRoot>(agg
|
|
|
45
45
|
type: "projection" | "processManager";
|
|
46
46
|
name: string;
|
|
47
47
|
metadata: Record<string, any>;
|
|
48
|
+
version: number;
|
|
48
49
|
}>;
|
|
49
50
|
pseudoEventStore: Event[];
|
|
50
51
|
pseudoAggregateRootSnapshotStore: Map<string, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/tests/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,OAAO,EAGL,KAAK,KAAK,EAMX,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,wBAAgB,mBAAmB;;;;;;;;;;;;;;;;;iBAehB,MAAM;gBAGP,MAAM;;;;;;;;;;;;;IAIvB;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EACjE,aAAa,EAAE,IAAI,GAAG,IAAI,EAAE,EAC5B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAA;CAAE
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/tests/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,OAAO,EAGL,KAAK,KAAK,EAMX,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,wBAAgB,mBAAmB;;;;;;;;;;;;;;;;;iBAehB,MAAM;gBAGP,MAAM;;;;;;;;;;;;;IAIvB;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,IAAI,SAAS,gBAAgB,EACjE,aAAa,EAAE,IAAI,GAAG,IAAI,EAAE,EAC5B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,KAAK,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmM9E"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import z from 'zod/v4'
|
|
2
2
|
|
|
3
3
|
import type { LoadEvents } from './createEventStore.ts'
|
|
4
|
-
import { ValidationError } from './errors.ts'
|
|
4
|
+
import { CheckpointConcurrencyError, ValidationError } from './errors.ts'
|
|
5
5
|
import type {
|
|
6
6
|
BaseOutputEvent,
|
|
7
7
|
MaybePromise,
|
|
@@ -13,6 +13,7 @@ const checkpointSchema = z.object({
|
|
|
13
13
|
type: z.enum(['projection', 'processManager']),
|
|
14
14
|
name: z.string(),
|
|
15
15
|
metadata: z.record(z.string(), z.any()),
|
|
16
|
+
version: z.int(),
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
export type Checkpoint = z.output<typeof checkpointSchema>
|
|
@@ -26,7 +27,19 @@ export type CheckpointMethods = {
|
|
|
26
27
|
type: 'projection' | 'processManager',
|
|
27
28
|
name: string,
|
|
28
29
|
) => MaybePromise<void>
|
|
29
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Persist a checkpoint using optimistic concurrency control.
|
|
32
|
+
*
|
|
33
|
+
* The write must only succeed if the currently stored version equals
|
|
34
|
+
* `expectedVersion` (or, when `expectedVersion` is `null`, if no checkpoint
|
|
35
|
+
* exists yet). `checkpoint.version` holds the version to store on success.
|
|
36
|
+
* Return `true` when the write was applied and `false` when it was rejected
|
|
37
|
+
* because another writer had advanced the checkpoint in the meantime.
|
|
38
|
+
*/
|
|
39
|
+
upsert: (
|
|
40
|
+
checkpoint: Checkpoint,
|
|
41
|
+
expectedVersion: number | null,
|
|
42
|
+
) => MaybePromise<boolean>
|
|
30
43
|
}
|
|
31
44
|
|
|
32
45
|
export function createCheckpointApi(
|
|
@@ -39,18 +52,81 @@ export function createCheckpointApi(
|
|
|
39
52
|
applyAfter?: (event: BaseOutputEvent) => MaybePromise<void>
|
|
40
53
|
},
|
|
41
54
|
) {
|
|
55
|
+
// In-memory view of the persisted checkpoint version. `null` means "no
|
|
56
|
+
// checkpoint has been written yet". It is kept in sync with the store on
|
|
57
|
+
// every load/upsert so optimistic-concurrency writes can detect when another
|
|
58
|
+
// instance has advanced the same checkpoint.
|
|
59
|
+
let version: number | null = null
|
|
60
|
+
|
|
42
61
|
const api = {
|
|
43
62
|
relatedStreamEvents: params.relatedStreamEvents,
|
|
44
63
|
async clear() {
|
|
45
64
|
await params.delete(params.type, params.name)
|
|
65
|
+
version = null
|
|
46
66
|
},
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Load the persisted checkpoint and sync the local version. Returns the
|
|
69
|
+
* raw checkpoint (or `null`), so callers can rehydrate their own state
|
|
70
|
+
* (e.g. a process manager reloading its folded state) from it.
|
|
71
|
+
*/
|
|
72
|
+
async load() {
|
|
73
|
+
const checkpoint = await params.get(params.type, params.name)
|
|
74
|
+
version = checkpoint?.version ?? null
|
|
75
|
+
return checkpoint ?? null
|
|
76
|
+
},
|
|
77
|
+
/**
|
|
78
|
+
* Persist the checkpoint position (and optional metadata) for the given
|
|
79
|
+
* event.
|
|
80
|
+
*
|
|
81
|
+
* - `'cas'` (compare-and-swap): the write must land on top of the exact
|
|
82
|
+
* version we last observed. If another writer advanced the checkpoint,
|
|
83
|
+
* the local version is refreshed and a {@link CheckpointConcurrencyError}
|
|
84
|
+
* is thrown so the caller can re-fold its state and retry. Used for
|
|
85
|
+
* process managers that fold state into the checkpoint.
|
|
86
|
+
* - `'monotonic'` (default): retries on conflict, skipping the write once
|
|
87
|
+
* the stored position already covers this event. Safe for cursors with
|
|
88
|
+
* no derived state (projections, stateless/after-effect writes).
|
|
89
|
+
*/
|
|
90
|
+
async upsert(
|
|
91
|
+
event: BaseOutputEvent,
|
|
92
|
+
metadata: Record<string, any> = {},
|
|
93
|
+
mode: 'cas' | 'monotonic' = 'monotonic',
|
|
94
|
+
) {
|
|
95
|
+
while (true) {
|
|
96
|
+
const expectedVersion = version
|
|
97
|
+
const nextVersion = (expectedVersion ?? -1) + 1
|
|
98
|
+
const committed = await params.upsert(
|
|
99
|
+
{
|
|
100
|
+
lastEventPosition: event.position,
|
|
101
|
+
type: params.type,
|
|
102
|
+
name: params.name,
|
|
103
|
+
metadata,
|
|
104
|
+
version: nextVersion,
|
|
105
|
+
},
|
|
106
|
+
expectedVersion,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if (committed) {
|
|
110
|
+
version = nextVersion
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Another writer advanced this checkpoint. Refresh our view of it.
|
|
115
|
+
const current = await api.load()
|
|
116
|
+
|
|
117
|
+
if (mode === 'cas') {
|
|
118
|
+
throw new CheckpointConcurrencyError(
|
|
119
|
+
params.type,
|
|
120
|
+
params.name,
|
|
121
|
+
expectedVersion,
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// monotonic: the stored cursor already covers this event, nothing to do.
|
|
126
|
+
if (current && current.lastEventPosition >= event.position) {
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
}
|
|
54
130
|
},
|
|
55
131
|
async rehydrated(
|
|
56
132
|
options: {
|
|
@@ -59,7 +135,7 @@ export function createCheckpointApi(
|
|
|
59
135
|
onProgress?: (index: number, event: BaseOutputEvent) => void
|
|
60
136
|
} = {},
|
|
61
137
|
) {
|
|
62
|
-
const checkpoint = await
|
|
138
|
+
const checkpoint = await api.load()
|
|
63
139
|
let startPosition = 0
|
|
64
140
|
if (checkpoint) {
|
|
65
141
|
const result = checkpointSchema.safeParse(checkpoint)
|
package/src/createEventStore.ts
CHANGED
|
@@ -172,7 +172,7 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
|
|
|
172
172
|
|
|
173
173
|
let exclusiveEmitEventsChain: Promise<any> = Promise.resolve()
|
|
174
174
|
const emitEvents: EmitEvents = async (events) => {
|
|
175
|
-
|
|
175
|
+
const result = exclusiveEmitEventsChain.then(async () => {
|
|
176
176
|
await Promise.all(processManagers.values().map((pm) => pm.beginSession()))
|
|
177
177
|
|
|
178
178
|
try {
|
|
@@ -200,7 +200,16 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
|
|
|
200
200
|
}
|
|
201
201
|
})
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
// Advance the serialization chain but swallow this operation's outcome so a
|
|
204
|
+
// rejection is delivered only to its own caller. Chaining the next op onto a
|
|
205
|
+
// rejected promise would skip its callback and re-propagate the stale error,
|
|
206
|
+
// permanently poisoning every subsequent emit for the life of the process.
|
|
207
|
+
exclusiveEmitEventsChain = result.then(
|
|
208
|
+
() => undefined,
|
|
209
|
+
() => undefined,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
return result
|
|
204
213
|
}
|
|
205
214
|
|
|
206
215
|
const loadEvents: LoadEvents = (select, range) => {
|
|
@@ -215,7 +224,7 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
|
|
|
215
224
|
expectedVersion,
|
|
216
225
|
) => {
|
|
217
226
|
assertInitializing()
|
|
218
|
-
|
|
227
|
+
const result = exclusiveAppendEventsChain.then(async () => {
|
|
219
228
|
if (events.length === 0) {
|
|
220
229
|
return []
|
|
221
230
|
}
|
|
@@ -241,7 +250,17 @@ export function createEventStore<const Root extends AnyAggregateRoot>(
|
|
|
241
250
|
return params.appendEvents(streamId, processedEvents, expectedVersion)
|
|
242
251
|
})
|
|
243
252
|
|
|
244
|
-
|
|
253
|
+
// Advance the serialization chain but swallow this operation's outcome so a
|
|
254
|
+
// rejection is delivered only to its own caller. Chaining the next append
|
|
255
|
+
// onto a rejected promise would skip its callback and re-propagate the stale
|
|
256
|
+
// error, permanently poisoning every subsequent append for the life of the
|
|
257
|
+
// process (a single ConcurrencyError would take down all writes).
|
|
258
|
+
exclusiveAppendEventsChain = result.then(
|
|
259
|
+
() => undefined,
|
|
260
|
+
() => undefined,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
return result
|
|
245
264
|
}
|
|
246
265
|
|
|
247
266
|
for (const aggregateRoot of params.aggregateRoots as unknown as InternalAggregateRootApi[]) {
|