@reventlessdev/reventless-core 3.0.0-alpha.262 → 3.0.0-alpha.264
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/CHANGELOG.md +23 -0
- package/package.json +9 -9
- package/src/admin/Platform_Admin_Structure.res.mjs +1 -1
- package/src/components/Aggregate/Aggregate_Builder.res.mjs +1 -1
- package/src/components/CommandGenerator/CommandGenerator.res +4 -4
- package/src/components/CommandGenerator/CommandGenerator_Callback.res +13 -20
- package/src/components/CommandGenerator/CommandGenerator_Callback.res.mjs +3 -24
- package/src/components/Dcb/Dcb_Builder.res +45 -49
- package/src/components/Dcb/Dcb_Builder.res.mjs +31 -40
- package/src/components/StateChangeSlice/StateChangeSlice.res +2 -0
- package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +6 -0
- package/src/components/StateChangeSlice/StateChangeSlice_Builder.res.mjs +4 -4
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +51 -22
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +47 -25
- package/src/plugin/component/Plugin_Structure.res +101 -4
- package/src/plugin/component/Plugin_Structure.res.mjs +82 -9
- package/tests/adapter/RuntimeExtensionHookReachTest.res.mjs +1 -1
- package/tests/commandgenerator/CommandGeneratorCallbackTest.res +1 -1
- package/tests/commandgenerator/CommandGeneratorCallbackTest.res.mjs +1 -1
- package/tests/commandgenerator/CommandGeneratorFixtures.res +2 -0
- package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +17 -3
- package/tests/commandgenerator/OwnerStampingTest.res.mjs +2 -2
- package/tests/commandtopic/CommandOutcomeHookTest.res.mjs +1 -1
- package/tests/dcb/DcbFixtures.res +18 -1
- package/tests/dcb/DcbFixtures.res.mjs +14 -0
- package/tests/dcb/DcbScopeInferenceTest.res +234 -0
- package/tests/dcb/DcbScopeInferenceTest.res.mjs +425 -13
- package/tests/dcb/DcbStateChangeSliceTest.res.mjs +22 -22
- package/tests/dcb/DcbTagTest.res +81 -68
- package/tests/dcb/DcbTagTest.res.mjs +88 -89
- package/tests/plugin/PluginStructureAccessTest.res +1 -0
- package/tests/plugin/PluginStructureAccessTest.res.mjs +1 -1
- package/tests/plugin/PluginStructureTest.res +47 -0
- package/tests/plugin/PluginStructureTest.res.mjs +50 -10
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,29 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 3.0.0-alpha.264 (2026-09-20)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @reventlessdev/reventless-core
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# 3.0.0-alpha.263 (2026-09-16)
|
|
15
|
+
|
|
16
|
+
* feat(spec)!: infer the DCB partition key per slice, and drop @partitionTag where inference agrees ([6c10161](https://github.com/ReventlessDev/reventless-core/commit/6c101611d438beea4bc9175ae8ea0ea1f6f7493b))
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
* **core:** fail the build when an extension cannot find its slice's partition key ([cf2b093](https://github.com/ReventlessDev/reventless-core/commit/cf2b093dd5dc7cf9425cdac919cd3910fc4aeefd))
|
|
20
|
+
* **spec:** let a slice's chapter break a partition-key tie ([2b9ae77](https://github.com/ReventlessDev/reventless-core/commit/2b9ae77e98eb42177d2bdd4977bc62bb7c7911aa))
|
|
21
|
+
|
|
22
|
+
### BREAKING CHANGES
|
|
23
|
+
|
|
24
|
+
* DcbTag.derivePartitionTag is removed; a boundary whose
|
|
25
|
+
partition cannot be inferred no longer deploys.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
6
29
|
# 3.0.0-alpha.262 (2026-09-11)
|
|
7
30
|
|
|
8
31
|
* feat(spec)!: a secret is a capability, so a test can know it in advance ([71507c6](https://github.com/ReventlessDev/reventless-core/commit/71507c6459b49178746f00c5040cb479d7fdade8))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-core",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.264",
|
|
4
4
|
"description": "Core package for Reventless framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"jest": {
|
|
@@ -28,17 +28,17 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"sury": "11.0.0-rc.2",
|
|
30
30
|
"uuid": "^13.0.0",
|
|
31
|
-
"@reventlessdev/rescript-
|
|
31
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.33",
|
|
32
32
|
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.14",
|
|
33
33
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
34
|
-
"@reventlessdev/rescript-
|
|
35
|
-
"@reventlessdev/rescript-
|
|
36
|
-
"@reventlessdev/rescript-
|
|
37
|
-
"@reventlessdev/rescript-ssh2": "2.0.0-alpha.
|
|
34
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.12",
|
|
35
|
+
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.21",
|
|
36
|
+
"@reventlessdev/rescript-fast-csv": "2.0.0-alpha.12",
|
|
37
|
+
"@reventlessdev/rescript-ssh2": "2.0.0-alpha.12",
|
|
38
38
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
39
|
-
"@reventlessdev/reventless-interop": "3.0.0-alpha.
|
|
40
|
-
"@reventlessdev/reventless-
|
|
41
|
-
"@reventlessdev/reventless-
|
|
39
|
+
"@reventlessdev/reventless-interop": "3.0.0-alpha.37",
|
|
40
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.137",
|
|
41
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.165"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"rescript": "12.3.0",
|
|
@@ -7,7 +7,7 @@ import * as PluginsReadModelSpec$ReventlessCore from "../plugin/lifecycle/Plugin
|
|
|
7
7
|
|
|
8
8
|
let pluginId = "Platform";
|
|
9
9
|
|
|
10
|
-
let pluginCommands = Plugin_Structure$ReventlessCore.extractCommandDefs(true, variantName => Api_Naming$ReventlessCore.adminField(PluginSpec$ReventlessCore.name + "_" + variantName), PluginSpec$ReventlessCore.commandAuthorization, PluginSpec$ReventlessCore.commandTransition, undefined, PluginSpec$ReventlessCore.commandSchema);
|
|
10
|
+
let pluginCommands = Plugin_Structure$ReventlessCore.extractCommandDefs(true, undefined, variantName => Api_Naming$ReventlessCore.adminField(PluginSpec$ReventlessCore.name + "_" + variantName), PluginSpec$ReventlessCore.commandAuthorization, PluginSpec$ReventlessCore.commandTransition, undefined, PluginSpec$ReventlessCore.commandSchema);
|
|
11
11
|
|
|
12
12
|
let pluginAggregate_producedEventTypes = [];
|
|
13
13
|
|
|
@@ -61,7 +61,7 @@ function Make(Spec) {
|
|
|
61
61
|
let fields = registeredFields !== undefined ? (
|
|
62
62
|
registeredFields.length !== 0 ? registeredFields : []
|
|
63
63
|
) : [];
|
|
64
|
-
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(publishJsons, publishJsonsAndWait, Spec.name, Spec.commandSchema, "Aggregate", undefined);
|
|
64
|
+
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(publishJsons, publishJsonsAndWait, Spec.name, Spec.commandSchema, "Aggregate", undefined, undefined);
|
|
65
65
|
fields.forEach(field => bindHandler(field, generateCommand));
|
|
66
66
|
} else {
|
|
67
67
|
let resources = Component$ReventlessCore.outputs(commandTopic).resources;
|
|
@@ -7,10 +7,10 @@ The `id` field is the envelope id for the produced command message:
|
|
|
7
7
|
- For **Aggregates**, it is required — the resolver populates it from the
|
|
8
8
|
GraphQL `id: ID!` argument injected into the mutation SDL.
|
|
9
9
|
- For **DCB StateChangeSlices**, it is optional. When the resolver does not
|
|
10
|
-
supply one, `makeGenerateCommand`
|
|
11
|
-
|
|
12
|
-
the
|
|
13
|
-
|
|
10
|
+
supply one, `makeGenerateCommand` takes the envelope id from the command's
|
|
11
|
+
value of the handling slice's partition key — the key `Dcb_Builder` derives
|
|
12
|
+
for storage and the fence — so envelope id and slice partition key share one
|
|
13
|
+
source of truth.
|
|
14
14
|
*/
|
|
15
15
|
type arguments = {id: string}
|
|
16
16
|
type meta = {ip: array<string>, user: string, info: string}
|
|
@@ -112,6 +112,8 @@ let makeGenerateCommand = (
|
|
|
112
112
|
~commandSchema: S.t<unknown>,
|
|
113
113
|
~componentKind: commandComponentKind,
|
|
114
114
|
~stripIdFromParams: bool=true,
|
|
115
|
+
// The handling slice's partition; the envelope id is its value on the command.
|
|
116
|
+
~partitionTag: option<Reventless.DcbTag.derivedPartitionTag>=?,
|
|
115
117
|
): CommandGenerator.commandGenerator => {
|
|
116
118
|
(payload: CommandGenerator.payload) =>
|
|
117
119
|
Effect.sync(() => {
|
|
@@ -157,9 +159,11 @@ let makeGenerateCommand = (
|
|
|
157
159
|
}
|
|
158
160
|
// Resolve the envelope id.
|
|
159
161
|
// - Aggregates always rely on the resolver-supplied id (id: ID! arg in SDL).
|
|
160
|
-
// - DCB StateChangeSlices fall back to
|
|
161
|
-
// partition
|
|
162
|
-
// @compositePartitionTag work end-to-end without per-call-site
|
|
162
|
+
// - DCB StateChangeSlices fall back to the value of the handling slice's
|
|
163
|
+
// partition field on the command when the resolver didn't supply one —
|
|
164
|
+
// what makes @compositePartitionTag work end-to-end without per-call-site
|
|
165
|
+
// id stuffing. A command without that field, or a generator that was not
|
|
166
|
+
// given the partition (the permissive `S.json` fallback), gets `""`.
|
|
163
167
|
let suppliedId = payload.arguments.id
|
|
164
168
|
let id = switch componentKind {
|
|
165
169
|
| Aggregate => suppliedId
|
|
@@ -167,23 +171,12 @@ let makeGenerateCommand = (
|
|
|
167
171
|
switch (suppliedId->Obj.magic: Nullable.t<string>)->Nullable.toOption {
|
|
168
172
|
| Some(idValue) => idValue
|
|
169
173
|
| None =>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
| Composite(spec) =>
|
|
177
|
-
let tags = Reventless.DcbTag.extractTagsFromJson(commandSchema, commandJson)
|
|
178
|
-
Reventless.DcbTag.getCompositePartitionKeyValue(tags, spec)
|
|
179
|
-
}
|
|
180
|
-
} catch {
|
|
181
|
-
// Permissive schemas (e.g. S.json on the AppSync direct-invocation path)
|
|
182
|
-
// have no tagged fields — derivePartitionTag throws. Fall back to "" so
|
|
183
|
-
// existing transports keep their pre-fix behavior; the slice decoder
|
|
184
|
-
// surfaces the missing id downstream as it did before.
|
|
185
|
-
| _ => ""
|
|
186
|
-
}
|
|
174
|
+
partitionTag->Option.mapOr("", pt =>
|
|
175
|
+
Reventless.DcbTag.extractTagsFromJson(
|
|
176
|
+
commandSchema,
|
|
177
|
+
commandJson,
|
|
178
|
+
)->Reventless.DcbTag.partitionValueOfTags(pt)
|
|
179
|
+
)
|
|
187
180
|
}
|
|
188
181
|
}
|
|
189
182
|
(meta, commandJson, id)
|
|
@@ -59,7 +59,7 @@ function dropNullArguments(obj) {
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
function makeGenerateCommand(publishJsons, publishJsonsAndWait, serviceName, commandSchema, componentKind, $staropt$star) {
|
|
62
|
+
function makeGenerateCommand(publishJsons, publishJsonsAndWait, serviceName, commandSchema, componentKind, $staropt$star, partitionTag) {
|
|
63
63
|
return payload => {
|
|
64
64
|
let stripIdFromParams = $staropt$star !== undefined ? $staropt$star : true;
|
|
65
65
|
return Effect.flatMap(Effect.tap(Effect.sync(() => {
|
|
@@ -85,28 +85,7 @@ function makeGenerateCommand(publishJsons, publishJsonsAndWait, serviceName, com
|
|
|
85
85
|
]].concat(params)) : commandStr;
|
|
86
86
|
let suppliedId = payload.arguments.id;
|
|
87
87
|
let id;
|
|
88
|
-
|
|
89
|
-
id = suppliedId;
|
|
90
|
-
} else {
|
|
91
|
-
try {
|
|
92
|
-
let derived = DcbTag$Reventless.derivePartitionTag([[
|
|
93
|
-
serviceName,
|
|
94
|
-
"",
|
|
95
|
-
commandSchema
|
|
96
|
-
]]);
|
|
97
|
-
if (derived.TAG === "Simple") {
|
|
98
|
-
let tags = DcbTag$Reventless.extractTagsFromJson(commandSchema, commandJson);
|
|
99
|
-
id = Stdlib_Option.getOr(DcbTag$Reventless.getPartitionTagValue([{
|
|
100
|
-
tags: tags
|
|
101
|
-
}], derived._0), "");
|
|
102
|
-
} else {
|
|
103
|
-
let tags$1 = DcbTag$Reventless.extractTagsFromJson(commandSchema, commandJson);
|
|
104
|
-
id = DcbTag$Reventless.getCompositePartitionKeyValue(tags$1, derived._0);
|
|
105
|
-
}
|
|
106
|
-
} catch (exn) {
|
|
107
|
-
id = "";
|
|
108
|
-
}
|
|
109
|
-
}
|
|
88
|
+
id = componentKind === "Aggregate" || !(suppliedId == null) ? suppliedId : Stdlib_Option.mapOr(partitionTag, "", pt => DcbTag$Reventless.partitionValueOfTags(DcbTag$Reventless.extractTagsFromJson(commandSchema, commandJson), pt));
|
|
110
89
|
return [
|
|
111
90
|
meta,
|
|
112
91
|
commandJson,
|
|
@@ -181,7 +160,7 @@ function makeGenerateCommand(publishJsons, publishJsonsAndWait, serviceName, com
|
|
|
181
160
|
|
|
182
161
|
function Make(Spec) {
|
|
183
162
|
return AggregateSpec => {
|
|
184
|
-
let generateCommand = makeGenerateCommand(Spec.publishJsons, Spec.publishJsonsAndWait, AggregateSpec.name, AggregateSpec.commandSchema, "Aggregate", undefined);
|
|
163
|
+
let generateCommand = makeGenerateCommand(Spec.publishJsons, Spec.publishJsonsAndWait, AggregateSpec.name, AggregateSpec.commandSchema, "Aggregate", undefined, undefined);
|
|
185
164
|
return {
|
|
186
165
|
generateCommand: generateCommand
|
|
187
166
|
};
|
|
@@ -1,26 +1,5 @@
|
|
|
1
|
-
// Converts a file:// module URL to a path relative to the project root (located by lerna.json),
|
|
2
|
-
// resolving symlinks so workspace packages show their source location rather than node_modules.
|
|
3
|
-
// Falls back to the bare URL string on any error.
|
|
4
1
|
let log = Logger.fromEnv()
|
|
5
2
|
|
|
6
|
-
let toRelativePath: string => string = %raw(`function toRelativePath(moduleUrl) {
|
|
7
|
-
try {
|
|
8
|
-
const fs = process.getBuiltinModule('node:fs');
|
|
9
|
-
const path = process.getBuiltinModule('node:path');
|
|
10
|
-
const { fileURLToPath } = process.getBuiltinModule('node:url');
|
|
11
|
-
const builderReal = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
12
|
-
const sliceReal = fs.realpathSync(fileURLToPath(moduleUrl));
|
|
13
|
-
let dir = path.dirname(builderReal);
|
|
14
|
-
while (dir !== path.dirname(dir)) {
|
|
15
|
-
if (fs.existsSync(path.join(dir, 'lerna.json'))) break;
|
|
16
|
-
dir = path.dirname(dir);
|
|
17
|
-
}
|
|
18
|
-
return path.relative(dir, sliceReal).replace(/\.mjs$/, '.res');
|
|
19
|
-
} catch(e) {
|
|
20
|
-
return moduleUrl.replace('file://', '');
|
|
21
|
-
}
|
|
22
|
-
}`)
|
|
23
|
-
|
|
24
3
|
// The tag of one compiled variant arm: `{TAG: "<Name>", …}` for a payload-bearing
|
|
25
4
|
// constructor, a bare string const for a payload-less one.
|
|
26
5
|
let variantTag = (variant: S.t<unknown>) =>
|
|
@@ -182,12 +161,6 @@ module Make = (
|
|
|
182
161
|
Sc.Spec.name,
|
|
183
162
|
Sc.Spec.eventSchema->S.castToUnknown,
|
|
184
163
|
))
|
|
185
|
-
let producedNamed =
|
|
186
|
-
stateChangeSlices->Array.map((module(Sc: StateChangeSlice.T)) => (
|
|
187
|
-
Sc.Spec.name,
|
|
188
|
-
toRelativePath(Sc.Spec.moduleUrl),
|
|
189
|
-
Sc.Spec.eventSchema->S.castToUnknown,
|
|
190
|
-
))
|
|
191
164
|
let consumed =
|
|
192
165
|
stateChangeSlices
|
|
193
166
|
->Array.map((module(Sc: StateChangeSlice.T)) => (
|
|
@@ -253,7 +226,39 @@ module Make = (
|
|
|
253
226
|
indexes
|
|
254
227
|
}
|
|
255
228
|
|
|
256
|
-
let
|
|
229
|
+
let sliceSchemas = stateChangeSlices->Array.map((module(Sc: StateChangeSlice.T)) => {
|
|
230
|
+
Reventless.DcbTag.name: Sc.Spec.name,
|
|
231
|
+
commandSchema: Sc.Spec.commandSchema->S.castToUnknown,
|
|
232
|
+
consumedEventSchema: Sc.Spec.consumedEventSchema->S.castToUnknown,
|
|
233
|
+
eventSchema: Sc.Spec.eventSchema->S.castToUnknown,
|
|
234
|
+
moduleUrl: Sc.Spec.moduleUrl,
|
|
235
|
+
})
|
|
236
|
+
let inferenceShapes = sliceSchemas->Array.map(Reventless.DcbTag.sliceShape)
|
|
237
|
+
|
|
238
|
+
// A `@partitionTag` inference contradicts would steer storage, fence and read
|
|
239
|
+
// scope to a key the slice only references, so it stops the build. One that
|
|
240
|
+
// inference agrees with is noise, and says so.
|
|
241
|
+
let hintIssues = Reventless.DcbValidation.validatePartitionHintsVsInference(
|
|
242
|
+
~shapes=inferenceShapes,
|
|
243
|
+
)
|
|
244
|
+
hintIssues.redundancies->Array.forEach(e =>
|
|
245
|
+
log.info(~comp="Dcb_Builder", `DCB partition (${e.sliceName}): ${e.message}`)
|
|
246
|
+
)
|
|
247
|
+
if hintIssues.contradictions->Array.length > 0 {
|
|
248
|
+
let detail =
|
|
249
|
+
hintIssues.contradictions
|
|
250
|
+
->Array.map(e => `${e.sliceName}: ${e.message}`)
|
|
251
|
+
->Array.join(" | ")
|
|
252
|
+
log.error(~comp="Dcb_Builder", `DCB partition contradiction (${name}): ${detail}`)
|
|
253
|
+
JsError.throwWithMessage(`DCB partition contradiction (${name}): ${detail}`)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Where each event is stored — and so its fence, and each command's envelope
|
|
257
|
+
// id. Throws, naming the slice, when a partition cannot be inferred.
|
|
258
|
+
let boundaryPartition = Reventless.DcbTag.deriveBoundaryPartition(sliceSchemas)
|
|
259
|
+
let partitionTag = boundaryPartition.partitionTag
|
|
260
|
+
let partitionTagOf = sliceName =>
|
|
261
|
+
boundaryPartition->Reventless.DcbTag.slicePartitionTag(sliceName)
|
|
257
262
|
|
|
258
263
|
// Tag keys declared `@crossPartition` across the produced event schemas.
|
|
259
264
|
// Derived once at build time (the scope is a property of the tag key, and
|
|
@@ -325,15 +330,6 @@ module Make = (
|
|
|
325
330
|
// preserved (generalised rule 3). Safety guard: if any slice's partition is
|
|
326
331
|
// ambiguous we keep the annotated values for the whole boundary rather than
|
|
327
332
|
// thread a partial inference. See docs/plans/done/dcb-tag-scope-inference.md.
|
|
328
|
-
let inferenceShapes =
|
|
329
|
-
stateChangeSlices->Array.map((module(Sc: StateChangeSlice.T)) =>
|
|
330
|
-
Reventless.DcbTag.sliceShapeFromSchemas(
|
|
331
|
-
~name=Sc.Spec.name,
|
|
332
|
-
~commandSchema=Sc.Spec.commandSchema->S.castToUnknown,
|
|
333
|
-
~consumedEventSchema=Sc.Spec.consumedEventSchema->S.castToUnknown,
|
|
334
|
-
~eventSchema=Sc.Spec.eventSchema->S.castToUnknown,
|
|
335
|
-
)
|
|
336
|
-
)
|
|
337
333
|
let inferred = Reventless.DcbScopeInference.infer(inferenceShapes)
|
|
338
334
|
if inferred.crossPartitionTagKeys != crossPartitionTagKeys {
|
|
339
335
|
log.info(
|
|
@@ -388,14 +384,7 @@ module Make = (
|
|
|
388
384
|
// (DcbCommandTopicEntryPoint.mjs) route through `DcbTag.deriveEffectiveScope`
|
|
389
385
|
// so the runtime decision query cannot drift from this scope — see
|
|
390
386
|
// docs/analysis/dcb-runtime-scope-annotation-drift.md.
|
|
391
|
-
let effective = Reventless.DcbTag.deriveEffectiveScope(
|
|
392
|
-
stateChangeSlices->Array.map((module(Sc: StateChangeSlice.T)) => {
|
|
393
|
-
Reventless.DcbTag.name: Sc.Spec.name,
|
|
394
|
-
commandSchema: Sc.Spec.commandSchema->S.castToUnknown,
|
|
395
|
-
consumedEventSchema: Sc.Spec.consumedEventSchema->S.castToUnknown,
|
|
396
|
-
eventSchema: Sc.Spec.eventSchema->S.castToUnknown,
|
|
397
|
-
}),
|
|
398
|
-
)
|
|
387
|
+
let effective = Reventless.DcbTag.deriveEffectiveScope(sliceSchemas)
|
|
399
388
|
let effectiveCrossPartitionTagKeys = effective.crossPartitionTagKeys
|
|
400
389
|
let effectiveTagKeysByEventType = effective.tagKeysByEventType
|
|
401
390
|
|
|
@@ -487,6 +476,7 @@ module Make = (
|
|
|
487
476
|
~publishJsons,
|
|
488
477
|
~tagKeysByEventType=effectiveTagKeysByEventType,
|
|
489
478
|
~crossPartitionTagKeys=effectiveCrossPartitionTagKeys,
|
|
479
|
+
~partitionTag=?partitionTagOf(StateChangeSlice.Spec.name),
|
|
490
480
|
~runtime=?componentRuntime->Dict.get(StateChangeSlice.Spec.name),
|
|
491
481
|
~opts,
|
|
492
482
|
)
|
|
@@ -507,6 +497,7 @@ module Make = (
|
|
|
507
497
|
~publishJsons=asyncPublishJsons,
|
|
508
498
|
~tagKeysByEventType=effectiveTagKeysByEventType,
|
|
509
499
|
~crossPartitionTagKeys=effectiveCrossPartitionTagKeys,
|
|
500
|
+
~partitionTag=?partitionTagOf(StateChangeSlice.Spec.name),
|
|
510
501
|
~runtime=?componentRuntime->Dict.get(StateChangeSlice.Spec.name),
|
|
511
502
|
~opts,
|
|
512
503
|
)
|
|
@@ -572,6 +563,7 @@ module Make = (
|
|
|
572
563
|
~commandSchema=S.Spec.commandSchema->Obj.magic,
|
|
573
564
|
~componentKind=CommandGenerator_Callback.StateChangeSlice,
|
|
574
565
|
~stripIdFromParams=false,
|
|
566
|
+
~partitionTag=?partitionTagOf(S.Spec.name),
|
|
575
567
|
)
|
|
576
568
|
Api_Naming.sliceMutationFields(
|
|
577
569
|
~plugin=apiNamePrefix,
|
|
@@ -602,6 +594,7 @@ module Make = (
|
|
|
602
594
|
~commandSchema=S.Spec.commandSchema->Obj.magic,
|
|
603
595
|
~componentKind=CommandGenerator_Callback.StateChangeSlice,
|
|
604
596
|
~stripIdFromParams=false,
|
|
597
|
+
~partitionTag=?partitionTagOf(S.Spec.name),
|
|
605
598
|
)
|
|
606
599
|
Api_Naming.sliceMutationFields(
|
|
607
600
|
~plugin=apiNamePrefix,
|
|
@@ -813,7 +806,7 @@ module Make = (
|
|
|
813
806
|
`Two DCB slices in "${name}" both declare the command "${tag}". ` ++
|
|
814
807
|
"Owner stamping resolves a command by that name alone, so it cannot " ++ "tell them apart. Rename one of the constructors.",
|
|
815
808
|
)
|
|
816
|
-
| None => byTag->Dict.set(tag, commandSchema)
|
|
809
|
+
| None => byTag->Dict.set(tag, (commandSchema, partitionTagOf(S.Spec.name)))
|
|
817
810
|
}
|
|
818
811
|
})
|
|
819
812
|
}
|
|
@@ -825,7 +818,7 @@ module Make = (
|
|
|
825
818
|
dcbCommandTopic
|
|
826
819
|
->Component.operations
|
|
827
820
|
->Pulumi.Output.apply(ops => {
|
|
828
|
-
let make = commandSchema =>
|
|
821
|
+
let make = (commandSchema, partitionTag) =>
|
|
829
822
|
CommandGenerator_Callback.makeGenerateCommand(
|
|
830
823
|
~publishJsons=ops.publishJsons,
|
|
831
824
|
~publishJsonsAndWait=?ops.publishJsonsAndWait,
|
|
@@ -833,16 +826,19 @@ module Make = (
|
|
|
833
826
|
~commandSchema,
|
|
834
827
|
~componentKind=CommandGenerator_Callback.StateChangeSlice,
|
|
835
828
|
~stripIdFromParams=false,
|
|
829
|
+
~partitionTag?,
|
|
836
830
|
)
|
|
837
831
|
let byTag = Dict.make()
|
|
838
832
|
dcbCommandSchemasByTag
|
|
839
833
|
->Dict.toArray
|
|
840
|
-
->Array.forEach(((tag, schema
|
|
834
|
+
->Array.forEach(((tag, (schema, partitionTag))) =>
|
|
835
|
+
byTag->Dict.set(tag, make(schema, partitionTag))
|
|
836
|
+
)
|
|
841
837
|
// A command no slice claims keeps the permissive generator — what every
|
|
842
838
|
// command got before this change — so nothing that reaches this handler
|
|
843
839
|
// by another route starts failing. It also cannot stamp, which is why
|
|
844
840
|
// the unknown case is logged rather than left to look like a success.
|
|
845
|
-
(byTag, make(S.json->S.castToUnknown))
|
|
841
|
+
(byTag, make(S.json->S.castToUnknown, None))
|
|
846
842
|
})
|
|
847
843
|
|
|
848
844
|
let dcbHandler =
|
|
@@ -8,6 +8,7 @@ import * as Output$Pulumi from "@reventlessdev/rescript-pulumi-pulumi/src/Output
|
|
|
8
8
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
9
9
|
import * as Effect from "effect/Effect";
|
|
10
10
|
import * as Pulumi from "@pulumi/pulumi";
|
|
11
|
+
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
11
12
|
import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
|
|
12
13
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
13
14
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
@@ -30,24 +31,6 @@ import * as OutboundTranslationSlice_Callback$ReventlessCore from "../OutboundTr
|
|
|
30
31
|
|
|
31
32
|
let log = Logger$ReventlessCore.fromEnv();
|
|
32
33
|
|
|
33
|
-
let toRelativePath = (function toRelativePath(moduleUrl) {
|
|
34
|
-
try {
|
|
35
|
-
const fs = process.getBuiltinModule('node:fs');
|
|
36
|
-
const path = process.getBuiltinModule('node:path');
|
|
37
|
-
const { fileURLToPath } = process.getBuiltinModule('node:url');
|
|
38
|
-
const builderReal = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
39
|
-
const sliceReal = fs.realpathSync(fileURLToPath(moduleUrl));
|
|
40
|
-
let dir = path.dirname(builderReal);
|
|
41
|
-
while (dir !== path.dirname(dir)) {
|
|
42
|
-
if (fs.existsSync(path.join(dir, 'lerna.json'))) break;
|
|
43
|
-
dir = path.dirname(dir);
|
|
44
|
-
}
|
|
45
|
-
return path.relative(dir, sliceReal).replace(/\.mjs$/, '.res');
|
|
46
|
-
} catch(e) {
|
|
47
|
-
return moduleUrl.replace('file://', '');
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
|
|
51
34
|
function variantTag(variant) {
|
|
52
35
|
switch (variant.type) {
|
|
53
36
|
case "string" :
|
|
@@ -157,11 +140,6 @@ function Make(DcbEventLogStorage) {
|
|
|
157
140
|
Sc.Spec.name,
|
|
158
141
|
Sc.Spec.eventSchema
|
|
159
142
|
]);
|
|
160
|
-
let producedNamed = stateChangeSlices.map(Sc => [
|
|
161
|
-
Sc.Spec.name,
|
|
162
|
-
toRelativePath(Sc.Spec.moduleUrl),
|
|
163
|
-
Sc.Spec.eventSchema
|
|
164
|
-
]);
|
|
165
143
|
let consumed = stateChangeSlices.map(Sc => [
|
|
166
144
|
Sc.Spec.name,
|
|
167
145
|
Sc.Spec.consumedEventSchema
|
|
@@ -191,7 +169,23 @@ function Make(DcbEventLogStorage) {
|
|
|
191
169
|
}
|
|
192
170
|
}).map(tagKey => `tag_` + tagKey);
|
|
193
171
|
let indexes$1 = indexes.length > 1 ? indexes.concat(["tag_composite"]) : indexes;
|
|
194
|
-
let
|
|
172
|
+
let sliceSchemas = stateChangeSlices.map(Sc => ({
|
|
173
|
+
name: Sc.Spec.name,
|
|
174
|
+
commandSchema: Sc.Spec.commandSchema,
|
|
175
|
+
consumedEventSchema: Sc.Spec.consumedEventSchema,
|
|
176
|
+
eventSchema: Sc.Spec.eventSchema,
|
|
177
|
+
moduleUrl: Sc.Spec.moduleUrl
|
|
178
|
+
}));
|
|
179
|
+
let inferenceShapes = sliceSchemas.map(DcbTag$Reventless.sliceShape);
|
|
180
|
+
let hintIssues = DcbValidation$Reventless.validatePartitionHintsVsInference(inferenceShapes);
|
|
181
|
+
hintIssues.redundancies.forEach(e => log.info("Dcb_Builder", undefined, `DCB partition (` + e.sliceName + `): ` + e.message));
|
|
182
|
+
if (hintIssues.contradictions.length !== 0) {
|
|
183
|
+
let detail = hintIssues.contradictions.map(e => e.sliceName + `: ` + e.message).join(" | ");
|
|
184
|
+
log.error("Dcb_Builder", undefined, `DCB partition contradiction (` + name + `): ` + detail);
|
|
185
|
+
Stdlib_JsError.throwWithMessage(`DCB partition contradiction (` + name + `): ` + detail);
|
|
186
|
+
}
|
|
187
|
+
let boundaryPartition = DcbTag$Reventless.deriveBoundaryPartition(sliceSchemas);
|
|
188
|
+
let partitionTag = boundaryPartition.partitionTag;
|
|
195
189
|
let arr$1 = producedSchemas.flatMap(DcbTag$Reventless.extractCrossPartitionTagKeys);
|
|
196
190
|
let seen$1 = new Set();
|
|
197
191
|
let crossPartitionTagKeys = arr$1.filter(f => {
|
|
@@ -209,7 +203,6 @@ function Make(DcbEventLogStorage) {
|
|
|
209
203
|
Sc.Spec.commandSchema,
|
|
210
204
|
Sc.Spec.consumedEventSchema
|
|
211
205
|
]), tagKeysByEventType).forEach(w => log.warn("Dcb_Builder", undefined, `DCB composite-read warning (` + w.sliceName + `): ` + w.message));
|
|
212
|
-
let inferenceShapes = stateChangeSlices.map(Sc => DcbTag$Reventless.sliceShapeFromSchemas(Sc.Spec.name, Sc.Spec.commandSchema, Sc.Spec.consumedEventSchema, Sc.Spec.eventSchema));
|
|
213
206
|
let inferred = DcbScopeInference$Reventless.infer(inferenceShapes);
|
|
214
207
|
if (Primitive_object.notequal(inferred.crossPartitionTagKeys, crossPartitionTagKeys)) {
|
|
215
208
|
log.info("Dcb_Builder", undefined, `DCB scope-inference diff: crossPartitionTagKeys annotated=[` + crossPartitionTagKeys.join(", ") + `] inferred=[` + inferred.crossPartitionTagKeys.join(", ") + `]`);
|
|
@@ -231,12 +224,7 @@ function Make(DcbEventLogStorage) {
|
|
|
231
224
|
let scopeIssues = DcbValidation$Reventless.validateScopeVsInference(scopeAnnotations, inferred);
|
|
232
225
|
scopeIssues.contradictions.forEach(e => log.warn("Dcb_Builder", undefined, `DCB scope contradiction (` + e.sliceName + `): ` + e.message));
|
|
233
226
|
scopeIssues.redundancies.forEach(e => log.info("Dcb_Builder", undefined, `DCB scope (` + e.sliceName + `): ` + e.message));
|
|
234
|
-
let effective = DcbTag$Reventless.deriveEffectiveScope(
|
|
235
|
-
name: Sc.Spec.name,
|
|
236
|
-
commandSchema: Sc.Spec.commandSchema,
|
|
237
|
-
consumedEventSchema: Sc.Spec.consumedEventSchema,
|
|
238
|
-
eventSchema: Sc.Spec.eventSchema
|
|
239
|
-
})));
|
|
227
|
+
let effective = DcbTag$Reventless.deriveEffectiveScope(sliceSchemas);
|
|
240
228
|
let effectiveCrossPartitionTagKeys = effective.crossPartitionTagKeys;
|
|
241
229
|
let effectiveTagKeysByEventType = effective.tagKeysByEventType;
|
|
242
230
|
if (effective.droppedCrossPartitionTagKeys.length !== 0) {
|
|
@@ -276,7 +264,7 @@ function Make(DcbEventLogStorage) {
|
|
|
276
264
|
asyncDcbCommandTopicOpt = undefined;
|
|
277
265
|
}
|
|
278
266
|
let stateChangeSlicesOutputs = Object.fromEntries(syncSlices.map(StateChangeSlice => {
|
|
279
|
-
let ch = StateChangeSlice.make(dcbEventLog, publishJsons, effectiveTagKeysByEventType, effectiveCrossPartitionTagKeys, componentRuntime[StateChangeSlice.Spec.name], opts);
|
|
267
|
+
let ch = StateChangeSlice.make(dcbEventLog, publishJsons, effectiveTagKeysByEventType, effectiveCrossPartitionTagKeys, DcbTag$Reventless.slicePartitionTag(boundaryPartition, StateChangeSlice.Spec.name), componentRuntime[StateChangeSlice.Spec.name], opts);
|
|
280
268
|
return [
|
|
281
269
|
StateChangeSlice.Spec.name,
|
|
282
270
|
Component$ReventlessCore.outputs(ch)
|
|
@@ -286,7 +274,7 @@ function Make(DcbEventLogStorage) {
|
|
|
286
274
|
if (asyncDcbCommandTopicOpt !== undefined) {
|
|
287
275
|
let asyncPublishJsons = Component$ReventlessCore.operations(Primitive_option.valFromOption(asyncDcbCommandTopicOpt)).apply(ops => ops.publishJsons);
|
|
288
276
|
asyncStateChangeSlicesOutputs = Object.fromEntries(asyncSlices.map(StateChangeSlice => {
|
|
289
|
-
let ch = StateChangeSlice.make(dcbEventLog, asyncPublishJsons, effectiveTagKeysByEventType, effectiveCrossPartitionTagKeys, componentRuntime[StateChangeSlice.Spec.name], opts);
|
|
277
|
+
let ch = StateChangeSlice.make(dcbEventLog, asyncPublishJsons, effectiveTagKeysByEventType, effectiveCrossPartitionTagKeys, DcbTag$Reventless.slicePartitionTag(boundaryPartition, StateChangeSlice.Spec.name), componentRuntime[StateChangeSlice.Spec.name], opts);
|
|
290
278
|
return [
|
|
291
279
|
StateChangeSlice.Spec.name,
|
|
292
280
|
Component$ReventlessCore.outputs(ch)
|
|
@@ -318,7 +306,7 @@ function Make(DcbEventLogStorage) {
|
|
|
318
306
|
if (ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema)) {
|
|
319
307
|
return;
|
|
320
308
|
}
|
|
321
|
-
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(ops.publishJsons, ops.publishJsonsAndWait, S.Spec.name, S.Spec.commandSchema, "StateChangeSlice", false);
|
|
309
|
+
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(ops.publishJsons, ops.publishJsonsAndWait, S.Spec.name, S.Spec.commandSchema, "StateChangeSlice", false, DcbTag$Reventless.slicePartitionTag(boundaryPartition, S.Spec.name));
|
|
322
310
|
Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema).forEach(param => bindHandler(param[0], generateCommand));
|
|
323
311
|
});
|
|
324
312
|
});
|
|
@@ -329,7 +317,7 @@ function Make(DcbEventLogStorage) {
|
|
|
329
317
|
if (ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema)) {
|
|
330
318
|
return;
|
|
331
319
|
}
|
|
332
|
-
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(asyncOps.publishJsons, asyncOps.publishJsonsAndWait, S.Spec.name, S.Spec.commandSchema, "StateChangeSlice", false);
|
|
320
|
+
let generateCommand = CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(asyncOps.publishJsons, asyncOps.publishJsonsAndWait, S.Spec.name, S.Spec.commandSchema, "StateChangeSlice", false, DcbTag$Reventless.slicePartitionTag(boundaryPartition, S.Spec.name));
|
|
333
321
|
Api_Naming$ReventlessCore.sliceMutationFields(apiNamePrefix, S.Spec.name, commandSchema).forEach(param => bindHandler(param[0], generateCommand));
|
|
334
322
|
});
|
|
335
323
|
});
|
|
@@ -437,7 +425,10 @@ function Make(DcbEventLogStorage) {
|
|
|
437
425
|
if (match !== undefined) {
|
|
438
426
|
return log.error("Dcb_Builder", undefined, `Two DCB slices in "` + name + `" both declare the command "` + tag + `". ` + "Owner stamping resolves a command by that name alone, so it cannot tell them apart. Rename one of the constructors.");
|
|
439
427
|
} else {
|
|
440
|
-
byTag[tag] =
|
|
428
|
+
byTag[tag] = [
|
|
429
|
+
commandSchema,
|
|
430
|
+
DcbTag$Reventless.slicePartitionTag(boundaryPartition, S.Spec.name)
|
|
431
|
+
];
|
|
441
432
|
return;
|
|
442
433
|
}
|
|
443
434
|
});
|
|
@@ -445,14 +436,15 @@ function Make(DcbEventLogStorage) {
|
|
|
445
436
|
}
|
|
446
437
|
});
|
|
447
438
|
let dcbGenerateCommandOutput = Component$ReventlessCore.operations(dcbCommandTopic).apply(ops => {
|
|
448
|
-
let make = commandSchema => CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(ops.publishJsons, ops.publishJsonsAndWait, name, commandSchema, "StateChangeSlice", false);
|
|
439
|
+
let make = (commandSchema, partitionTag) => CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(ops.publishJsons, ops.publishJsonsAndWait, name, commandSchema, "StateChangeSlice", false, partitionTag);
|
|
449
440
|
let byTag$1 = {};
|
|
450
441
|
Object.entries(byTag).forEach(param => {
|
|
451
|
-
|
|
442
|
+
let match = param[1];
|
|
443
|
+
byTag$1[param[0]] = make(match[0], match[1]);
|
|
452
444
|
});
|
|
453
445
|
return [
|
|
454
446
|
byTag$1,
|
|
455
|
-
make(Sury.json)
|
|
447
|
+
make(Sury.json, undefined)
|
|
456
448
|
];
|
|
457
449
|
});
|
|
458
450
|
let dcbHandler = Pulumi.all([
|
|
@@ -693,7 +685,6 @@ function Make(DcbEventLogStorage) {
|
|
|
693
685
|
|
|
694
686
|
export {
|
|
695
687
|
log,
|
|
696
|
-
toRelativePath,
|
|
697
688
|
variantTag,
|
|
698
689
|
mergedEventSchema,
|
|
699
690
|
emptyResult,
|
|
@@ -33,6 +33,8 @@ module type T = {
|
|
|
33
33
|
clause (instead of an AND-ed composite) so the decision read is a real
|
|
34
34
|
secondary-tag read. */
|
|
35
35
|
~crossPartitionTagKeys: array<string>=?,
|
|
36
|
+
/** This slice's partition, as `Dcb_Builder` derives it for the whole boundary. */
|
|
37
|
+
~partitionTag: Reventless.DcbTag.derivedPartitionTag=?,
|
|
36
38
|
~runtime: ReventlessInfra.RuntimeHints.t=?,
|
|
37
39
|
~opts: Pulumi.ComponentResource.options=?,
|
|
38
40
|
) => component
|
|
@@ -13,6 +13,7 @@ module Make = (
|
|
|
13
13
|
let makeJsonHandler = (
|
|
14
14
|
~tagKeysByEventType,
|
|
15
15
|
~crossPartitionTagKeys,
|
|
16
|
+
~partitionTag,
|
|
16
17
|
dcbEventLogOps: DcbEventLog.operations,
|
|
17
18
|
) => {
|
|
18
19
|
let handler: CommandTopic.jsonCommandsHandler = stream => {
|
|
@@ -42,6 +43,7 @@ module Make = (
|
|
|
42
43
|
Callback.handleCommands(
|
|
43
44
|
~tagKeysByEventType,
|
|
44
45
|
~crossPartitionTagKeys,
|
|
46
|
+
~partitionTag?,
|
|
45
47
|
dcbEventLogOps,
|
|
46
48
|
decodedStream,
|
|
47
49
|
)
|
|
@@ -54,6 +56,7 @@ module Make = (
|
|
|
54
56
|
~publishJsons: Pulumi.Output.t<CommandTopic.publishJsons>,
|
|
55
57
|
~tagKeysByEventType,
|
|
56
58
|
~crossPartitionTagKeys,
|
|
59
|
+
~partitionTag,
|
|
57
60
|
self,
|
|
58
61
|
_name,
|
|
59
62
|
) => {
|
|
@@ -67,6 +70,7 @@ module Make = (
|
|
|
67
70
|
let jsonHandler = makeJsonHandler(
|
|
68
71
|
~tagKeysByEventType,
|
|
69
72
|
~crossPartitionTagKeys,
|
|
73
|
+
~partitionTag,
|
|
70
74
|
dcbEventLogOps,
|
|
71
75
|
)
|
|
72
76
|
CommandTopic.registerHandler(
|
|
@@ -98,6 +102,7 @@ module Make = (
|
|
|
98
102
|
~publishJsons,
|
|
99
103
|
~tagKeysByEventType=Dict.make(),
|
|
100
104
|
~crossPartitionTagKeys=[],
|
|
105
|
+
~partitionTag=?,
|
|
101
106
|
~runtime as _=?,
|
|
102
107
|
~opts=?,
|
|
103
108
|
): StateChangeSlice.component =>
|
|
@@ -109,6 +114,7 @@ module Make = (
|
|
|
109
114
|
~publishJsons,
|
|
110
115
|
~tagKeysByEventType,
|
|
111
116
|
~crossPartitionTagKeys,
|
|
117
|
+
~partitionTag,
|
|
112
118
|
...
|
|
113
119
|
),
|
|
114
120
|
~opts,
|
|
@@ -18,7 +18,7 @@ let log = Logger$ReventlessCore.fromEnv();
|
|
|
18
18
|
function Make(Spec) {
|
|
19
19
|
return Behavior => {
|
|
20
20
|
let Callback = StateChangeSlice_Callback$ReventlessCore.Make(Spec)(Behavior);
|
|
21
|
-
let makeJsonHandler = (tagKeysByEventType, crossPartitionTagKeys, dcbEventLogOps) => (stream => {
|
|
21
|
+
let makeJsonHandler = (tagKeysByEventType, crossPartitionTagKeys, partitionTag, dcbEventLogOps) => (stream => {
|
|
22
22
|
let decodedStream = Stream.flatMap(Stream.mapEffect(stream, param => {
|
|
23
23
|
let reference = param.reference;
|
|
24
24
|
let json = param.command;
|
|
@@ -44,16 +44,16 @@ function Make(Spec) {
|
|
|
44
44
|
return Stream.empty;
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
|
-
return Callback.handleCommands(tagKeysByEventType, crossPartitionTagKeys, dcbEventLogOps, decodedStream);
|
|
47
|
+
return Callback.handleCommands(tagKeysByEventType, crossPartitionTagKeys, partitionTag, dcbEventLogOps, decodedStream);
|
|
48
48
|
});
|
|
49
|
-
let make = (dcbEventLog, publishJsons, tagKeysByEventTypeOpt, crossPartitionTagKeysOpt, param, opts) => {
|
|
49
|
+
let make = (dcbEventLog, publishJsons, tagKeysByEventTypeOpt, crossPartitionTagKeysOpt, partitionTag, param, opts) => {
|
|
50
50
|
let tagKeysByEventType = tagKeysByEventTypeOpt !== undefined ? tagKeysByEventTypeOpt : ({});
|
|
51
51
|
let crossPartitionTagKeys = crossPartitionTagKeysOpt !== undefined ? crossPartitionTagKeysOpt : [];
|
|
52
52
|
return Component$ReventlessCore.make(ComponentType$ReventlessCore.toString(StateChangeSlice$ReventlessCore.componentType), Spec.name, (extra, extra$1) => {
|
|
53
53
|
let commandSchema = Spec.commandSchema;
|
|
54
54
|
let commandTypeNames = CommandTopic$ReventlessCore.extractTypeNamesFromSchema(commandSchema);
|
|
55
55
|
Component$ReventlessCore.operations(dcbEventLog).apply(dcbEventLogOps => {
|
|
56
|
-
let jsonHandler = makeJsonHandler(tagKeysByEventType, crossPartitionTagKeys, dcbEventLogOps);
|
|
56
|
+
let jsonHandler = makeJsonHandler(tagKeysByEventType, crossPartitionTagKeys, partitionTag, dcbEventLogOps);
|
|
57
57
|
CommandTopic$ReventlessCore.registerHandler(commandSchema, jsonHandler, commandTypeNames);
|
|
58
58
|
});
|
|
59
59
|
Component$ReventlessCore.setOperations(extra, publishJsons.apply(publishJsons => ({
|