@reventlessdev/reventless-core 3.0.0-alpha.260 → 3.0.0-alpha.261
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 +8 -0
- package/package.json +9 -9
- package/src/Behavior.res +1 -4
- package/src/Message.res +17 -14
- package/src/Projection.res +51 -25
- package/src/RequestContext.res +8 -9
- package/src/ResourceAttribution.res +28 -14
- package/src/adapter/Adapter.res +48 -4
- package/src/adapter/EventLogProvisioning/EventLogProvisioning.res +5 -5
- package/src/adapter/Messaging/Messaging_Log_Backend.res +10 -7
- package/src/adapter/Messaging/Messaging_Log_Backend.res.mjs +2 -4
- package/src/adapter/Monitoring/Monitoring.res +16 -17
- package/src/adapter/QueryInterception/QueryInterception.res +0 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +12 -5
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +11 -7
- package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +1 -7
- package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +1 -7
- package/src/adapter/RuntimeExtension/RuntimeExtension.res +0 -1
- package/src/admin/Platform_Admin.res +17 -6
- package/src/admin/Platform_AdminApi.res +14 -9
- package/src/admin/Platform_Admin_Callback.res +1 -1
- package/src/admin/Platform_BakedManifest.res +34 -34
- package/src/admin/Platform_ComponentDefinitionsApi.res +9 -21
- package/src/admin/Platform_PluginStructuresApi.res +15 -12
- package/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry.res +1 -1
- package/src/components/Aggregate/Aggregate.res +13 -12
- package/src/components/Aggregate/Aggregate_Builder.res +22 -21
- package/src/components/Aggregate/Aggregate_Callback.res +91 -86
- package/src/components/Api/ApiNoApiHelpers.res +1 -3
- package/src/components/Api/Api_Ids.res +0 -1
- package/src/components/Api/Api_Naming.res +41 -18
- package/src/components/Api/GraphQL_FragmentGenerator.res +38 -51
- package/src/components/Api/GraphQL_SchemaInspector.res +5 -3
- package/src/components/Api/GraphQL_Stitcher.res +9 -10
- package/src/components/Api/MCP_SchemaGenerator.res +8 -12
- package/src/components/Api/OwnerScopeDiagnostics.res +1 -2
- package/src/components/Api/QueryDbListQuery.res +13 -6
- package/src/components/Api/SchemaType.res +28 -23
- package/src/components/Api/SuryToJsonSchema.res +9 -10
- package/src/components/AutomationSlice/AutomationSlice.res +4 -4
- package/src/components/AutomationSlice/AutomationSlice_Builder.res +15 -14
- package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -3
- package/src/components/Builder_Helpers.res +12 -23
- package/src/components/CommandGenerator/CommandGenerator.res +6 -1
- package/src/components/CommandGenerator/CommandGenerator_Builder.res +29 -21
- package/src/components/CommandGenerator/CommandGenerator_Callback.res +17 -21
- package/src/components/CommandTopic/CommandTopic.res +3 -3
- package/src/components/CommandTopic/CommandTopic_Builder.res +10 -10
- package/src/components/CommandTopic/CommandTopic_Callback.res +1 -4
- package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -2
- package/src/components/Counter/Counter_Builder.res +1 -6
- package/src/components/Counter/Counter_Callback.res +3 -3
- package/src/components/Dcb/Dcb_Builder.res +970 -956
- package/src/components/DcbEventLog/DcbEventLog.res +4 -4
- package/src/components/DcbEventLog/DcbEventLog_Builder.res +0 -1
- package/src/components/DcbEventLog/DcbEventLog_Operations.res +17 -18
- package/src/components/EventCollector/EventCollector_Builder.res +2 -1
- package/src/components/EventLog/EventLog.res +5 -1
- package/src/components/EventLog/EventLog_Operations.res +12 -8
- package/src/components/EventMapper/EventMapper.res +8 -10
- package/src/components/EventMapper/EventMapper_Builder.res +4 -1
- package/src/components/EventMapper/EventMapper_Callback.res +46 -31
- package/src/components/EventTopic/EventTopic.res +3 -3
- package/src/components/EventTopic/EventTopic_Builder.res +1 -1
- package/src/components/Extension/Extension.res +4 -1
- package/src/components/Extension/Extension_Operations.res +11 -3
- package/src/components/ExtensionPoint/ExtensionPoint.res +3 -3
- package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +9 -10
- package/src/components/ExtensionPoint/ExtensionPoint_Callback.res +2 -6
- package/src/components/ExtensionPoint/ExtensionPoint_Operations.res +13 -5
- package/src/components/Heartbeat/Heartbeat_Callback.res +3 -3
- package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +4 -4
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +7 -10
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +4 -4
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +15 -14
- package/src/components/QueryDb/QueryDb_Adapter.res +1 -3
- package/src/components/QueryDb/QueryDb_Operations.res +10 -10
- package/src/components/ReadModel/ReadModel.res +3 -3
- package/src/components/ReadModel/ReadModel_Builder.res +1 -2
- package/src/components/ReadModel/ReadModel_Callback.res +2 -1
- package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +5 -2
- package/src/components/StateChangeSlice/StateChangeSlice.res +3 -3
- package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +23 -4
- package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +22 -6
- package/src/components/StateTopic.res +1 -3
- package/src/components/StateViewSlice/StateViewSlice.res +4 -4
- package/src/components/StateViewSlice/StateViewSlice_Builder.res +79 -68
- package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
- package/src/components/Task/Task.res +3 -3
- package/src/components/Task/Task_Adapter.res +4 -1
- package/src/components/Task/Task_Builder.res +24 -21
- package/src/plugin/api/PluginBaseFragment.res +9 -3
- package/src/plugin/component/Capability_Inference.res +8 -10
- package/src/plugin/component/Plugin.res +6 -6
- package/src/plugin/component/Plugin_Builder.res +54 -50
- package/src/plugin/component/Plugin_Callback.res +10 -6
- package/src/plugin/component/Plugin_Helpers.res +264 -230
- package/src/plugin/component/Plugin_Structure.res +370 -324
- package/src/plugin/component/Plugin_SubscriptionSchema.res +8 -6
- package/src/plugin/component/SchemaWalker.res +11 -12
- package/src/plugin/connect/PluginConnectExtension_Mapping.res +45 -50
- package/src/plugin/lifecycle/PluginBehavior.res +3 -4
- package/src/plugin/lifecycle/PluginSpec.res +1 -2
- package/src/plugin/lifecycle/PluginsProjection.res +16 -5
- package/src/plugin/lifecycle/PluginsReadModelSpec.res +0 -2
- package/src/util/CommandPublisher.res +9 -2
- package/src/util/CsvStream.res +3 -3
- package/src/util/Interstack.res +7 -15
- package/src/util/Interstack.resi +3 -3
- package/src/util/LogFormat.res +5 -9
- package/src/util/Logger.res +1 -2
- package/src/util/Lru.res +2 -1
- package/src/util/Lru.resi +2 -3
- package/src/util/ScheduleOps.res +24 -27
- package/src/util/StorePrefixCollision.res +6 -9
- package/src/util/Util_Promise.res +4 -1
- package/src/util/Util_Promise.res.mjs +1 -1
- package/tests/IdentityTest.res +166 -113
- package/tests/ResourceAttributionTest.res +28 -25
- package/tests/StorePrefixCollisionTest.res +2 -1
- package/tests/TaskBucketNamingTest.res +3 -2
- package/tests/adapter/EventLogProvisioningTest.res +51 -48
- package/tests/adapter/MonitoringTest.res +81 -38
- package/tests/adapter/QueryInterceptionTest.res +2 -2
- package/tests/adapter/RefusalVocabularyTest.res +31 -23
- package/tests/adapter/RuntimeExtensionHookReachTest.res +9 -8
- package/tests/adapter/RuntimeExtensionTest.res +5 -3
- package/tests/admin/AdminApiSchemaDriftTest.res +22 -16
- package/tests/admin/Platform_Admin_StructureTest.res +10 -11
- package/tests/admin/Platform_BakedManifestTest.res +31 -35
- package/tests/admin/Platform_ComponentDefinitionsApiTest.res +18 -15
- package/tests/admin/Platform_PluginStructuresApiTest.res +5 -3
- package/tests/admin/Platform_UIFragmentsApiTest.res +6 -3
- package/tests/aggregate/AggregateCacheTest.res +10 -12
- package/tests/aggregate/AggregateCallbackTest.res +75 -46
- package/tests/aggregate/AggregateCausationTest.res +19 -20
- package/tests/aggregate/AggregateConflictTest.res +41 -19
- package/tests/aggregate/AggregateFixtures.res +15 -5
- package/tests/aggregate/AggregateRejectionTest.res +97 -80
- package/tests/aggregate/AggregateSnapshotTest.res +44 -16
- package/tests/api/Api_IdsTest.res +10 -4
- package/tests/api/BrandedMarkerCompositionTest.res +48 -36
- package/tests/api/GeolocationSemanticTest.res +3 -3
- package/tests/api/GraphQL_FragmentGeneratorTest.res +66 -54
- package/tests/api/OwnerScopeDiagnosticsTest.res +31 -27
- package/tests/api/StorageRefFieldsTest.res +30 -18
- package/tests/api/SuryToJsonSchemaTest.res +1315 -1014
- package/tests/api/TaggedUnionSchemaTest.res +17 -24
- package/tests/commandgenerator/CommandGeneratorCallbackTest.res +235 -179
- package/tests/commandgenerator/CommandGeneratorFixtures.res +8 -13
- package/tests/commandgenerator/OwnerStampingTest.res +91 -76
- package/tests/commandtopic/CommandOutcomeHookTest.res +198 -155
- package/tests/commandtopic/CommandTopicCallbackFixtures.res +5 -4
- package/tests/commandtopic/CommandTopicCallbackTest.res +61 -43
- package/tests/commandtopic/CommandTopicHelpersRejectionTest.res +70 -55
- package/tests/counter/CounterCallbackTest.res +40 -34
- package/tests/counter/CounterFixtures.res +4 -4
- package/tests/dcb/DcbDecodeTest.res +115 -84
- package/tests/dcb/DcbEventLogOperationsTest.res +194 -143
- package/tests/dcb/DcbEventLogSchemaTest.res +13 -13
- package/tests/dcb/DcbFixtures.res +4 -5
- package/tests/dcb/DcbScopeInferenceTest.res +173 -114
- package/tests/dcb/DcbStateChangeSliceTest.res +391 -262
- package/tests/dcb/DcbTagTest.res +22 -11
- package/tests/dcb/DcbValidationTest.res +288 -218
- package/tests/eventlog/EventLogFixtures.res +4 -4
- package/tests/eventlog/EventLogOperationsTest.res +102 -67
- package/tests/eventlog/EventLogRetryTest.res +104 -65
- package/tests/eventmapper/EventMapperCallbackTest.res +118 -83
- package/tests/eventmapper/EventMapperFixtures.res +15 -23
- package/tests/eventmapper/EventMapperTest.res +54 -38
- package/tests/eventtopic/EventTopicFixtures.res +3 -4
- package/tests/eventtopic/EventTopicOperationsTest.res +41 -29
- package/tests/extensionpoint/ExtensionPointCallbackTest.res +58 -45
- package/tests/extensionpoint/ExtensionPointFixtures.res +16 -20
- package/tests/extensionpoint/ExtensionPointOperationsTest.res +70 -49
- package/tests/extensionpoint/PluginDisconnectScheduleTest.res +2 -1
- package/tests/logger/LogFormatTest.res +104 -82
- package/tests/logger/LoggerLazyTest.res +21 -12
- package/tests/message/MessageTest.res +96 -93
- package/tests/message/MetaEnvelopeTest.res +26 -30
- package/tests/plugin/HeartbeatDisconnectGraceTest.res +31 -25
- package/tests/plugin/ManifestVisibilityTest.res +20 -12
- package/tests/plugin/PluginDefinitionScalars.res +1 -2
- package/tests/plugin/PluginLifecycleCorpusTest.res +15 -12
- package/tests/plugin/PluginSpecExperiment.res +0 -1
- package/tests/plugin/PluginStructureTest.res +1529 -1045
- package/tests/plugin/Plugin_EventQuerySchemaTest.res +21 -10
- package/tests/plugin/SchemaWalkerTest.res +116 -70
- package/tests/plugin/StateChange/PsReserveStock.res +4 -4
- package/tests/plugin/StateView/PsAnnotatedView.res +4 -4
- package/tests/plugin/StateView/PsCustomersView.res +4 -4
- package/tests/plugin/StateView/PsShipmentsView.res +3 -2
- package/tests/projection/LifecycleTrailTest.res +1 -4
- package/tests/projection/ProjectionOptimizeTest.res +13 -9
- package/tests/querydb/QueryDbFixtures.res +0 -1
- package/tests/querydb/QueryDbOperationsTest.res +99 -64
- package/tests/querydb/TaggedUnionStampTest.res +10 -8
- package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res +50 -35
- package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +4 -10
- package/tests/util/CommandPublisherTest.res +0 -1
- package/tests/util/CsvStreamTest.res +3 -3
- package/tests/util/LruTest.res +84 -56
|
@@ -28,8 +28,7 @@ let buildDescriptionSuffix = (
|
|
|
28
28
|
~entry: ReventlessInfra.Api.mutationSchemaEntry,
|
|
29
29
|
): string => {
|
|
30
30
|
let viewsSuffix = switch entry.linkedViews {
|
|
31
|
-
| Some(views) if views->Array.length > 0 =>
|
|
32
|
-
` Affects views: ${views->Array.join(", ")}.`
|
|
31
|
+
| Some(views) if views->Array.length > 0 => ` Affects views: ${views->Array.join(", ")}.`
|
|
33
32
|
| _ => ""
|
|
34
33
|
}
|
|
35
34
|
let consistencySuffix = switch entry.consistencyRead {
|
|
@@ -41,10 +40,9 @@ let buildDescriptionSuffix = (
|
|
|
41
40
|
|
|
42
41
|
/** Generate MCP tool definitions from mutation entries.
|
|
43
42
|
Each command variant becomes a separate tool. */
|
|
44
|
-
let generateTools = (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
): array<mcpToolDefinition> => {
|
|
43
|
+
let generateTools = (~pluginName: string, ~mutationEntries: array<mutationSchemaEntry>): array<
|
|
44
|
+
mcpToolDefinition,
|
|
45
|
+
> => {
|
|
48
46
|
let tools: array<mcpToolDefinition> = []
|
|
49
47
|
|
|
50
48
|
mutationEntries->Array.forEach(entry => {
|
|
@@ -87,8 +85,7 @@ let generateTools = (
|
|
|
87
85
|
obj->Dict.set("required", JSON.Encode.array(arr))
|
|
88
86
|
| None => ()
|
|
89
87
|
}
|
|
90
|
-
| None =>
|
|
91
|
-
obj->Dict.set("required", JSON.Encode.array([JSON.Encode.string("id")]))
|
|
88
|
+
| None => obj->Dict.set("required", JSON.Encode.array([JSON.Encode.string("id")]))
|
|
92
89
|
}
|
|
93
90
|
JSON.Encode.object(obj)
|
|
94
91
|
| None => inputSchema
|
|
@@ -124,10 +121,9 @@ let generateTools = (
|
|
|
124
121
|
|
|
125
122
|
/** Generate MCP resource definitions from query entries.
|
|
126
123
|
Each query entry becomes one or two resources (single + list). */
|
|
127
|
-
let generateResources = (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
): array<mcpResourceDefinition> => {
|
|
124
|
+
let generateResources = (~pluginName: string, ~queryEntries: array<querySchemaEntry>): array<
|
|
125
|
+
mcpResourceDefinition,
|
|
126
|
+
> => {
|
|
131
127
|
let resources: array<mcpResourceDefinition> = []
|
|
132
128
|
|
|
133
129
|
queryEntries->Array.forEach(entry => {
|
|
@@ -43,8 +43,7 @@ let warnIfNoElevatedGroups = (~comp: string, ~view: string, ~ownerField: option<
|
|
|
43
43
|
`${view}: "${field}" is declared @owner, but no elevated groups are configured. ` ++
|
|
44
44
|
"Every caller — administrators included — will see only their own rows. " ++
|
|
45
45
|
"Call OwnerScope.setElevatedGroups([...]) before components are built, or set " ++
|
|
46
|
-
"REVENTLESS_ELEVATED_GROUPS — the environment is what reaches a deployment's " ++
|
|
47
|
-
"separate function runtimes, which a call in the deploy program does not.",
|
|
46
|
+
"REVENTLESS_ELEVATED_GROUPS — the environment is what reaches a deployment's " ++ "separate function runtimes, which a call in the deploy program does not.",
|
|
48
47
|
)
|
|
49
48
|
}
|
|
50
49
|
| _ => ()
|
|
@@ -66,10 +66,14 @@ let buildConnection = (
|
|
|
66
66
|
~cursorValueOf: JSON.t => string,
|
|
67
67
|
): JSON.t => {
|
|
68
68
|
let edges =
|
|
69
|
-
pageItems->Array.map(item =>
|
|
69
|
+
pageItems->Array.map(item =>
|
|
70
|
+
Obj.magic({"node": item, "cursor": encodeCursor(cursorValueOf(item))})
|
|
71
|
+
)
|
|
70
72
|
let startCursor = pageItems->Array.get(0)->Option.map(item => encodeCursor(cursorValueOf(item)))
|
|
71
73
|
let endCursor =
|
|
72
|
-
pageItems
|
|
74
|
+
pageItems
|
|
75
|
+
->Array.get(pageItems->Array.length - 1)
|
|
76
|
+
->Option.map(item => encodeCursor(cursorValueOf(item)))
|
|
73
77
|
Obj.magic({
|
|
74
78
|
"edges": edges,
|
|
75
79
|
"pageInfo": {
|
|
@@ -130,7 +134,7 @@ let run = (
|
|
|
130
134
|
let perFieldChecks: array<JSON.t => bool> = capability.filterFields->Array.flatMap(f => {
|
|
131
135
|
let checks: array<JSON.t => bool> = []
|
|
132
136
|
switch filterDict->Dict.get(f.name ++ "Eq") {
|
|
133
|
-
| Some(v)
|
|
137
|
+
| Some(v) if v != JSON.Encode.null =>
|
|
134
138
|
let expected = switch v->JSON.Decode.string {
|
|
135
139
|
| Some(s) => s
|
|
136
140
|
| None => v->JSON.Decode.float->Option.map(f => Float.toString(f))->Option.getOr("")
|
|
@@ -142,16 +146,18 @@ let run = (
|
|
|
142
146
|
}
|
|
143
147
|
if f.range {
|
|
144
148
|
switch filterDict->Dict.get(f.name ++ "From") {
|
|
145
|
-
| Some(v)
|
|
149
|
+
| Some(v) if v != JSON.Encode.null =>
|
|
146
150
|
let from =
|
|
147
151
|
v
|
|
148
152
|
->JSON.Decode.string
|
|
149
153
|
->Option.getOr(v->JSON.Decode.float->Option.map(f => Float.toString(f))->Option.getOr(""))
|
|
150
|
-
checks->Array.push(item =>
|
|
154
|
+
checks->Array.push(item =>
|
|
155
|
+
getFieldString(item, f.name)->Option.mapOr(false, v => v >= from)
|
|
156
|
+
)
|
|
151
157
|
| _ => ()
|
|
152
158
|
}
|
|
153
159
|
switch filterDict->Dict.get(f.name ++ "To") {
|
|
154
|
-
| Some(v)
|
|
160
|
+
| Some(v) if v != JSON.Encode.null =>
|
|
155
161
|
let to_ =
|
|
156
162
|
v
|
|
157
163
|
->JSON.Decode.string
|
|
@@ -207,6 +213,7 @@ let run = (
|
|
|
207
213
|
item->JSON.Decode.object->Option.flatMap(d => d->Dict.get(scope.field)),
|
|
208
214
|
)
|
|
209
215
|
)
|
|
216
|
+
|
|
210
217
|
| None => true
|
|
211
218
|
}
|
|
212
219
|
passSearch && passPrefix && passIds && passPerField && passOwner && passRetired
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
type rec schemaType =
|
|
2
2
|
| ScalarString
|
|
3
3
|
| ScalarNumber
|
|
4
|
-
|
|
4
|
+
/** A number the schema says is whole. sury carries the fact on the number's
|
|
5
5
|
`format`, and it was being dropped here — so every `int` in the domain
|
|
6
6
|
reached the SDL as `Float` and JSON Schema as `"number"`, and a quantity
|
|
7
7
|
was a field a client could legally send `2.5` in. */
|
|
8
|
-
ScalarInt
|
|
8
|
+
| ScalarInt
|
|
9
9
|
| ScalarBoolean
|
|
10
10
|
| ScalarBigInt
|
|
11
11
|
| EntityId
|
|
12
12
|
| DateTime
|
|
13
|
-
|
|
13
|
+
/** A calendar day, with no instant in it. A shape of its own rather than a
|
|
14
14
|
plain string so `format: "date"` reaches the JSON Schema — but, unlike
|
|
15
15
|
`DateTime`, it is not excluded from the generic semantic wrapper below,
|
|
16
16
|
so it carries `x-reventless-semantic` as well. `DateTime`'s exclusion
|
|
17
17
|
exists because its bare-`format` output predates the marker and is a
|
|
18
18
|
published contract; a new semantic has no such history. */
|
|
19
|
-
CalendarDate
|
|
19
|
+
| CalendarDate
|
|
20
20
|
| Nullable(schemaType)
|
|
21
21
|
| ArrayOf(schemaType)
|
|
22
22
|
| ObjectRef(string, dict<schemaType>)
|
|
23
23
|
| Enum(string, array<string>)
|
|
24
|
-
|
|
24
|
+
/** A field whose type carries a semantic the IR has no dedicated shape for.
|
|
25
25
|
Wraps the shape the value actually has, so every consumer that only cares
|
|
26
26
|
about shape unwraps and is otherwise unaffected. `DateTime` and `EntityId`
|
|
27
27
|
are *not* expressed this way: they long predate the generic marker and
|
|
28
28
|
their JSON Schema `format` output is a published contract. */
|
|
29
|
-
Semantic(Reventless.Semantic.t, schemaType)
|
|
30
|
-
|
|
29
|
+
| Semantic(Reventless.Semantic.t, schemaType)
|
|
30
|
+
/** A field whose type declares the value it opens with. Wraps the shape the
|
|
31
31
|
value has, as `Semantic` does, so a consumer that cares only about shape
|
|
32
32
|
unwraps: a default changes where a form starts, never what the field is. */
|
|
33
|
-
Defaulted(JSON.t, schemaType)
|
|
34
|
-
|
|
33
|
+
| Defaulted(JSON.t, schemaType)
|
|
34
|
+
/** A variant used as a field: the union's name, and one arm per constructor
|
|
35
35
|
keyed by the `TAG` sury discriminates on. Each arm is the `ObjectRef` its
|
|
36
36
|
member type is emitted from, so the arm's own name travels with it and
|
|
37
37
|
every consumer that can already render an object renders an arm.
|
|
38
38
|
|
|
39
39
|
Only a *named* union reaches this case — see `Reventless.TaggedUnion`,
|
|
40
40
|
which owns the name and the arm rules both. */
|
|
41
|
-
TaggedUnion(string, array<(string, schemaType)>)
|
|
41
|
+
| TaggedUnion(string, array<(string, schemaType)>)
|
|
42
42
|
| Unknown
|
|
43
43
|
|
|
44
44
|
let isTagged = Reventless.DcbTag.isTagged
|
|
@@ -96,7 +96,11 @@ let rec fromSury = (~parentName: string, ~fieldName: string, schema: S.t<unknown
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
and withoutDefault = (
|
|
99
|
+
and withoutDefault = (
|
|
100
|
+
~parentName: string,
|
|
101
|
+
~fieldName: string,
|
|
102
|
+
schema: S.t<unknown>,
|
|
103
|
+
): schemaType => {
|
|
100
104
|
// Semantics the IR already has a dedicated shape for keep it: `dateTime` and
|
|
101
105
|
// `reference` are read below via `isDateTime` / `getTarget`, both of which now
|
|
102
106
|
// consult the generic marker, and their `format` output is a published
|
|
@@ -150,9 +154,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
|
|
|
150
154
|
| _ => ScalarString
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
|
-
let itemType =
|
|
154
|
-
|
|
155
|
-
|
|
157
|
+
let itemType =
|
|
158
|
+
(isIdsFieldName(fieldName) || isIdFieldName(fieldName)) && itemType == ScalarString
|
|
159
|
+
? EntityId
|
|
160
|
+
: itemType
|
|
156
161
|
ArrayOf(itemType)
|
|
157
162
|
| Object({properties}) =>
|
|
158
163
|
let nestedName =
|
|
@@ -164,7 +169,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
|
|
|
164
169
|
->Dict.toArray
|
|
165
170
|
->Array.forEach(((propName, propSchema)) => {
|
|
166
171
|
if propName !== "TAG" {
|
|
167
|
-
fields->Dict.set(
|
|
172
|
+
fields->Dict.set(
|
|
173
|
+
propName,
|
|
174
|
+
fromSury(~parentName=nestedName, ~fieldName=propName, propSchema),
|
|
175
|
+
)
|
|
168
176
|
}
|
|
169
177
|
})
|
|
170
178
|
if fields->Dict.keysToArray->Array.length == 0 {
|
|
@@ -181,13 +189,7 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
|
|
|
181
189
|
)
|
|
182
190
|
let isOptional = nonNullVariants->Array.length < anyOf->Array.length
|
|
183
191
|
if nonNullVariants->Array.length == 1 {
|
|
184
|
-
Nullable(
|
|
185
|
-
fromSury(
|
|
186
|
-
~parentName,
|
|
187
|
-
~fieldName,
|
|
188
|
-
nonNullVariants->Array.getUnsafe(0),
|
|
189
|
-
),
|
|
190
|
-
)
|
|
192
|
+
Nullable(fromSury(~parentName, ~fieldName, nonNullVariants->Array.getUnsafe(0)))
|
|
191
193
|
} else {
|
|
192
194
|
let constValues = nonNullVariants->Array.filterMap(v =>
|
|
193
195
|
switch v {
|
|
@@ -195,7 +197,10 @@ and shapeOf = (~parentName: string, ~fieldName: string, schema: S.t<unknown>): s
|
|
|
195
197
|
| _ => None
|
|
196
198
|
}
|
|
197
199
|
)
|
|
198
|
-
if
|
|
200
|
+
if (
|
|
201
|
+
constValues->Array.length == nonNullVariants->Array.length &&
|
|
202
|
+
constValues->Array.length > 0
|
|
203
|
+
) {
|
|
199
204
|
let enumName =
|
|
200
205
|
parentName ++
|
|
201
206
|
fieldName->String.charAt(0)->String.toUpperCase ++
|
|
@@ -13,10 +13,10 @@ let jsonObject = (entries: array<(string, JSON.t)>): JSON.t =>
|
|
|
13
13
|
// An absent plugin means "the declaring plugin's own", which the key's absence
|
|
14
14
|
// says exactly. Writing an empty string instead would make "mine" and "unnamed"
|
|
15
15
|
// indistinguishable to every reader.
|
|
16
|
-
let withOptionalPlugin = (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
)
|
|
16
|
+
let withOptionalPlugin = (entries: array<(string, JSON.t)>, plugin: option<string>): array<(
|
|
17
|
+
string,
|
|
18
|
+
JSON.t,
|
|
19
|
+
)> =>
|
|
20
20
|
switch plugin {
|
|
21
21
|
| Some(p) => entries->Array.concat([("plugin", JSON.Encode.string(p))])
|
|
22
22
|
| None => entries
|
|
@@ -47,8 +47,7 @@ let mergeAnnotations = (
|
|
|
47
47
|
}
|
|
48
48
|
switch spec.indexes->Array.find(((field, _)) => field === fieldName) {
|
|
49
49
|
| Some((_, indexName)) =>
|
|
50
|
-
let value =
|
|
51
|
-
indexName === "" ? JSON.Encode.bool(true) : JSON.Encode.string(indexName)
|
|
50
|
+
let value = indexName === "" ? JSON.Encode.bool(true) : JSON.Encode.string(indexName)
|
|
52
51
|
obj->Dict.set("x-reventless-index", value)
|
|
53
52
|
| None => ()
|
|
54
53
|
}
|
|
@@ -141,10 +140,9 @@ let mergeAnnotations = (
|
|
|
141
140
|
// the keys above follow: false is what every record said before the opt-in
|
|
142
141
|
// existed, and writing it would put a key on every retirement to say
|
|
143
142
|
// nothing changed.
|
|
144
|
-
let entries =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
: entries
|
|
143
|
+
let entries = r.namedWhenRetired
|
|
144
|
+
? Array.concat(entries, [("namedWhenRetired", JSON.Encode.bool(true))])
|
|
145
|
+
: entries
|
|
148
146
|
obj->Dict.set("x-reventless-retired", JSON.Encode.object(Dict.fromArray(entries)))
|
|
149
147
|
| _ => ()
|
|
150
148
|
}
|
|
@@ -428,6 +426,7 @@ and objectRefToJsonSchema = (
|
|
|
428
426
|
| None => withAnnotations
|
|
429
427
|
}
|
|
430
428
|
props->Dict.set(fieldName, withAnnotations)
|
|
429
|
+
|
|
431
430
|
// Optional two ways, because neither source answers alone. `optional` is
|
|
432
431
|
// read off the sury schema and is the only thing that can speak for a
|
|
433
432
|
// reference or a tagged field, which classify as `EntityId` before their
|
|
@@ -5,9 +5,9 @@ type outputs = ReventlessInfra.AutomationSlice.outputs
|
|
|
5
5
|
type operations = ReventlessInfra.AutomationSlice.operations
|
|
6
6
|
type component = Component.t<t, outputs, operations>
|
|
7
7
|
|
|
8
|
-
let toResolvedOutputs = (
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
|
|
9
|
+
ReventlessInterop.AutomationSlice.resolvedOutputs,
|
|
10
|
+
> =>
|
|
11
11
|
(
|
|
12
12
|
outputs.resources->Adapter.resourcesToInterop,
|
|
13
13
|
outputs.queryDb.resources->Adapter.resourcesToInterop,
|
|
@@ -15,7 +15,7 @@ let toResolvedOutputs = (
|
|
|
15
15
|
->Pulumi.Output.all2
|
|
16
16
|
->Pulumi.Output.apply(((resources, queryDbResources)) => {
|
|
17
17
|
let resolved: ReventlessInterop.AutomationSlice.resolvedOutputs = {
|
|
18
|
-
resources
|
|
18
|
+
resources,
|
|
19
19
|
queryDb: {resources: queryDbResources},
|
|
20
20
|
}
|
|
21
21
|
resolved
|
|
@@ -110,8 +110,7 @@ module Make = (
|
|
|
110
110
|
`AutomationSlice "${Spec.name}" has a Mapping with sourceName "${sourceName}", ` ++
|
|
111
111
|
`but no EventTopic with that key exists in allEventTopics. ` ++
|
|
112
112
|
`Available source names: [${availableNames}]. ` ++
|
|
113
|
-
`Check Mapping.Make's first arg matches an Aggregate Spec.name or a DCB ` ++
|
|
114
|
-
`source name (typically "<pluginName>DcbEventLog").`,
|
|
113
|
+
`Check Mapping.Make's first arg matches an Aggregate Spec.name or a DCB ` ++ `source name (typically "<pluginName>DcbEventLog").`,
|
|
115
114
|
)
|
|
116
115
|
}
|
|
117
116
|
)
|
|
@@ -159,18 +158,20 @@ module Make = (
|
|
|
159
158
|
let _ =
|
|
160
159
|
Callback.phase2(publishJsonsFn)
|
|
161
160
|
->Promise.then(() => syncToQueryDb(queryDbOps))
|
|
162
|
-
->Promise.catch(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
161
|
+
->Promise.catch(
|
|
162
|
+
exn => {
|
|
163
|
+
let errMsg =
|
|
164
|
+
exn
|
|
165
|
+
->JsExn.fromException
|
|
166
|
+
->Option.flatMap(JsExn.message)
|
|
167
|
+
->Option.getOr("unknown")
|
|
168
|
+
EffectLogger.logError(
|
|
169
|
+
~comp=`AutomationSlice(${Spec.name})`,
|
|
170
|
+
`detached phase 2 error: ${errMsg}`,
|
|
171
|
+
)->Effect.runSync
|
|
172
|
+
Promise.resolve()
|
|
173
|
+
},
|
|
174
|
+
)
|
|
174
175
|
},
|
|
175
176
|
)
|
|
176
177
|
)
|
|
@@ -172,9 +172,9 @@ module Make = (
|
|
|
172
172
|
handle: (JSON.t, ~sourceId: string, Reventless.AutomationSlice.context) => unit,
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
let dispatches: array<
|
|
176
|
-
|
|
177
|
-
) => {
|
|
175
|
+
let dispatches: array<
|
|
176
|
+
dispatch,
|
|
177
|
+
> = Automation.mappings->Array.map((module(M: Automation.Mapping)) => {
|
|
178
178
|
let decoder = Reventless.DcbDecode.makeDecoder(M.sourceEventSchema)
|
|
179
179
|
let handle = (json: JSON.t, ~sourceId: string, ctx: Reventless.AutomationSlice.context) => {
|
|
180
180
|
let (eventType, dataDict) = json->Message.splitMessage
|
|
@@ -30,14 +30,9 @@ let createAggregatesWithoutEventMappers = (
|
|
|
30
30
|
~opts,
|
|
31
31
|
)
|
|
32
32
|
let aggOutputs = SpecificAggregate.outputs(aggregate)
|
|
33
|
-
addEventMapperFns->Dict.set(
|
|
34
|
-
SpecificAggregate.Spec.name,
|
|
35
|
-
aggOutputs.addEventMapper,
|
|
36
|
-
)
|
|
33
|
+
addEventMapperFns->Dict.set(SpecificAggregate.Spec.name, aggOutputs.addEventMapper)
|
|
37
34
|
let resources =
|
|
38
|
-
aggOutputs.commandTopic->Pulumi.Output.apply(commandTopic =>
|
|
39
|
-
commandTopic.resources
|
|
40
|
-
)
|
|
35
|
+
aggOutputs.commandTopic->Pulumi.Output.apply(commandTopic => commandTopic.resources)
|
|
41
36
|
aggregateResources->Dict.set(SpecificAggregate.Spec.name, resources)
|
|
42
37
|
let publishJsons =
|
|
43
38
|
SpecificAggregate.operations(aggregate)->Pulumi.Output.apply(({publishJsons}) => publishJsons)
|
|
@@ -54,10 +49,7 @@ let createAggregatesWithoutEventMappers = (
|
|
|
54
49
|
->Array.map(aggregate => {(aggregate.name, aggregate)})
|
|
55
50
|
->Dict.fromArray
|
|
56
51
|
|
|
57
|
-
|
|
58
|
-
let finishAggregates = (
|
|
59
|
-
aggregatesOutputs: dict<Aggregate.outputs>,
|
|
60
|
-
) => {
|
|
52
|
+
let finishAggregates = (aggregatesOutputs: dict<Aggregate.outputs>) => {
|
|
61
53
|
let allOutputs = aggregatesOutputs->Dict.valuesToArray
|
|
62
54
|
|
|
63
55
|
// Wait for ALL commandTopicOutputs (not just those with event mappers)
|
|
@@ -89,10 +81,7 @@ let finishAggregates = (
|
|
|
89
81
|
)
|
|
90
82
|
}
|
|
91
83
|
|
|
92
|
-
let addEventMappers = (
|
|
93
|
-
allEventTopics,
|
|
94
|
-
queryEngine,
|
|
95
|
-
) => {
|
|
84
|
+
let addEventMappers = (allEventTopics, queryEngine) => {
|
|
96
85
|
let aggregatesOutputs =
|
|
97
86
|
addEventMapperFns->Dict.mapValues(addEventMapperFn =>
|
|
98
87
|
addEventMapperFn(allEventTopics, queryEngine)
|
|
@@ -126,9 +115,7 @@ let finishTasks = () =>
|
|
|
126
115
|
let _ =
|
|
127
116
|
taskSideEffectGates
|
|
128
117
|
->Pulumi.Output.all
|
|
129
|
-
->Pulumi.Output.apply(_ =>
|
|
130
|
-
taskSideEffectFinishFns->Array.forEach(finishFn => finishFn())
|
|
131
|
-
)
|
|
118
|
+
->Pulumi.Output.apply(_ => taskSideEffectFinishFns->Array.forEach(finishFn => finishFn()))
|
|
132
119
|
}
|
|
133
120
|
|
|
134
121
|
let readModelNamesForSourceName = Dict.make()
|
|
@@ -154,8 +141,7 @@ let extractReadModelsOutputs = readModels =>
|
|
|
154
141
|
->Dict.fromArray
|
|
155
142
|
|
|
156
143
|
let createReadModels = (
|
|
157
|
-
type a,
|
|
158
|
-
type r,
|
|
144
|
+
type a r,
|
|
159
145
|
readModels: array<module(ReventlessInfra.ReadModel.T with type api = a and type role = r)>,
|
|
160
146
|
~api: a,
|
|
161
147
|
~apiRole: r,
|
|
@@ -163,7 +149,9 @@ let createReadModels = (
|
|
|
163
149
|
allEventTopics,
|
|
164
150
|
opts,
|
|
165
151
|
) => {
|
|
166
|
-
let readModels = readModels->Array.map((
|
|
152
|
+
let readModels = readModels->Array.map((
|
|
153
|
+
module(SpecificReadModel: ReventlessInfra.ReadModel.T with type api = a and type role = r),
|
|
154
|
+
) => {
|
|
167
155
|
let readModel = SpecificReadModel.make(
|
|
168
156
|
~api,
|
|
169
157
|
~apiRole,
|
|
@@ -222,8 +210,9 @@ let createExtensionPoints = (
|
|
|
222
210
|
~opts,
|
|
223
211
|
) => {
|
|
224
212
|
let triples =
|
|
225
|
-
extensionPoints
|
|
226
|
-
|
|
213
|
+
extensionPoints->Array.map((
|
|
214
|
+
module(SpecificExtensionPoint: ReventlessInfra.ExtensionPoint.T),
|
|
215
|
+
) => {
|
|
227
216
|
let extensionPoint = SpecificExtensionPoint.make(
|
|
228
217
|
~aggregateResources,
|
|
229
218
|
~publishToAggregates,
|
|
@@ -27,7 +27,12 @@ external asEvent: 'a => event = "%identity"
|
|
|
27
27
|
let metaInfo = event => (event->asEvent).meta->Option.map(({info}) => info)
|
|
28
28
|
|
|
29
29
|
type commandGenerator = payload => Effect.t<CommandTopic.commandOutcome, unit, unit>
|
|
30
|
-
type effectEventHandler<'context> = Runtime.effectHandler<
|
|
30
|
+
type effectEventHandler<'context> = Runtime.effectHandler<
|
|
31
|
+
payload,
|
|
32
|
+
'context,
|
|
33
|
+
CommandTopic.commandOutcome,
|
|
34
|
+
unit,
|
|
35
|
+
>
|
|
31
36
|
|
|
32
37
|
type publishJsons = CommandTopic.publishJsons
|
|
33
38
|
|
|
@@ -1,25 +1,29 @@
|
|
|
1
|
-
module Make = (
|
|
2
|
-
Spec: Reventless.Aggregate.Spec,
|
|
3
|
-
Resolvers: CommandGenerator_Adapter.Resolvers,
|
|
4
|
-
): (
|
|
1
|
+
module Make = (Spec: Reventless.Aggregate.Spec, Resolvers: CommandGenerator_Adapter.Resolvers): (
|
|
5
2
|
CommandGenerator.T with type runtimeParts := Resolvers.runtimeParts and type api := Resolvers.api
|
|
6
3
|
) => {
|
|
7
4
|
let construct = (self, _name) => {
|
|
8
|
-
let resources =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
5
|
+
let resources =
|
|
6
|
+
Plugin_Helpers.aggregateMutationFieldsRegistry
|
|
7
|
+
->Dict.get(Spec.name)
|
|
8
|
+
->Option.getOr([])
|
|
9
|
+
->Array.map(field => {
|
|
10
|
+
let r: ReventlessInfra.Adapter.resource = {
|
|
11
|
+
id: ""->Pulumi.Output.make,
|
|
12
|
+
resourceInfo: ReventlessInfra.Adapter.ApiResolver({
|
|
13
|
+
typeName: "Mutation",
|
|
14
|
+
fieldName: field,
|
|
15
|
+
})->Pulumi.Output.make,
|
|
16
|
+
name: ""->Pulumi.Output.make,
|
|
17
|
+
urn: ""->Pulumi.Output.make,
|
|
18
|
+
service: ""->Pulumi.Output.make,
|
|
19
|
+
role: "commandGenerator"->Pulumi.Output.make,
|
|
20
|
+
region: ""->Pulumi.Output.make,
|
|
21
|
+
resourceType: ""->Pulumi.Output.make,
|
|
22
|
+
configuration: Dict.make()->Pulumi.Output.make,
|
|
23
|
+
tags: Dict.make()->Pulumi.Output.make,
|
|
24
|
+
}
|
|
25
|
+
r
|
|
26
|
+
})
|
|
23
27
|
let outputs: CommandGenerator.outputs = {resources: resources}
|
|
24
28
|
let _ = self->Component.setOutputs(outputs)
|
|
25
29
|
}
|
|
@@ -32,7 +36,8 @@ module Make = (
|
|
|
32
36
|
->ComponentType.name(CommandGenerator.componentType)
|
|
33
37
|
let opts = {Pulumi.ComponentResource.parent: commandGeneratorResource}
|
|
34
38
|
|
|
35
|
-
let fields =
|
|
39
|
+
let fields =
|
|
40
|
+
Plugin_Helpers.aggregateMutationFieldsRegistry->Dict.get(Spec.name)->Option.getOr([])
|
|
36
41
|
|
|
37
42
|
let resolvers = Resolvers.make(
|
|
38
43
|
~name,
|
|
@@ -48,7 +53,10 @@ module Make = (
|
|
|
48
53
|
let _ = commandGenerator->Component.setOutputs(cgOutputs)
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
let makeHandler = (
|
|
56
|
+
let makeHandler = (
|
|
57
|
+
~publishJsons,
|
|
58
|
+
~publishJsonsAndWait: option<CommandTopic.publishJsonsAndWait>,
|
|
59
|
+
) => {
|
|
52
60
|
module Callback = CommandGenerator_Callback.Make(
|
|
53
61
|
{
|
|
54
62
|
let publishJsons = publishJsons
|
|
@@ -168,9 +168,7 @@ let makeGenerateCommand = (
|
|
|
168
168
|
| Some(idValue) => idValue
|
|
169
169
|
| None =>
|
|
170
170
|
try {
|
|
171
|
-
let derived = Reventless.DcbTag.derivePartitionTag([
|
|
172
|
-
(serviceName, "", commandSchema),
|
|
173
|
-
])
|
|
171
|
+
let derived = Reventless.DcbTag.derivePartitionTag([(serviceName, "", commandSchema)])
|
|
174
172
|
switch derived {
|
|
175
173
|
| Simple(pt) =>
|
|
176
174
|
let tags = Reventless.DcbTag.extractTagsFromJson(commandSchema, commandJson)
|
|
@@ -221,22 +219,23 @@ let makeGenerateCommand = (
|
|
|
221
219
|
| Allow =>
|
|
222
220
|
switch publishJsonsAndWait {
|
|
223
221
|
| Some(publishAndWait) =>
|
|
224
|
-
Effect.promise(() => publishAndWait([{id, meta, commandJson}]))
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
222
|
+
Effect.promise(() => publishAndWait([{id, meta, commandJson}]))->Effect.map(
|
|
223
|
+
outcomes => {
|
|
224
|
+
// For aggregates, entityId comes from the envelope id.
|
|
225
|
+
// DCB slices populate entityId via the side-channel; don't override it.
|
|
226
|
+
switch outcomes->Array.getUnsafe(0) {
|
|
227
|
+
| CommandTopic.Accepted(payload) if payload.entityId->Option.isNone =>
|
|
228
|
+
CommandTopic.Accepted({...payload, entityId: id})
|
|
229
|
+
| outcome => outcome
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
)
|
|
234
233
|
| None =>
|
|
235
|
-
Effect.promise(() => publishJsons([{id, meta, commandJson}]))
|
|
236
|
-
|
|
234
|
+
Effect.promise(() => publishJsons([{id, meta, commandJson}]))->Effect.map(
|
|
235
|
+
_ => CommandTopic.Pending({msgId: meta.msgId}),
|
|
236
|
+
)
|
|
237
237
|
}
|
|
238
|
-
| Deny(msg) =>
|
|
239
|
-
JsError.throwWithMessage(msg)
|
|
238
|
+
| Deny(msg) => JsError.throwWithMessage(msg)
|
|
240
239
|
}
|
|
241
240
|
)
|
|
242
241
|
| exception err =>
|
|
@@ -265,10 +264,7 @@ let makeGenerateCommand = (
|
|
|
265
264
|
})
|
|
266
265
|
}
|
|
267
266
|
|
|
268
|
-
module Make = (
|
|
269
|
-
Spec: Spec,
|
|
270
|
-
AggregateSpec: Reventless.Aggregate.Spec,
|
|
271
|
-
): T => {
|
|
267
|
+
module Make = (Spec: Spec, AggregateSpec: Reventless.Aggregate.Spec): T => {
|
|
272
268
|
let generateCommand = makeGenerateCommand(
|
|
273
269
|
~publishJsons=Spec.publishJsons,
|
|
274
270
|
~publishJsonsAndWait=?Spec.publishJsonsAndWait,
|
|
@@ -63,9 +63,9 @@ module type T = {
|
|
|
63
63
|
) => component
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
let toResolvedOutputs = (
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
|
|
67
|
+
ReventlessInterop.CommandTopic.resolvedOutputs,
|
|
68
|
+
> =>
|
|
69
69
|
outputs.resources
|
|
70
70
|
->Adapter.resourcesToInterop
|
|
71
71
|
->Pulumi.Output.apply(resources => {
|
|
@@ -49,21 +49,21 @@ module Make = (Spec: ReventlessInfra.CommandTopic.T, Channel: CommandTopic_Adapt
|
|
|
49
49
|
let handlers = CommandTopic.getHandlers(typeName)
|
|
50
50
|
Effect.promise(async () => {
|
|
51
51
|
let allResults: array<result<string, string>> = []
|
|
52
|
-
let _ =
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
let _ = await handlers
|
|
53
|
+
->Array.map(
|
|
54
|
+
async handlerEntry => {
|
|
55
55
|
let {CommandTopic.handler: handler} = handlerEntry
|
|
56
56
|
try {
|
|
57
|
-
let results =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)->Effect.runPromise
|
|
57
|
+
let results = await handler(
|
|
58
|
+
Stream.fromIterable([{ReventlessInfra.CommandTopic.reference, command: json}]),
|
|
59
|
+
)->Effect.runPromise
|
|
61
60
|
allResults->Array.pushMany(results)
|
|
62
61
|
} catch {
|
|
63
62
|
| _ => () // Skip if handler fails
|
|
64
63
|
}
|
|
65
|
-
}
|
|
66
|
-
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
->Promise.all
|
|
67
67
|
allResults
|
|
68
68
|
})
|
|
69
69
|
})
|
|
@@ -89,7 +89,7 @@ module Make = (Spec: ReventlessInfra.CommandTopic.T, Channel: CommandTopic_Adapt
|
|
|
89
89
|
{
|
|
90
90
|
publish: Operations.publish,
|
|
91
91
|
publishJsons: Operations.publishJsons,
|
|
92
|
-
publishJsonsStream
|
|
92
|
+
publishJsonsStream,
|
|
93
93
|
publishJsonsAndWait,
|
|
94
94
|
}
|
|
95
95
|
}),
|
|
@@ -19,10 +19,7 @@ module Make = (Spec: ReventlessInfra.CommandTopic.T, Ops: Ops with module Spec =
|
|
|
19
19
|
| exception err =>
|
|
20
20
|
let commandStr = json->JSON.stringify
|
|
21
21
|
let errMsg = err->Reventless.Util_Sury.exnMessage
|
|
22
|
-
EffectLogger.logError(
|
|
23
|
-
~comp,
|
|
24
|
-
`decode failed: ${commandStr} err=${errMsg}`,
|
|
25
|
-
)->Effect.runSync
|
|
22
|
+
EffectLogger.logError(~comp, `decode failed: ${commandStr} err=${errMsg}`)->Effect.runSync
|
|
26
23
|
None
|
|
27
24
|
}
|
|
28
25
|
)
|