@reventlessdev/reventless-core 3.0.0-alpha.169 → 3.0.0-alpha.171

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.
Files changed (110) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/package.json +16 -16
  3. package/src/admin/Platform_Admin.res +5 -2
  4. package/src/admin/Platform_Admin.res.mjs +4 -4
  5. package/src/components/Aggregate/Aggregate.res +5 -1
  6. package/src/components/Aggregate/Aggregate_Builder.res +21 -6
  7. package/src/components/Aggregate/Aggregate_Builder.res.mjs +10 -7
  8. package/src/components/AutomationSlice/AutomationSlice.res +1 -0
  9. package/src/components/AutomationSlice/AutomationSlice_Builder.res +13 -2
  10. package/src/components/AutomationSlice/AutomationSlice_Builder.res.mjs +5 -2
  11. package/src/components/Builder_Helpers.res +16 -2
  12. package/src/components/Builder_Helpers.res.mjs +6 -6
  13. package/src/components/Dcb/Dcb_Builder.res +46 -4
  14. package/src/components/Dcb/Dcb_Builder.res.mjs +13 -9
  15. package/src/components/ExtensionPoint/ExtensionPoint.res +2 -0
  16. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +10 -0
  17. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res.mjs +6 -4
  18. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +1 -0
  19. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +8 -1
  20. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs +1 -1
  21. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +1 -0
  22. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +12 -3
  23. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs +5 -2
  24. package/src/components/ReadModel/ReadModel.res +1 -0
  25. package/src/components/ReadModel/ReadModel_Builder.res +9 -1
  26. package/src/components/ReadModel/ReadModel_Builder.res.mjs +5 -2
  27. package/src/components/StateChangeSlice/StateChangeSlice.res +1 -0
  28. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +6 -0
  29. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res.mjs +1 -1
  30. package/src/components/StateViewSlice/StateViewSlice.res +1 -0
  31. package/src/components/StateViewSlice/StateViewSlice_Builder.res +11 -3
  32. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +5 -2
  33. package/src/components/Task/Task.res +1 -0
  34. package/src/components/Task/Task_Builder.res +11 -2
  35. package/src/components/Task/Task_Builder.res.mjs +7 -4
  36. package/src/plugin/component/Plugin.res +5 -0
  37. package/src/plugin/component/Plugin_Builder.res +10 -2
  38. package/src/plugin/component/Plugin_Builder.res.mjs +7 -6
  39. package/src/plugin/component/Plugin_Helpers.res +2 -0
  40. package/src/plugin/component/Plugin_Helpers.res.mjs +2 -2
  41. package/src/plugin/connect/PluginExtensionPoint_Builder.res +2 -0
  42. package/src/plugin/connect/PluginExtensionPoint_Builder.res.mjs +3 -3
  43. package/tests/plugin/ManifestVisibilityTest.res +2 -2
  44. package/tests/plugin/PluginStructureTest.res +6 -6
  45. package/tests/IdentityTest.res.mjs +0 -174
  46. package/tests/adapter/MonitoringTest.res.mjs +0 -82
  47. package/tests/admin/Platform_ComponentDefinitionsApiTest.res.mjs +0 -356
  48. package/tests/admin/Platform_UIFragmentsApiTest.res.mjs +0 -101
  49. package/tests/aggregate/AggregateCacheTest.res.mjs +0 -433
  50. package/tests/aggregate/AggregateCallbackTest.res.mjs +0 -143
  51. package/tests/aggregate/AggregateCausationTest.res.mjs +0 -47
  52. package/tests/aggregate/AggregateConflictTest.res.mjs +0 -386
  53. package/tests/aggregate/AggregateFixtures.res.mjs +0 -308
  54. package/tests/aggregate/AggregateRejectionTest.res.mjs +0 -166
  55. package/tests/aggregate/AggregateSnapshotTest.res.mjs +0 -645
  56. package/tests/api/ApiNoApiTest.res.mjs +0 -90
  57. package/tests/api/GraphQL_StitcherTest.res.mjs +0 -112
  58. package/tests/api/SimpleTest.res.mjs +0 -10
  59. package/tests/api/SuryToJsonSchemaTest.res.mjs +0 -674
  60. package/tests/commandgenerator/CommandGeneratorCallbackTest.res.mjs +0 -160
  61. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +0 -197
  62. package/tests/commandtopic/CommandTopicCallbackFixtures.res.mjs +0 -152
  63. package/tests/commandtopic/CommandTopicCallbackTest.res.mjs +0 -106
  64. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res.mjs +0 -109
  65. package/tests/counter/CounterCallbackTest.res.mjs +0 -140
  66. package/tests/counter/CounterFixtures.res.mjs +0 -67
  67. package/tests/dcb/DcbDecodeTest.res.mjs +0 -194
  68. package/tests/dcb/DcbEventLogOperationsTest.res.mjs +0 -268
  69. package/tests/dcb/DcbFixtures.res.mjs +0 -534
  70. package/tests/dcb/DcbScopeInferenceTest.res.mjs +0 -480
  71. package/tests/dcb/DcbStateChangeSliceTest.res.mjs +0 -540
  72. package/tests/dcb/DcbTagTest.res.mjs +0 -867
  73. package/tests/dcb/DcbValidationTest.res.mjs +0 -476
  74. package/tests/eventlog/EventLogFixtures.res.mjs +0 -196
  75. package/tests/eventlog/EventLogOperationsTest.res.mjs +0 -192
  76. package/tests/eventlog/EventLogRetryTest.res.mjs +0 -195
  77. package/tests/eventmapper/EventMapperCallbackTest.res.mjs +0 -141
  78. package/tests/eventmapper/EventMapperFixtures.res.mjs +0 -440
  79. package/tests/eventmapper/EventMapperTest.res.mjs +0 -83
  80. package/tests/eventtopic/EventTopicFixtures.res.mjs +0 -65
  81. package/tests/eventtopic/EventTopicOperationsTest.res.mjs +0 -71
  82. package/tests/extensionpoint/ExtensionPointCallbackTest.res.mjs +0 -94
  83. package/tests/extensionpoint/ExtensionPointFixtures.res.mjs +0 -205
  84. package/tests/extensionpoint/ExtensionPointOperationsTest.res.mjs +0 -304
  85. package/tests/ftp/FTPTest.res.mjs +0 -88
  86. package/tests/logger/LogFormatTest.res.mjs +0 -309
  87. package/tests/logger/LoggerLazyTest.res.mjs +0 -40
  88. package/tests/message/MessageTest.res.mjs +0 -218
  89. package/tests/message/MetaEnvelopeTest.res.mjs +0 -188
  90. package/tests/plugin/ManifestVisibilityTest.res.mjs +0 -215
  91. package/tests/plugin/PluginSpecExperiment.res.mjs +0 -31
  92. package/tests/plugin/PluginStructureTest.res.mjs +0 -419
  93. package/tests/plugin/PluginVersionTest.res.mjs +0 -30
  94. package/tests/plugin/SchemaWalkerTest.res.mjs +0 -160
  95. package/tests/plugin/StateChangeSlice/PsPlaceOrder.res.mjs +0 -62
  96. package/tests/plugin/StateChangeSlice/PsShipOrder.res.mjs +0 -69
  97. package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +0 -95
  98. package/tests/plugin/StateViewSlice/PsAvailableProductsView.res.mjs +0 -69
  99. package/tests/plugin/StateViewSlice/PsCustomersView.res.mjs +0 -69
  100. package/tests/plugin/StateViewSlice/PsOrdersView.res.mjs +0 -81
  101. package/tests/poc/StructuralSubtypingPoc.res.mjs +0 -61
  102. package/tests/projection/ProjectionOptimizeTest.res.mjs +0 -75
  103. package/tests/querydb/QueryDbFixtures.res.mjs +0 -135
  104. package/tests/querydb/QueryDbOperationsTest.res.mjs +0 -168
  105. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res.mjs +0 -77
  106. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res.mjs +0 -139
  107. package/tests/util/CommandPublisherTest.res.mjs +0 -78
  108. package/tests/util/CsvStreamTest.res.mjs +0 -51
  109. package/tests/util/LruTest.res.mjs +0 -105
  110. package/tests/util/MetricsTest.res.mjs +0 -53
@@ -1,540 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Id$Reventless from "@reventlessdev/reventless-spec/src/types/Id.res.mjs";
4
- import * as Effect from "effect/Effect";
5
- import * as Stream from "effect/Stream";
6
- import * as DcbFixtures$ReventlessCore from "./DcbFixtures.res.mjs";
7
- import * as DcbEventLog_Operations$ReventlessCore from "../../src/components/DcbEventLog/DcbEventLog_Operations.res.mjs";
8
- import * as StateChangeSlice_Callback$ReventlessCore from "../../src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs";
9
-
10
- let mock = DcbFixtures$ReventlessCore.makeMockStorage();
11
-
12
- let storage = mock.operations;
13
-
14
- let publishJson = mock.mockPublishJson;
15
-
16
- let TestDcbOps = {
17
- name: "TestDcbEventLog",
18
- serviceName: "TestDcbEventLog",
19
- storage: storage,
20
- publishJson: publishJson
21
- };
22
-
23
- let EventLogOps = DcbEventLog_Operations$ReventlessCore.Make(TestDcbOps);
24
-
25
- let testDcbEventLog_read = EventLogOps.read;
26
-
27
- let testDcbEventLog_append = EventLogOps.append;
28
-
29
- let testDcbEventLog_readStream = EventLogOps.readStream;
30
-
31
- let testDcbEventLog_appendStream = EventLogOps.appendStream;
32
-
33
- let testDcbEventLog = {
34
- read: testDcbEventLog_read,
35
- append: testDcbEventLog_append,
36
- readStream: testDcbEventLog_readStream,
37
- appendStream: testDcbEventLog_appendStream
38
- };
39
-
40
- let initialState = DcbFixtures$ReventlessCore.TestCommandSpec.initialState;
41
-
42
- let evolve = DcbFixtures$ReventlessCore.TestCommandSpec.evolve;
43
-
44
- let decide = DcbFixtures$ReventlessCore.TestCommandSpec.decide;
45
-
46
- let moduleUrl = DcbFixtures$ReventlessCore.TestCommandSpec.moduleUrl;
47
-
48
- let TestCommandBehavior = {
49
- initialState: initialState,
50
- evolve: evolve,
51
- decide: decide,
52
- moduleUrl: moduleUrl
53
- };
54
-
55
- let TestHandler = StateChangeSlice_Callback$ReventlessCore.Make({
56
- name: DcbFixtures$ReventlessCore.TestCommandSpec.name,
57
- moduleUrl: DcbFixtures$ReventlessCore.TestCommandSpec.moduleUrl,
58
- Id: Id$Reventless.$$String,
59
- consumedEventSchema: DcbFixtures$ReventlessCore.TestCommandSpec.consumedEventSchema,
60
- errorSchema: DcbFixtures$ReventlessCore.TestCommandSpec.errorSchema,
61
- eventSchema: DcbFixtures$ReventlessCore.TestCommandSpec.eventSchema,
62
- commandSchema: DcbFixtures$ReventlessCore.TestCommandSpec.commandSchema,
63
- commandAuthorization: DcbFixtures$ReventlessCore.TestCommandSpec.commandAuthorization,
64
- readConsistency: DcbFixtures$ReventlessCore.TestCommandSpec.readConsistency
65
- })(TestCommandBehavior);
66
-
67
- let name = DcbFixtures$ReventlessCore.TestCommandSpec.name;
68
-
69
- let moduleUrl$1 = DcbFixtures$ReventlessCore.TestCommandSpec.moduleUrl;
70
-
71
- let eventSchema = DcbFixtures$ReventlessCore.TestCommandSpec.eventSchema;
72
-
73
- let consumedEventSchema = DcbFixtures$ReventlessCore.TestCommandSpec.consumedEventSchema;
74
-
75
- let commandSchema = DcbFixtures$ReventlessCore.TestCommandSpec.commandSchema;
76
-
77
- let errorSchema = DcbFixtures$ReventlessCore.TestCommandSpec.errorSchema;
78
-
79
- let commandAuthorization = DcbFixtures$ReventlessCore.TestCommandSpec.commandAuthorization;
80
-
81
- let StrongSpec_Id = DcbFixtures$ReventlessCore.TestCommandSpec.Id;
82
-
83
- let StrongSpec_initialState = DcbFixtures$ReventlessCore.TestCommandSpec.initialState;
84
-
85
- let StrongSpec_evolve = DcbFixtures$ReventlessCore.TestCommandSpec.evolve;
86
-
87
- let StrongSpec_decide = DcbFixtures$ReventlessCore.TestCommandSpec.decide;
88
-
89
- let StrongSpec = {
90
- name: name,
91
- Id: StrongSpec_Id,
92
- moduleUrl: moduleUrl$1,
93
- eventSchema: eventSchema,
94
- consumedEventSchema: consumedEventSchema,
95
- commandSchema: commandSchema,
96
- errorSchema: errorSchema,
97
- initialState: StrongSpec_initialState,
98
- evolve: StrongSpec_evolve,
99
- decide: StrongSpec_decide,
100
- commandAuthorization: commandAuthorization,
101
- readConsistency: "AlwaysStrong"
102
- };
103
-
104
- let name$1 = DcbFixtures$ReventlessCore.TestCommandSpec.name;
105
-
106
- let moduleUrl$2 = DcbFixtures$ReventlessCore.TestCommandSpec.moduleUrl;
107
-
108
- let eventSchema$1 = DcbFixtures$ReventlessCore.TestCommandSpec.eventSchema;
109
-
110
- let consumedEventSchema$1 = DcbFixtures$ReventlessCore.TestCommandSpec.consumedEventSchema;
111
-
112
- let commandSchema$1 = DcbFixtures$ReventlessCore.TestCommandSpec.commandSchema;
113
-
114
- let errorSchema$1 = DcbFixtures$ReventlessCore.TestCommandSpec.errorSchema;
115
-
116
- let commandAuthorization$1 = DcbFixtures$ReventlessCore.TestCommandSpec.commandAuthorization;
117
-
118
- let EventualSpec_Id = DcbFixtures$ReventlessCore.TestCommandSpec.Id;
119
-
120
- let EventualSpec_initialState = DcbFixtures$ReventlessCore.TestCommandSpec.initialState;
121
-
122
- let EventualSpec_evolve = DcbFixtures$ReventlessCore.TestCommandSpec.evolve;
123
-
124
- let EventualSpec_decide = DcbFixtures$ReventlessCore.TestCommandSpec.decide;
125
-
126
- let EventualSpec = {
127
- name: name$1,
128
- Id: EventualSpec_Id,
129
- moduleUrl: moduleUrl$2,
130
- eventSchema: eventSchema$1,
131
- consumedEventSchema: consumedEventSchema$1,
132
- commandSchema: commandSchema$1,
133
- errorSchema: errorSchema$1,
134
- initialState: EventualSpec_initialState,
135
- evolve: EventualSpec_evolve,
136
- decide: EventualSpec_decide,
137
- commandAuthorization: commandAuthorization$1,
138
- readConsistency: "AlwaysEventual"
139
- };
140
-
141
- let StrongHandler = StateChangeSlice_Callback$ReventlessCore.Make({
142
- name: name,
143
- moduleUrl: moduleUrl$1,
144
- Id: Id$Reventless.$$String,
145
- consumedEventSchema: consumedEventSchema,
146
- errorSchema: errorSchema,
147
- eventSchema: eventSchema,
148
- commandSchema: commandSchema,
149
- commandAuthorization: commandAuthorization,
150
- readConsistency: "AlwaysStrong"
151
- })(TestCommandBehavior);
152
-
153
- let EventualHandler = StateChangeSlice_Callback$ReventlessCore.Make({
154
- name: name$1,
155
- moduleUrl: moduleUrl$2,
156
- Id: Id$Reventless.$$String,
157
- consumedEventSchema: consumedEventSchema$1,
158
- errorSchema: errorSchema$1,
159
- eventSchema: eventSchema$1,
160
- commandSchema: commandSchema$1,
161
- commandAuthorization: commandAuthorization$1,
162
- readConsistency: "AlwaysEventual"
163
- })(TestCommandBehavior);
164
-
165
- function makeTopicItem(reference, command) {
166
- return {
167
- command: {
168
- id: Id$Reventless.$$String.makeFromString("cmd-" + reference),
169
- meta: DcbFixtures$ReventlessCore.testMeta,
170
- command: command
171
- },
172
- reference: reference
173
- };
174
- }
175
-
176
- globalThis.beforeEach(() => {
177
- mock.reset();
178
- TestHandler.resetCache();
179
- StrongHandler.resetCache();
180
- EventualHandler.resetCache();
181
- });
182
-
183
- globalThis.describe("StateChangeSlice_Callback:", () => {
184
- globalThis.describe("handleCommands - happy path", () => {
185
- globalThis.test("CreateItem on empty log succeeds", async () => {
186
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
187
- TAG: "CreateItem",
188
- itemId: "item-1",
189
- name: "Test"
190
- })])));
191
- globalThis.expect([
192
- results,
193
- mock.getEvents().length,
194
- mock.publishedEvents.contents.length
195
- ]).toEqual([
196
- [{
197
- TAG: "Ok",
198
- _0: "ref-1"
199
- }],
200
- 1,
201
- 1
202
- ]);
203
- });
204
- globalThis.test("stored event carries only its entity tags (no framework provenance tag)", async () => {
205
- await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
206
- TAG: "CreateItem",
207
- itemId: "item-1",
208
- name: "Test"
209
- })])));
210
- let storedEvent = mock.getEvents()[0];
211
- globalThis.expect(storedEvent.tags).toEqual([{
212
- key: "itemId",
213
- value: "item-1"
214
- }]);
215
- });
216
- });
217
- globalThis.describe("handleCommands - decide returns Ok([])", () => {
218
- globalThis.test("NoOp returns Ok without storing events", async () => {
219
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-noop", "NoOp")])));
220
- globalThis.expect([
221
- results,
222
- mock.getEvents().length
223
- ]).toEqual([
224
- [{
225
- TAG: "Ok",
226
- _0: "ref-noop"
227
- }],
228
- 0
229
- ]);
230
- });
231
- });
232
- globalThis.describe("handleCommands - decide returns Error", () => {
233
- globalThis.test("CreateItem when item exists returns Ok (business-rule violations ACK, not NACK)", async () => {
234
- await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
235
- TAG: "CreateItem",
236
- itemId: "item-1",
237
- name: "Test"
238
- })])));
239
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-2", {
240
- TAG: "CreateItem",
241
- itemId: "item-1",
242
- name: "Duplicate"
243
- })])));
244
- globalThis.expect(results).toEqual([{
245
- TAG: "Ok",
246
- _0: "ref-2"
247
- }]);
248
- });
249
- });
250
- globalThis.describe("handleCommands - retry on conflict", () => {
251
- globalThis.test("retries and succeeds after 1 append failure", async () => {
252
- mock.failNextAppends.contents = 1;
253
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
254
- TAG: "CreateItem",
255
- itemId: "item-1",
256
- name: "Test"
257
- })])));
258
- globalThis.expect([
259
- results,
260
- mock.getEvents().length
261
- ]).toEqual([
262
- [{
263
- TAG: "Ok",
264
- _0: "ref-1"
265
- }],
266
- 1
267
- ]);
268
- });
269
- globalThis.test("returns Error after retries exhausted (4 failures)", async () => {
270
- mock.failNextAppends.contents = 4;
271
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
272
- TAG: "CreateItem",
273
- itemId: "item-1",
274
- name: "Test"
275
- })])));
276
- globalThis.expect([
277
- results,
278
- mock.getEvents().length
279
- ]).toEqual([
280
- [{
281
- TAG: "Error",
282
- _0: "ref-1"
283
- }],
284
- 0
285
- ]);
286
- });
287
- });
288
- globalThis.describe("handleCommands - read consistency (eventual-first, strong-on-retry)", () => {
289
- globalThis.test("a conflict-free command reads eventually-consistent (no strong read)", async () => {
290
- await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
291
- TAG: "CreateItem",
292
- itemId: "item-1",
293
- name: "Test"
294
- })])));
295
- globalThis.expect(mock.readStrongConsistency.contents).toEqual([false]);
296
- });
297
- globalThis.test("escalates to strong consistency on retry after a conflict", async () => {
298
- mock.failNextAppends.contents = 1;
299
- await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
300
- TAG: "CreateItem",
301
- itemId: "item-1",
302
- name: "Test"
303
- })])));
304
- globalThis.expect(mock.readStrongConsistency.contents).toEqual([
305
- false,
306
- true
307
- ]);
308
- });
309
- globalThis.test("every retry after the first is strong (2 failures)", async () => {
310
- mock.failNextAppends.contents = 2;
311
- await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
312
- TAG: "CreateItem",
313
- itemId: "item-1",
314
- name: "Test"
315
- })])));
316
- globalThis.expect(mock.readStrongConsistency.contents).toEqual([
317
- false,
318
- true,
319
- true
320
- ]);
321
- });
322
- });
323
- globalThis.describe("handleCommands - read consistency (per-slice override)", () => {
324
- globalThis.test("AlwaysStrong reads strong on the first attempt", async () => {
325
- await Effect.runPromise(StrongHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
326
- TAG: "CreateItem",
327
- itemId: "item-1",
328
- name: "Test"
329
- })])));
330
- globalThis.expect(mock.readStrongConsistency.contents).toEqual([true]);
331
- });
332
- globalThis.test("AlwaysStrong stays strong across retries (2 failures)", async () => {
333
- mock.failNextAppends.contents = 2;
334
- await Effect.runPromise(StrongHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
335
- TAG: "CreateItem",
336
- itemId: "item-1",
337
- name: "Test"
338
- })])));
339
- globalThis.expect(mock.readStrongConsistency.contents).toEqual([
340
- true,
341
- true,
342
- true
343
- ]);
344
- });
345
- globalThis.test("AlwaysEventual never reads strong, even on retry (2 failures)", async () => {
346
- mock.failNextAppends.contents = 2;
347
- await Effect.runPromise(EventualHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
348
- TAG: "CreateItem",
349
- itemId: "item-1",
350
- name: "Test"
351
- })])));
352
- globalThis.expect(mock.readStrongConsistency.contents).toEqual([
353
- false,
354
- false,
355
- false
356
- ]);
357
- });
358
- });
359
- globalThis.describe("handleCommands - conditional append", () => {
360
- globalThis.test("RenameItem after CreateItem uses headPosition in condition", async () => {
361
- await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-1", {
362
- TAG: "CreateItem",
363
- itemId: "item-1",
364
- name: "Test"
365
- })])));
366
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-2", {
367
- TAG: "RenameItem",
368
- itemId: "item-1",
369
- newName: "Updated"
370
- })])));
371
- globalThis.expect([
372
- results,
373
- mock.getEvents().length
374
- ]).toEqual([
375
- [{
376
- TAG: "Ok",
377
- _0: "ref-2"
378
- }],
379
- 2
380
- ]);
381
- });
382
- });
383
- globalThis.describe("handleCommands - batch", () => {
384
- globalThis.test("multiple successful commands", async () => {
385
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([
386
- makeTopicItem("ref-1", {
387
- TAG: "CreateItem",
388
- itemId: "item-1",
389
- name: "First"
390
- }),
391
- makeTopicItem("ref-2", {
392
- TAG: "CreateItem",
393
- itemId: "item-2",
394
- name: "Second"
395
- })
396
- ])));
397
- globalThis.expect(results).toEqual([
398
- {
399
- TAG: "Ok",
400
- _0: "ref-1"
401
- },
402
- {
403
- TAG: "Ok",
404
- _0: "ref-2"
405
- }
406
- ]);
407
- });
408
- globalThis.test("mixed: new item succeeds, duplicate item ACKs as Ok (business-rule violation)", async () => {
409
- await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem("ref-0", {
410
- TAG: "CreateItem",
411
- itemId: "item-1",
412
- name: "Existing"
413
- })])));
414
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([
415
- makeTopicItem("ref-1", {
416
- TAG: "CreateItem",
417
- itemId: "item-2",
418
- name: "New"
419
- }),
420
- makeTopicItem("ref-2", {
421
- TAG: "CreateItem",
422
- itemId: "item-1",
423
- name: "Duplicate"
424
- })
425
- ])));
426
- globalThis.expect(results).toEqual([
427
- {
428
- TAG: "Ok",
429
- _0: "ref-1"
430
- },
431
- {
432
- TAG: "Ok",
433
- _0: "ref-2"
434
- }
435
- ]);
436
- });
437
- globalThis.test("empty batch returns empty array", async () => {
438
- let results = await Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([])));
439
- globalThis.expect(results).toEqual([]);
440
- });
441
- });
442
- globalThis.describe("handleCommands - projection cache", () => {
443
- globalThis.test("a third same-entity command reads only the delta", async () => {
444
- let run = (reference, command) => Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem(reference, command)])));
445
- await run("ref-1", {
446
- TAG: "CreateItem",
447
- itemId: "item-1",
448
- name: "A"
449
- });
450
- await run("ref-2", {
451
- TAG: "RenameItem",
452
- itemId: "item-1",
453
- newName: "B"
454
- });
455
- let r3 = await run("ref-3", {
456
- TAG: "RenameItem",
457
- itemId: "item-1",
458
- newName: "C"
459
- });
460
- globalThis.expect([
461
- r3,
462
- mock.readAfters.contents,
463
- mock.getEvents().length
464
- ]).toEqual([
465
- [{
466
- TAG: "Ok",
467
- _0: "ref-3"
468
- }],
469
- [
470
- undefined,
471
- undefined,
472
- "1"
473
- ],
474
- 3
475
- ]);
476
- });
477
- globalThis.test("a different entity does not hit another entity's cache (full read)", async () => {
478
- let run = (reference, command) => Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem(reference, command)])));
479
- await run("ref-1", {
480
- TAG: "CreateItem",
481
- itemId: "item-1",
482
- name: "A"
483
- });
484
- await run("ref-2", {
485
- TAG: "CreateItem",
486
- itemId: "item-2",
487
- name: "B"
488
- });
489
- globalThis.expect(mock.readAfters.contents).toEqual([
490
- undefined,
491
- undefined
492
- ]);
493
- });
494
- globalThis.test("conflict re-seeds the cache so the retry reads the delta", async () => {
495
- let run = (reference, command) => Effect.runPromise(TestHandler.handleCommands(undefined, undefined, testDcbEventLog, Stream.fromIterable([makeTopicItem(reference, command)])));
496
- await run("ref-1", {
497
- TAG: "CreateItem",
498
- itemId: "item-1",
499
- name: "A"
500
- });
501
- mock.failNextAppends.contents = 1;
502
- let r2 = await run("ref-2", {
503
- TAG: "RenameItem",
504
- itemId: "item-1",
505
- newName: "B"
506
- });
507
- globalThis.expect([
508
- r2,
509
- mock.readAfters.contents,
510
- mock.getEvents().length
511
- ]).toEqual([
512
- [{
513
- TAG: "Ok",
514
- _0: "ref-2"
515
- }],
516
- [
517
- undefined,
518
- undefined,
519
- "1"
520
- ],
521
- 2
522
- ]);
523
- });
524
- });
525
- });
526
-
527
- export {
528
- mock,
529
- TestDcbOps,
530
- EventLogOps,
531
- testDcbEventLog,
532
- TestCommandBehavior,
533
- TestHandler,
534
- StrongSpec,
535
- EventualSpec,
536
- StrongHandler,
537
- EventualHandler,
538
- makeTopicItem,
539
- }
540
- /* mock Not a pure module */