@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
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
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.261 (2026-09-09)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @reventlessdev/reventless-core
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
# 3.0.0-alpha.260 (2026-09-08)
|
|
7
15
|
|
|
8
16
|
### Features
|
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.261",
|
|
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-effect": "0.1.0-alpha.
|
|
32
|
-
"@reventlessdev/rescript-fast-csv": "2.0.0-alpha.
|
|
31
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.33",
|
|
32
|
+
"@reventlessdev/rescript-fast-csv": "2.0.0-alpha.11",
|
|
33
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.11",
|
|
33
34
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.10",
|
|
34
35
|
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.14",
|
|
35
|
-
"@reventlessdev/rescript-
|
|
36
|
-
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.19",
|
|
37
|
-
"@reventlessdev/rescript-ssh2": "2.0.0-alpha.10",
|
|
36
|
+
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.20",
|
|
38
37
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.0",
|
|
39
|
-
"@reventlessdev/
|
|
40
|
-
"@reventlessdev/reventless-
|
|
41
|
-
"@reventlessdev/reventless-
|
|
38
|
+
"@reventlessdev/rescript-ssh2": "2.0.0-alpha.11",
|
|
39
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.162",
|
|
40
|
+
"@reventlessdev/reventless-interop": "3.0.0-alpha.36",
|
|
41
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.134"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"rescript": "12.3.0",
|
package/src/Behavior.res
CHANGED
|
@@ -12,7 +12,4 @@ module type Spec = {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
type evolve<'state, 'event> = ('state, 'event) => 'state
|
|
15
|
-
type decide<'state, 'command, 'event, 'error> = (
|
|
16
|
-
'state,
|
|
17
|
-
'command,
|
|
18
|
-
) => result<array<'event>, 'error>
|
|
15
|
+
type decide<'state, 'command, 'event, 'error> = ('state, 'command) => result<array<'event>, 'error>
|
package/src/Message.res
CHANGED
|
@@ -83,7 +83,11 @@ let encodeCommand' = (command', idSchema, commandSchema) =>
|
|
|
83
83
|
let uuid = Uuid.v4
|
|
84
84
|
|
|
85
85
|
let log: ('a, string) => 'a = (value, str) => {
|
|
86
|
-
logger.debug(
|
|
86
|
+
logger.debug(
|
|
87
|
+
~comp="Message",
|
|
88
|
+
~data=value->JSON.stringifyAny->Option.getOr("")->JSON.Encode.string,
|
|
89
|
+
str,
|
|
90
|
+
)
|
|
87
91
|
value
|
|
88
92
|
}
|
|
89
93
|
|
|
@@ -205,7 +209,6 @@ let hrtimeToString: (~hrtime: hrtime, ~now: float) => string = (~hrtime, ~now) =
|
|
|
205
209
|
now->Float.toString ++ ("-" ++ (String.repeat("0", 9 - milLength) ++ milString))
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
|
|
209
212
|
let generateMeta = (
|
|
210
213
|
~service,
|
|
211
214
|
~ip=?,
|
|
@@ -222,12 +225,12 @@ let generateMeta = (
|
|
|
222
225
|
time: nowAsISOString(),
|
|
223
226
|
msgId,
|
|
224
227
|
correlationId: correlationId->Option.getOr(msgId),
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
?ip,
|
|
229
|
+
?user,
|
|
230
|
+
?causationId,
|
|
231
|
+
?traceparent,
|
|
232
|
+
?schemaVersion,
|
|
233
|
+
?headers,
|
|
231
234
|
}
|
|
232
235
|
}
|
|
233
236
|
|
|
@@ -332,13 +335,13 @@ let storedEventToFlatJson = (
|
|
|
332
335
|
}
|
|
333
336
|
|
|
334
337
|
/** Decode the flat on-disk JSON shape into a typed `StoredEvent`. */
|
|
335
|
-
let flatJsonToStoredEvent = (
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
): Reventless.StoredEvent.storedEvent<'id> => {
|
|
338
|
+
let flatJsonToStoredEvent = (json: JSON.t, idSchema: S.t<'id>): Reventless.StoredEvent.storedEvent<
|
|
339
|
+
'id,
|
|
340
|
+
> => {
|
|
339
341
|
let dict = json->JSON.Decode.object->Option.getOrThrow
|
|
340
342
|
let id = dict->Dict.get("id")->Option.getOrThrow->Reventless.Util_Sury.fromJson(idSchema)
|
|
341
|
-
let position =
|
|
343
|
+
let position =
|
|
344
|
+
dict->Dict.get("position")->Option.getOrThrow->JSON.Decode.string->Option.getOrThrow
|
|
342
345
|
let event = dict->Dict.get("event")->Option.getOrThrow->JSON.Decode.string->Option.getOrThrow
|
|
343
346
|
let data = dict->Dict.get("data")->Option.getOrThrow
|
|
344
347
|
let recordedAt =
|
|
@@ -348,7 +351,7 @@ let flatJsonToStoredEvent = (
|
|
|
348
351
|
dict
|
|
349
352
|
->Dict.get("tags")
|
|
350
353
|
->Option.map(t => t->Reventless.Util_Sury.fromJson(S.array(Reventless.DcbTag.tagSchema)))
|
|
351
|
-
{id, position, event, data, recordedAt, meta,
|
|
354
|
+
{id, position, event, data, recordedAt, meta, ?tags}
|
|
352
355
|
}
|
|
353
356
|
|
|
354
357
|
// type decoder<'a> = JSON.t => result<'a, Decco.decodeError>
|
package/src/Projection.res
CHANGED
|
@@ -101,8 +101,7 @@ let rewriteActionWith = (
|
|
|
101
101
|
// `Set` opens a trail rather than extending one: it replaces the whole row,
|
|
102
102
|
// the trail included, so there is no prior value left to compare against.
|
|
103
103
|
let created = state => apply(state, ~overlays, ~priorLifecycle=None)
|
|
104
|
-
let updated = (fn, state) =>
|
|
105
|
-
apply(fn(state), ~overlays, ~priorLifecycle=priorLifecycleOf(state))
|
|
104
|
+
let updated = (fn, state) => apply(fn(state), ~overlays, ~priorLifecycle=priorLifecycleOf(state))
|
|
106
105
|
let labelled = state => apply(state, ~overlays={...overlays, trail: None}, ~priorLifecycle=None)
|
|
107
106
|
switch action {
|
|
108
107
|
| Create(id, state) => Create(id, created(state))
|
|
@@ -127,11 +126,10 @@ let rewriteActionWith = (
|
|
|
127
126
|
}
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
let rewriteAction = (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
): action<'id, 'state> =>
|
|
129
|
+
let rewriteAction = (action: action<'id, 'state>, ~at: string, stateSchema: S.t<'state>): action<
|
|
130
|
+
'id,
|
|
131
|
+
'state,
|
|
132
|
+
> =>
|
|
135
133
|
switch overlaysFor(stateSchema->S.castToUnknown) {
|
|
136
134
|
| None => action
|
|
137
135
|
| Some(overlays) =>
|
|
@@ -156,11 +154,10 @@ The rewrite a test harness applies: the trail and nothing else. `displayName`
|
|
|
156
154
|
lives in the state schema and not in the record, so composing it would produce a
|
|
157
155
|
state no expectation can spell.
|
|
158
156
|
*/
|
|
159
|
-
let rewriteTrail = (
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
): action<'id, 'state> =>
|
|
157
|
+
let rewriteTrail = (action: action<'id, 'state>, ~at: string, stateSchema: S.t<'state>): action<
|
|
158
|
+
'id,
|
|
159
|
+
'state,
|
|
160
|
+
> =>
|
|
164
161
|
switch trailOverlays(Some(stateSchema->S.castToUnknown)) {
|
|
165
162
|
| None => action
|
|
166
163
|
| Some(overlays) =>
|
|
@@ -186,7 +183,12 @@ let rewriteJsonAction = (
|
|
|
186
183
|
switch trailOverlays(stateSchema) {
|
|
187
184
|
| None => action
|
|
188
185
|
| Some(overlays) =>
|
|
189
|
-
action->rewriteActionWith(
|
|
186
|
+
action->rewriteActionWith(
|
|
187
|
+
~overlays,
|
|
188
|
+
~at,
|
|
189
|
+
~toDict=JSON.Decode.object,
|
|
190
|
+
~fromDict=JSON.Encode.object,
|
|
191
|
+
)
|
|
190
192
|
}
|
|
191
193
|
|
|
192
194
|
let applyChanges = async (
|
|
@@ -219,8 +221,7 @@ let applyChanges = async (
|
|
|
219
221
|
)
|
|
220
222
|
let changedCount = changedStates->Array.length
|
|
221
223
|
|
|
222
|
-
let batchToSave =
|
|
223
|
-
changedStates->Array.concat(addedStates)->Array.map(state => (id, state, None))
|
|
224
|
+
let batchToSave = changedStates->Array.concat(addedStates)->Array.map(state => (id, state, None))
|
|
224
225
|
|
|
225
226
|
let deletedSubIds = beforeSubIds->Set.diff(afterSubIds)->Set.toArray
|
|
226
227
|
let batchToDelete = deletedSubIds->Array.map(subId => (id, Some((subIdField, subId))))
|
|
@@ -472,39 +473,60 @@ let optimizeActions = actions => {
|
|
|
472
473
|
UpdateWithDefault(id1, g(defaultState1), state => g(f(state))),
|
|
473
474
|
])
|
|
474
475
|
| (UpdateWithDefault(id1, defaultState1, f), Create(id2, _state2)) if id1 == id2 =>
|
|
475
|
-
log.warn(
|
|
476
|
+
log.warn(
|
|
477
|
+
~comp="Projection",
|
|
478
|
+
`optimizing Create after UpdateWithDefault for id=${id1}, ignoring the Create`,
|
|
479
|
+
)
|
|
476
480
|
previousActions->Array.concat([UpdateWithDefault(id1, defaultState1, f)])
|
|
477
481
|
| (Create(id1, state1), Create(id2, state2)) if id1 == id2 =>
|
|
478
482
|
log.warn(
|
|
479
483
|
~comp="Projection",
|
|
480
|
-
`optimizing 2 sequential Create for id=${id1}, ignoring second: ${state2
|
|
484
|
+
`optimizing 2 sequential Create for id=${id1}, ignoring second: ${state2
|
|
485
|
+
->JSON.stringifyAny
|
|
486
|
+
->Option.getOr("?")}`,
|
|
481
487
|
)
|
|
482
488
|
previousActions->Array.concat([Create(id1, state1)])
|
|
483
489
|
| (Create(id1, state1), Delete(id2)) if id1 == id2 =>
|
|
484
490
|
log.warn(
|
|
485
491
|
~comp="Projection",
|
|
486
|
-
`optimizing Delete after Create for id=${id1}, ignoring Create: ${state1
|
|
492
|
+
`optimizing Delete after Create for id=${id1}, ignoring Create: ${state1
|
|
493
|
+
->JSON.stringifyAny
|
|
494
|
+
->Option.getOr("?")}`,
|
|
487
495
|
)
|
|
488
496
|
previousActions->Array.concat([Delete(id1)])
|
|
489
497
|
| (Update(id1, _f), Delete(id2)) if id1 == id2 =>
|
|
490
|
-
log.warn(
|
|
498
|
+
log.warn(
|
|
499
|
+
~comp="Projection",
|
|
500
|
+
`optimizing Delete after Update for id=${id1}, ignoring the Update`,
|
|
501
|
+
)
|
|
491
502
|
previousActions->Array.concat([Delete(id1)])
|
|
492
503
|
| (UpdateWithDefault(id1, _defaultState1, _f), Delete(id2)) if id1 == id2 =>
|
|
493
|
-
log.warn(
|
|
504
|
+
log.warn(
|
|
505
|
+
~comp="Projection",
|
|
506
|
+
`optimizing Delete after UpdateWithDefault for id=${id1}, ignoring the UpdateWithDefault`,
|
|
507
|
+
)
|
|
494
508
|
previousActions->Array.concat([Delete(id1)])
|
|
495
509
|
| (Delete(id1), Create(id2, state2)) if id1 == id2 =>
|
|
496
510
|
previousActions->Array.concat([Set(id1, state2)])
|
|
497
511
|
| (Create(id1, state1), Set(id2, state2)) if id1 == id2 =>
|
|
498
512
|
log.warn(
|
|
499
513
|
~comp="Projection",
|
|
500
|
-
`optimizing Set after Create for id=${id1}, ignoring Create: ${state1
|
|
514
|
+
`optimizing Set after Create for id=${id1}, ignoring Create: ${state1
|
|
515
|
+
->JSON.stringifyAny
|
|
516
|
+
->Option.getOr("?")}`,
|
|
501
517
|
)
|
|
502
518
|
previousActions->Array.concat([Set(id1, state2)])
|
|
503
519
|
| (Update(id1, _f), Set(id2, state2)) if id1 == id2 =>
|
|
504
|
-
log.warn(
|
|
520
|
+
log.warn(
|
|
521
|
+
~comp="Projection",
|
|
522
|
+
`optimizing Set after Update for id=${id1}, ignoring the Update`,
|
|
523
|
+
)
|
|
505
524
|
previousActions->Array.concat([Set(id1, state2)])
|
|
506
525
|
| (UpdateWithDefault(id1, _defaultState1, _f), Set(id2, state2)) if id1 == id2 =>
|
|
507
|
-
log.warn(
|
|
526
|
+
log.warn(
|
|
527
|
+
~comp="Projection",
|
|
528
|
+
`optimizing Set after UpdateWithDefault for id=${id1}, ignoring the UpdateWithDefault`,
|
|
529
|
+
)
|
|
508
530
|
previousActions->Array.concat([Set(id1, state2)])
|
|
509
531
|
// MULTI STATES
|
|
510
532
|
/*
|
|
@@ -542,7 +564,9 @@ let optimizeActions = actions => {
|
|
|
542
564
|
// any other action will be just appended
|
|
543
565
|
log.warn(
|
|
544
566
|
~comp="Projection",
|
|
545
|
-
`actions not optimized: ${lastAction->JSON.stringifyAny->Option.getOr("?")} + ${action
|
|
567
|
+
`actions not optimized: ${lastAction->JSON.stringifyAny->Option.getOr("?")} + ${action
|
|
568
|
+
->JSON.stringifyAny
|
|
569
|
+
->Option.getOr("?")}`,
|
|
546
570
|
)
|
|
547
571
|
optimizedActions->Array.concat([action])
|
|
548
572
|
}
|
|
@@ -571,7 +595,9 @@ let handleActions = async (~comp="Projection", actions, operations, subIdConfig)
|
|
|
571
595
|
| Error(err) =>
|
|
572
596
|
log.error(
|
|
573
597
|
~comp,
|
|
574
|
-
`storage error: ${err
|
|
598
|
+
`storage error: ${err
|
|
599
|
+
->Message.encode(ReventlessInfra.QueryDb.storageErrorSchema)
|
|
600
|
+
->JSON.stringify}`,
|
|
575
601
|
)
|
|
576
602
|
}
|
|
577
603
|
await action->handleAction(~comp, operations, subIdConfig)
|
package/src/RequestContext.res
CHANGED
|
@@ -56,11 +56,11 @@ let make = (
|
|
|
56
56
|
~claims=Dict.make(),
|
|
57
57
|
): t => {
|
|
58
58
|
correlationId,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
?causationId,
|
|
60
|
+
?component,
|
|
61
|
+
?pluginName,
|
|
62
|
+
?timestamp,
|
|
63
|
+
?retryCount,
|
|
64
64
|
identity,
|
|
65
65
|
claims,
|
|
66
66
|
}
|
|
@@ -90,8 +90,7 @@ let fromOptions = (o: options): t =>
|
|
|
90
90
|
~retryCount=?o.retryCount,
|
|
91
91
|
)
|
|
92
92
|
|
|
93
|
-
let getClaim = (ctx: t, key: string): option<string> =>
|
|
94
|
-
ctx.claims->Dict.get(key)
|
|
93
|
+
let getClaim = (ctx: t, key: string): option<string> => ctx.claims->Dict.get(key)
|
|
95
94
|
|
|
96
95
|
let withClaim = (ctx: t, key: string, value: string): t => {
|
|
97
96
|
let next = ctx.claims->Dict.toArray->Dict.fromArray
|
|
@@ -107,8 +106,8 @@ let test = (
|
|
|
107
106
|
~claims=Dict.make(),
|
|
108
107
|
): t => {
|
|
109
108
|
correlationId,
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
?timestamp,
|
|
110
|
+
?retryCount,
|
|
112
111
|
identity,
|
|
113
112
|
claims,
|
|
114
113
|
}
|
|
@@ -24,9 +24,12 @@ neither derives from the other.
|
|
|
24
24
|
/** The level a resource is attributed to. */
|
|
25
25
|
module Scope = {
|
|
26
26
|
type t =
|
|
27
|
-
|
|
28
|
-
|
|
|
29
|
-
|
|
27
|
+
/** owned by one model component */
|
|
28
|
+
| Component
|
|
29
|
+
/** shared substrate within a plugin (DcbEventLog, plugin DLQ, …) */
|
|
30
|
+
| Plugin
|
|
31
|
+
/** shared substrate across the platform (API, auth, hosting, …) */
|
|
32
|
+
| Platform
|
|
30
33
|
|
|
31
34
|
let toString = scope =>
|
|
32
35
|
switch scope {
|
|
@@ -50,17 +53,28 @@ module Role = {
|
|
|
50
53
|
| EventLogSubscription
|
|
51
54
|
| EventCollector
|
|
52
55
|
| QueryDb
|
|
53
|
-
|
|
54
|
-
|
|
|
55
|
-
|
|
56
|
-
|
|
|
57
|
-
|
|
58
|
-
|
|
|
59
|
-
|
|
60
|
-
|
|
|
61
|
-
|
|
62
|
-
|
|
|
63
|
-
|
|
56
|
+
/** the execution unit that runs a component's handler */
|
|
57
|
+
| Runtime
|
|
58
|
+
/** queue/topic receiving messages that exhausted processing */
|
|
59
|
+
| DeadLetter
|
|
60
|
+
/** scheduled invocation (heartbeat, task scheduler) */
|
|
61
|
+
| Scheduler
|
|
62
|
+
/** log storage and log-derived metrics */
|
|
63
|
+
| Logs
|
|
64
|
+
/** execution identity and its policies */
|
|
65
|
+
| Identity
|
|
66
|
+
/** the GraphQL API surface and its resolvers */
|
|
67
|
+
| Api
|
|
68
|
+
/** identity provider / user pools */
|
|
69
|
+
| Auth
|
|
70
|
+
/** static-site hosting, CDN, certificates, DNS */
|
|
71
|
+
| Hosting
|
|
72
|
+
/** VPC and its network plumbing */
|
|
73
|
+
| Network
|
|
74
|
+
/** transport wiring between a source and a runtime */
|
|
75
|
+
| EventSourceMapping
|
|
76
|
+
/** bulk data movement (cloner, migrations) */
|
|
77
|
+
| DataTransfer
|
|
64
78
|
| Other(string)
|
|
65
79
|
|
|
66
80
|
let toString = role =>
|
package/src/adapter/Adapter.res
CHANGED
|
@@ -38,7 +38,18 @@ let resourcesOutputToResource: Pulumi.Output.t<array<ReventlessInfra.Adapter.res
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
let resolvedToResource = (
|
|
41
|
-
{
|
|
41
|
+
{
|
|
42
|
+
id,
|
|
43
|
+
name,
|
|
44
|
+
urn,
|
|
45
|
+
resourceInfo,
|
|
46
|
+
service,
|
|
47
|
+
role,
|
|
48
|
+
region,
|
|
49
|
+
resourceType,
|
|
50
|
+
configuration,
|
|
51
|
+
tags,
|
|
52
|
+
}: resolvedResource,
|
|
42
53
|
): ReventlessInfra.Adapter.resource => {
|
|
43
54
|
id: id->Pulumi.Output.make,
|
|
44
55
|
name: name->Pulumi.Output.make,
|
|
@@ -124,7 +135,18 @@ let urns = resources => resources->Array.map((resource: resolvedResource) => res
|
|
|
124
135
|
// ---------------------------------------------------------------------------
|
|
125
136
|
|
|
126
137
|
let toInteropResource = (
|
|
127
|
-
{
|
|
138
|
+
{
|
|
139
|
+
name,
|
|
140
|
+
id,
|
|
141
|
+
urn,
|
|
142
|
+
resourceInfo,
|
|
143
|
+
service,
|
|
144
|
+
role,
|
|
145
|
+
region,
|
|
146
|
+
resourceType,
|
|
147
|
+
configuration,
|
|
148
|
+
tags,
|
|
149
|
+
}: resolvedResource,
|
|
128
150
|
): ReventlessInterop.Resource.t => {
|
|
129
151
|
name,
|
|
130
152
|
id,
|
|
@@ -144,7 +166,18 @@ let resourcesToInterop = (resources: array<ReventlessInfra.Adapter.resource>) =>
|
|
|
144
166
|
->Pulumi.Output.apply(rs => rs->Array.map(toInteropResource))
|
|
145
167
|
|
|
146
168
|
let fromInteropResolved = (
|
|
147
|
-
{
|
|
169
|
+
{
|
|
170
|
+
name,
|
|
171
|
+
id,
|
|
172
|
+
urn,
|
|
173
|
+
resourceInfo,
|
|
174
|
+
service,
|
|
175
|
+
role,
|
|
176
|
+
region,
|
|
177
|
+
resourceType,
|
|
178
|
+
configuration,
|
|
179
|
+
tags,
|
|
180
|
+
}: ReventlessInterop.Resource.t,
|
|
148
181
|
): resolvedResource => {
|
|
149
182
|
name,
|
|
150
183
|
id,
|
|
@@ -159,7 +192,18 @@ let fromInteropResolved = (
|
|
|
159
192
|
}
|
|
160
193
|
|
|
161
194
|
let fromInteropResource = (
|
|
162
|
-
{
|
|
195
|
+
{
|
|
196
|
+
name,
|
|
197
|
+
id,
|
|
198
|
+
urn,
|
|
199
|
+
resourceInfo,
|
|
200
|
+
service,
|
|
201
|
+
role,
|
|
202
|
+
region,
|
|
203
|
+
resourceType,
|
|
204
|
+
configuration,
|
|
205
|
+
tags,
|
|
206
|
+
}: ReventlessInterop.Resource.t,
|
|
163
207
|
): ReventlessInfra.Adapter.resource => {
|
|
164
208
|
id: id->Pulumi.Output.make,
|
|
165
209
|
name: name->Pulumi.Output.make,
|
|
@@ -22,7 +22,6 @@ internals into every deployment's stack outputs.
|
|
|
22
22
|
|
|
23
23
|
See `docs/plans/done/event-log-provisioned-seam.md`.
|
|
24
24
|
*/
|
|
25
|
-
|
|
26
25
|
/**
|
|
27
26
|
Which event-log family provisioned the log. The two differ in what a reader finds
|
|
28
27
|
on the wire — a classic log is per-aggregate and its rows carry an aggregate id;
|
|
@@ -30,8 +29,10 @@ a DCB log is per-plugin and its rows carry tags — so a backend that decodes
|
|
|
30
29
|
records needs to know which it is looking at before it looks.
|
|
31
30
|
*/
|
|
32
31
|
type logStyle =
|
|
33
|
-
|
|
34
|
-
|
|
|
32
|
+
/** per-aggregate log behind `EventLog_Builder` */
|
|
33
|
+
| Classic
|
|
34
|
+
/** per-plugin tagged log behind `DcbEventLog_Builder` */
|
|
35
|
+
| Dcb
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
An event-log backend, registered by an extension (a deploy program) before the
|
|
@@ -124,8 +125,7 @@ let use = (b: module(Backend)) => {
|
|
|
124
125
|
JsError.throwWithMessage(
|
|
125
126
|
"EventLogProvisioning.use called twice: only one event-log backend can be registered. " ++
|
|
126
127
|
"A DynamoDB stream supports two readers per shard and core's event collector already holds one, " ++
|
|
127
|
-
"so a second backend would throttle the first. Compose the two backends into one, or fan out " ++
|
|
128
|
-
"behind a single registration.",
|
|
128
|
+
"so a second backend would throttle the first. Compose the two backends into one, or fan out " ++ "behind a single registration.",
|
|
129
129
|
)
|
|
130
130
|
}
|
|
131
131
|
registered := true
|
|
@@ -40,8 +40,7 @@ deployment does. SMS and push are absent for the same reason they are absent
|
|
|
40
40
|
there — no transport — and answer `UnsupportedChannel`, which is settled rather
|
|
41
41
|
than retried.
|
|
42
42
|
*/
|
|
43
|
-
let channels = (~sender: string): array<Reventless.Messaging.channel> =>
|
|
44
|
-
sender == "" ? [] : [Email]
|
|
43
|
+
let channels = (~sender: string): array<Reventless.Messaging.channel> => sender == "" ? [] : [Email]
|
|
45
44
|
|
|
46
45
|
/** The message as it would have gone out, headers and all.
|
|
47
46
|
|
|
@@ -91,8 +90,12 @@ let send = async (
|
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
/** The port, closed over the sender this platform was given. What a platform's
|
|
94
|
-
capability record carries when logging is the chosen transport.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
capability record carries when logging is the chosen transport.
|
|
94
|
+
|
|
95
|
+
No push service, so `makeProvider` publishes no `Push` channel — the same
|
|
96
|
+
empty answer this transport gives for SMS, and for the same reason. */
|
|
97
|
+
let provider = (~sender: string): Reventless.Messaging.provider =>
|
|
98
|
+
Reventless.Messaging.makeProvider(~emailAndSms=channels(~sender), ~pushServices=[], ~send=(
|
|
99
|
+
~recipient,
|
|
100
|
+
~message,
|
|
101
|
+
) => send(~sender, ~recipient, ~message))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
3
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
4
|
+
import * as Messaging$Reventless from "@reventlessdev/reventless-spec/src/semantic/Messaging.res.mjs";
|
|
4
5
|
import * as Logger$ReventlessCore from "../../util/Logger.res.mjs";
|
|
5
6
|
|
|
6
7
|
let log = Logger$ReventlessCore.fromEnv();
|
|
@@ -69,10 +70,7 @@ async function send(sender, recipient, message) {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
function provider(sender) {
|
|
72
|
-
return
|
|
73
|
-
channels: channels(sender),
|
|
74
|
-
send: (recipient, message) => send(sender, recipient, message)
|
|
75
|
-
};
|
|
73
|
+
return Messaging$Reventless.makeProvider(channels(sender), [], (recipient, message) => send(sender, recipient, message));
|
|
76
74
|
}
|
|
77
75
|
|
|
78
76
|
export {
|
|
@@ -12,7 +12,6 @@ listener.
|
|
|
12
12
|
|
|
13
13
|
See `docs/plans/done/monitoring-hook-seam.md`.
|
|
14
14
|
*/
|
|
15
|
-
|
|
16
15
|
/**
|
|
17
16
|
The ROLE of a provisioned execution unit, not its mechanism. What "failure"
|
|
18
17
|
means for a unit is provider-specific (a Lambda `Errors` metric vs. container
|
|
@@ -23,27 +22,27 @@ hatch for support units and future roles (same pattern as the protocol's
|
|
|
23
22
|
`OtherKind`).
|
|
24
23
|
*/
|
|
25
24
|
type unitKind =
|
|
26
|
-
|
|
25
|
+
/** aggregates, state-change slices, extension points — failure = writes
|
|
27
26
|
rejected/dropped (the silent-freeze class) */
|
|
28
|
-
CommandHandler
|
|
29
|
-
|
|
30
|
-
Projection
|
|
31
|
-
|
|
27
|
+
| CommandHandler
|
|
28
|
+
/** state-view slices, read models — failure = silently stale reads */
|
|
29
|
+
| Projection
|
|
30
|
+
/** automation slices, side-effect handlers, translations — failure = missed
|
|
32
31
|
side effects at boundaries */
|
|
33
|
-
Reactor
|
|
34
|
-
|
|
32
|
+
| Reactor
|
|
33
|
+
/** cross-plugin/admin event ingestion — failure = event flow between plugins
|
|
35
34
|
stops */
|
|
36
|
-
EventCollector
|
|
37
|
-
|
|
38
|
-
Task
|
|
39
|
-
|
|
35
|
+
| EventCollector
|
|
36
|
+
/** scheduled task runners */
|
|
37
|
+
| Task
|
|
38
|
+
/** heartbeat/keep-alive — failure = lifecycle detection AND any staleness
|
|
40
39
|
watchdog go blind (monitoring's own pulse) */
|
|
41
|
-
Scheduler
|
|
42
|
-
|
|
43
|
-
DeadLetterSink
|
|
44
|
-
|
|
40
|
+
| Scheduler
|
|
41
|
+
/** receives messages that exhausted processing */
|
|
42
|
+
| DeadLetterSink
|
|
43
|
+
/** support units (counters, change-feed relays, migration runners, query
|
|
45
44
|
resolvers, …) — providers pass their name */
|
|
46
|
-
Other(string)
|
|
45
|
+
| Other(string)
|
|
47
46
|
|
|
48
47
|
/**
|
|
49
48
|
A monitoring backend, registered by an extension (a deploy program) before the
|
|
@@ -172,13 +172,18 @@ module Make = (
|
|
|
172
172
|
(infos, handler)
|
|
173
173
|
->Pulumi.Output.all2
|
|
174
174
|
->Pulumi.Output.apply(((infos, handler)) => {
|
|
175
|
-
let infoStrs = infos->Array.filterMap(ri =>
|
|
176
|
-
|
|
175
|
+
let infoStrs = infos->Array.filterMap(ri =>
|
|
176
|
+
switch ri {
|
|
177
|
+
| ReventlessInfra.Adapter.ApiResolver({typeName, fieldName}) =>
|
|
178
|
+
Some(`${typeName}.${fieldName}`)
|
|
177
179
|
| _ => None
|
|
178
|
-
|
|
180
|
+
}
|
|
181
|
+
)
|
|
179
182
|
log.debug(
|
|
180
183
|
~comp="AggregateRuntime",
|
|
181
|
-
`forCommandGenerator ${commandGeneratorName}: set handler for ${infoStrs->Array.join(
|
|
184
|
+
`forCommandGenerator ${commandGeneratorName}: set handler for ${infoStrs->Array.join(
|
|
185
|
+
", ",
|
|
186
|
+
)}`,
|
|
182
187
|
)
|
|
183
188
|
infoStrs->Array.map(info => commandGeneratorHandlers->Dict.set(info, handler))
|
|
184
189
|
})
|
|
@@ -260,7 +265,9 @@ module Make = (
|
|
|
260
265
|
let handlers = eventCollectorHandlers->Dict.get(urn)->Option.getOr([])
|
|
261
266
|
eventCollectorHandlers->Dict.set(
|
|
262
267
|
urn,
|
|
263
|
-
handlers->Array.concat([
|
|
268
|
+
handlers->Array.concat([
|
|
269
|
+
{comp, handler: handler->RuntimeEnvironment.asEffectHandler},
|
|
270
|
+
]),
|
|
264
271
|
)
|
|
265
272
|
})
|
|
266
273
|
})
|