@reventlessdev/reventless-core 3.0.0-alpha.208 → 3.0.0-alpha.209
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 +10 -0
- package/package.json +3 -3
- package/src/admin/Platform_Admin.res.mjs +1 -1
- package/src/components/Aggregate/Aggregate_Builder.res +12 -6
- package/src/components/Aggregate/Aggregate_Builder.res.mjs +17 -15
- package/src/components/Dcb/Dcb_Builder.res +21 -1
- package/src/components/Dcb/Dcb_Builder.res.mjs +4 -2
- package/src/plugin/component/Plugin_Builder.res +3 -0
- package/src/plugin/component/Plugin_Builder.res.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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.209 (2026-08-03)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **aws:** give slice command publishes a queue they can actually reach ([42fdb55](https://github.com/ReventlessDev/reventless-core/commit/42fdb55b751a197d586c49e3615ce12ffea42046))
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **dcb:** route an outbound slice's command to the aggregate it targets ([897b37b](https://github.com/ReventlessDev/reventless-core/commit/897b37b46a4e856567646dfdc2f0652e81cf7388))
|
|
14
|
+
|
|
15
|
+
|
|
6
16
|
# 3.0.0-alpha.208 (2026-08-03)
|
|
7
17
|
|
|
8
18
|
### Bug Fixes
|
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.209",
|
|
4
4
|
"description": "Core package for Reventless framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"jest": {
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"uuid": "^13.0.0",
|
|
31
31
|
"@reventlessdev/rescript-effect": "0.1.0-alpha.32",
|
|
32
32
|
"@reventlessdev/rescript-fast-csv": "2.0.0-alpha.1",
|
|
33
|
-
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
34
33
|
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.14",
|
|
34
|
+
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
35
35
|
"@reventlessdev/rescript-node": "2.0.0-alpha.1",
|
|
36
36
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.18",
|
|
37
37
|
"@reventlessdev/rescript-ssh2": "2.0.0-alpha.1",
|
|
38
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.124",
|
|
39
38
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
39
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.124",
|
|
40
40
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.30",
|
|
41
41
|
"@reventlessdev/reventless-spec": "3.0.0-alpha.99"
|
|
42
42
|
},
|
|
@@ -78,7 +78,7 @@ function Make(RuntimeEnvironment) {
|
|
|
78
78
|
A.Spec.eventSchema
|
|
79
79
|
]);
|
|
80
80
|
Plugin_Helpers$ReventlessCore.registerAdminAggregateMutations(aggregates, Config.hooks);
|
|
81
|
-
let dcbResult = DcbBuilder.construct(Platform_Admin_Structure$ReventlessCore.pluginId, Platform_Admin_Structure$ReventlessCore.pluginId, "Platform", true, undefined, undefined, aggregateEventTopics, aggregateProducedEvents, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, undefined, undefined, undefined, opts);
|
|
81
|
+
let dcbResult = DcbBuilder.construct(Platform_Admin_Structure$ReventlessCore.pluginId, Platform_Admin_Structure$ReventlessCore.pluginId, "Platform", true, undefined, undefined, aggregateEventTopics, aggregateProducedEvents, undefined, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, undefined, undefined, undefined, opts);
|
|
82
82
|
let slicePublishJsons = dcbResult.dcbPublishJsons;
|
|
83
83
|
if (slicePublishJsons !== undefined) {
|
|
84
84
|
stateChangeSlices.forEach(Sc => {
|
|
@@ -66,7 +66,17 @@ module Make = (
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
let createCommandTopic = (eventLog: SpecificEventLog.component, name, opts, ~memorySize, ~timeout) =>
|
|
69
|
+
let createCommandTopic = (eventLog: SpecificEventLog.component, name, opts, ~memorySize, ~timeout) => {
|
|
70
|
+
// Created outside the apply below, so the topic — and with it the channel's
|
|
71
|
+
// queue — exists while plugin construction is still synchronous. An outbound
|
|
72
|
+
// slice targeting this aggregate resolves its publish queue in a finalizer
|
|
73
|
+
// that runs before any Output settles; a queue created inside the apply is
|
|
74
|
+
// invisible there. Only the handler needs the event log's operations.
|
|
75
|
+
let commandTopic = SpecificCommandTopic.make(
|
|
76
|
+
~name,
|
|
77
|
+
~owner={kind: ComponentType.Aggregate, name: Spec.name},
|
|
78
|
+
~opts,
|
|
79
|
+
)
|
|
70
80
|
eventLog
|
|
71
81
|
->Component.operations
|
|
72
82
|
->Pulumi.Output.apply(eventLogOps => {
|
|
@@ -79,11 +89,6 @@ module Make = (
|
|
|
79
89
|
let eventLog = eventLogOps
|
|
80
90
|
},
|
|
81
91
|
)
|
|
82
|
-
let commandTopic = SpecificCommandTopic.make(
|
|
83
|
-
~name,
|
|
84
|
-
~owner={kind: ComponentType.Aggregate, name: Spec.name},
|
|
85
|
-
~opts,
|
|
86
|
-
)
|
|
87
92
|
let handler = SpecificCommandTopic.makeHandler(
|
|
88
93
|
~commandTopic,
|
|
89
94
|
~commandsHandler=AggregateCallback.handleCommands,
|
|
@@ -98,6 +103,7 @@ module Make = (
|
|
|
98
103
|
)
|
|
99
104
|
commandTopic
|
|
100
105
|
})
|
|
106
|
+
}
|
|
101
107
|
|
|
102
108
|
let createCommandGenerator = (
|
|
103
109
|
commandTopic: Pulumi.Output.t<SpecificCommandTopic.component>,
|
|
@@ -30,25 +30,27 @@ function Make(Spec) {
|
|
|
30
30
|
Id: Spec.Id,
|
|
31
31
|
commandSchema: Spec.commandSchema
|
|
32
32
|
})(SpecificEventCollector)(EventMappings)(AggregateRuntimeBuilder);
|
|
33
|
-
let createCommandTopic = (eventLog, name, opts, memorySize, timeout) =>
|
|
34
|
-
let AggregateCallback = Aggregate_Callback$ReventlessCore.Make(Spec)(Behavior)({
|
|
35
|
-
Spec: Spec,
|
|
36
|
-
EventLog: SpecificEventLog,
|
|
37
|
-
eventLog: eventLogOps
|
|
38
|
-
});
|
|
33
|
+
let createCommandTopic = (eventLog, name, opts, memorySize, timeout) => {
|
|
39
34
|
let commandTopic = SpecificCommandTopic.make(name, {
|
|
40
35
|
kind: "Aggregate",
|
|
41
36
|
name: Spec.name
|
|
42
37
|
}, opts);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
return Component$ReventlessCore.operations(eventLog).apply(eventLogOps => {
|
|
39
|
+
let AggregateCallback = Aggregate_Callback$ReventlessCore.Make(Spec)(Behavior)({
|
|
40
|
+
Spec: Spec,
|
|
41
|
+
EventLog: SpecificEventLog,
|
|
42
|
+
eventLog: eventLogOps
|
|
43
|
+
});
|
|
44
|
+
let handler = SpecificCommandTopic.makeHandler(commandTopic, AggregateCallback.handleCommands);
|
|
45
|
+
let eventLog$1 = Component$ReventlessCore.outputs(eventLog);
|
|
46
|
+
let resources = [
|
|
47
|
+
eventLog$1.resources,
|
|
48
|
+
eventLog$1.eventTopic.resources
|
|
49
|
+
].flat();
|
|
50
|
+
AggregateRuntimeBuilder.forCommandTopic(handler, none => SpecificCommandTopic.connect(none, resources, commandTopic), memorySize, timeout, commandTopic);
|
|
51
|
+
return commandTopic;
|
|
52
|
+
});
|
|
53
|
+
};
|
|
52
54
|
let createCommandGenerator = (commandTopic, api, name, opts, memorySize, timeout) => Output$Pulumi.flatMap(commandTopic, commandTopic => Component$ReventlessCore.operations(commandTopic).apply(param => {
|
|
53
55
|
let publishJsonsAndWait = param.publishJsonsAndWait;
|
|
54
56
|
let publishJsons = param.publishJsons;
|
|
@@ -94,6 +94,17 @@ module Make = (
|
|
|
94
94
|
// also drives DCB GSI creation: an aggregate's events live on its own
|
|
95
95
|
// EventLog and must not mint indexes on the DCB table.
|
|
96
96
|
~aggregateProducedEvents: array<(string, S.t<unknown>)>=[],
|
|
97
|
+
// Per-aggregate command publishers, keyed by Aggregate `Spec.name`. An
|
|
98
|
+
// OutboundTranslationSlice naming one in `targetName` publishes its command
|
|
99
|
+
// through that aggregate's CommandTopic instead of this plugin's DCB topic —
|
|
100
|
+
// the two are handled by different Lambdas, so sending an aggregate command
|
|
101
|
+
// to the DCB queue delivers it somewhere nothing handles it.
|
|
102
|
+
//
|
|
103
|
+
// Populated before this runs (`createAggregatesWithoutEventMappers`), so the
|
|
104
|
+
// publisher is in hand by the time a slice is built. DCB StateChangeSlice
|
|
105
|
+
// publishers are registered *after* and are deliberately absent: a slice
|
|
106
|
+
// targeting one wants the DCB topic, which is the fallback.
|
|
107
|
+
~publishToAggregates: dict<Pulumi.Output.t<CommandTopic.publishJsons>>=Dict.make(),
|
|
97
108
|
~stateChangeSlices: array<module(StateChangeSlice.T)>,
|
|
98
109
|
~stateViewSlices: array<module(StateViewSlice.T)>,
|
|
99
110
|
~automationSlices: array<module(AutomationSlice.T)>,
|
|
@@ -629,12 +640,21 @@ module Make = (
|
|
|
629
640
|
let outboundTranslationSlicesOutputs =
|
|
630
641
|
outboundTranslationSlices
|
|
631
642
|
->Array.map((module(OTS: OutboundTranslationSlice.T)) => {
|
|
643
|
+
// Where this slice's inbound command goes. `targetName` naming an
|
|
644
|
+
// Aggregate routes to that aggregate's CommandTopic; anything else —
|
|
645
|
+
// a DCB slice, or no target at all — keeps the plugin's DCB topic,
|
|
646
|
+
// which is what every slice wanted before aggregates were reachable.
|
|
647
|
+
let targetPublishJsons =
|
|
648
|
+
OTS.Spec.targetName
|
|
649
|
+
->Option.flatMap(target => publishToAggregates->Dict.get(target))
|
|
650
|
+
->Option.getOr(publishJsons)
|
|
651
|
+
|
|
632
652
|
let ots = OTS.make(
|
|
633
653
|
~dcbEventLog,
|
|
634
654
|
// Same dict the AutomationSlices get, so an outbound slice can
|
|
635
655
|
// name an Aggregate source by its Spec.name.
|
|
636
656
|
~allEventTopics,
|
|
637
|
-
~publishJsons,
|
|
657
|
+
~publishJsons=targetPublishJsons,
|
|
638
658
|
~runtime=?componentRuntime->Dict.get(OTS.Spec.name),
|
|
639
659
|
~opts,
|
|
640
660
|
)
|
|
@@ -83,13 +83,14 @@ let emptyResult = {
|
|
|
83
83
|
|
|
84
84
|
function Make(DcbEventLogStorage) {
|
|
85
85
|
return DcbEventTopicPublisher => (DcbCommandTopicChannel => (DcbCommandTopicChannelAsync => (RuntimeBuilder => (HooksConfig => {
|
|
86
|
-
let construct = (name, childName, apiNamePrefixOpt, onAdminApiOpt, environmentOpt, platformNameOpt, aggregateEventTopicsOpt, aggregateProducedEventsOpt, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponentsOpt, componentRuntimeOpt, pluginStructure, opts) => {
|
|
86
|
+
let construct = (name, childName, apiNamePrefixOpt, onAdminApiOpt, environmentOpt, platformNameOpt, aggregateEventTopicsOpt, aggregateProducedEventsOpt, publishToAggregatesOpt, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponentsOpt, componentRuntimeOpt, pluginStructure, opts) => {
|
|
87
87
|
let apiNamePrefix = apiNamePrefixOpt !== undefined ? apiNamePrefixOpt : name;
|
|
88
88
|
let onAdminApi = onAdminApiOpt !== undefined ? onAdminApiOpt : false;
|
|
89
89
|
let environment = environmentOpt !== undefined ? environmentOpt : "";
|
|
90
90
|
let platformName = platformNameOpt !== undefined ? platformNameOpt : "";
|
|
91
91
|
let aggregateEventTopics = aggregateEventTopicsOpt !== undefined ? aggregateEventTopicsOpt : ({});
|
|
92
92
|
let aggregateProducedEvents = aggregateProducedEventsOpt !== undefined ? aggregateProducedEventsOpt : [];
|
|
93
|
+
let publishToAggregates = publishToAggregatesOpt !== undefined ? publishToAggregatesOpt : ({});
|
|
93
94
|
let systemCallableComponents = systemCallableComponentsOpt !== undefined ? systemCallableComponentsOpt : [];
|
|
94
95
|
let componentRuntime = componentRuntimeOpt !== undefined ? componentRuntimeOpt : ({});
|
|
95
96
|
let hasDcb = stateChangeSlices.length !== 0;
|
|
@@ -330,7 +331,8 @@ function Make(DcbEventLogStorage) {
|
|
|
330
331
|
];
|
|
331
332
|
}));
|
|
332
333
|
let outboundTranslationSlicesOutputs = Object.fromEntries(outboundTranslationSlices.map(OTS => {
|
|
333
|
-
let
|
|
334
|
+
let targetPublishJsons = Stdlib_Option.getOr(Stdlib_Option.flatMap(OTS.Spec.targetName, target => publishToAggregates[target]), publishJsons);
|
|
335
|
+
let ots = OTS.make(dcbEventLog, allEventTopics, targetPublishJsons, componentRuntime[OTS.Spec.name], opts);
|
|
334
336
|
return [
|
|
335
337
|
OTS.Spec.name,
|
|
336
338
|
Component$ReventlessCore.outputs(ots)
|
|
@@ -168,6 +168,9 @@ module Make = (
|
|
|
168
168
|
~platformName=Spec.platformName,
|
|
169
169
|
~aggregateEventTopics,
|
|
170
170
|
~aggregateProducedEvents,
|
|
171
|
+
// Carries the aggregate publishers registered just above, so an outbound
|
|
172
|
+
// slice can route its command to the aggregate it names.
|
|
173
|
+
~publishToAggregates,
|
|
171
174
|
~stateChangeSlices,
|
|
172
175
|
~stateViewSlices,
|
|
173
176
|
~automationSlices,
|
|
@@ -156,7 +156,7 @@ function Make(Spec) {
|
|
|
156
156
|
let DcbBuilder = Dcb_Builder$ReventlessCore.Make(DcbEventLogStorage)(DcbEventTopicPublisher)(DcbCommandTopicChannel)(DcbCommandTopicChannelAsync)(PluginRuntimeBuilder)({
|
|
157
157
|
hooks: Spec.hooks
|
|
158
158
|
});
|
|
159
|
-
let dcbResult = DcbBuilder.construct(extra$1, childName, undefined, undefined, Spec.environment, Spec.platformName, aggregateEventTopics, aggregateProducedEvents, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponents, componentRuntime, pluginStructure, opts);
|
|
159
|
+
let dcbResult = DcbBuilder.construct(extra$1, childName, undefined, undefined, Spec.environment, Spec.platformName, aggregateEventTopics, aggregateProducedEvents, Plugin_Helpers$ReventlessCore.publishToAggregates, stateChangeSlices, stateViewSlices, automationSlices, outboundTranslationSlices, inboundTranslationSlices, systemCallableComponents, componentRuntime, pluginStructure, opts);
|
|
160
160
|
let mutationEntriesFromAggregates = aggregates.flatMap(M => {
|
|
161
161
|
let commandSchema = M.Spec.commandSchema;
|
|
162
162
|
if (ApiNoApiHelpers$ReventlessCore.isNoApi(commandSchema)) {
|