@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.
Files changed (203) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +9 -9
  3. package/src/Behavior.res +1 -4
  4. package/src/Message.res +17 -14
  5. package/src/Projection.res +51 -25
  6. package/src/RequestContext.res +8 -9
  7. package/src/ResourceAttribution.res +28 -14
  8. package/src/adapter/Adapter.res +48 -4
  9. package/src/adapter/EventLogProvisioning/EventLogProvisioning.res +5 -5
  10. package/src/adapter/Messaging/Messaging_Log_Backend.res +10 -7
  11. package/src/adapter/Messaging/Messaging_Log_Backend.res.mjs +2 -4
  12. package/src/adapter/Monitoring/Monitoring.res +16 -17
  13. package/src/adapter/QueryInterception/QueryInterception.res +0 -1
  14. package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +12 -5
  15. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +11 -7
  16. package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +1 -7
  17. package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +1 -7
  18. package/src/adapter/RuntimeExtension/RuntimeExtension.res +0 -1
  19. package/src/admin/Platform_Admin.res +17 -6
  20. package/src/admin/Platform_AdminApi.res +14 -9
  21. package/src/admin/Platform_Admin_Callback.res +1 -1
  22. package/src/admin/Platform_BakedManifest.res +34 -34
  23. package/src/admin/Platform_ComponentDefinitionsApi.res +9 -21
  24. package/src/admin/Platform_PluginStructuresApi.res +15 -12
  25. package/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry.res +1 -1
  26. package/src/components/Aggregate/Aggregate.res +13 -12
  27. package/src/components/Aggregate/Aggregate_Builder.res +22 -21
  28. package/src/components/Aggregate/Aggregate_Callback.res +91 -86
  29. package/src/components/Api/ApiNoApiHelpers.res +1 -3
  30. package/src/components/Api/Api_Ids.res +0 -1
  31. package/src/components/Api/Api_Naming.res +41 -18
  32. package/src/components/Api/GraphQL_FragmentGenerator.res +38 -51
  33. package/src/components/Api/GraphQL_SchemaInspector.res +5 -3
  34. package/src/components/Api/GraphQL_Stitcher.res +9 -10
  35. package/src/components/Api/MCP_SchemaGenerator.res +8 -12
  36. package/src/components/Api/OwnerScopeDiagnostics.res +1 -2
  37. package/src/components/Api/QueryDbListQuery.res +13 -6
  38. package/src/components/Api/SchemaType.res +28 -23
  39. package/src/components/Api/SuryToJsonSchema.res +9 -10
  40. package/src/components/AutomationSlice/AutomationSlice.res +4 -4
  41. package/src/components/AutomationSlice/AutomationSlice_Builder.res +15 -14
  42. package/src/components/AutomationSlice/AutomationSlice_Callback.res +3 -3
  43. package/src/components/Builder_Helpers.res +12 -23
  44. package/src/components/CommandGenerator/CommandGenerator.res +6 -1
  45. package/src/components/CommandGenerator/CommandGenerator_Builder.res +29 -21
  46. package/src/components/CommandGenerator/CommandGenerator_Callback.res +17 -21
  47. package/src/components/CommandTopic/CommandTopic.res +3 -3
  48. package/src/components/CommandTopic/CommandTopic_Builder.res +10 -10
  49. package/src/components/CommandTopic/CommandTopic_Callback.res +1 -4
  50. package/src/components/CommandTopic/CommandTopic_Helpers.res +1 -2
  51. package/src/components/Counter/Counter_Builder.res +1 -6
  52. package/src/components/Counter/Counter_Callback.res +3 -3
  53. package/src/components/Dcb/Dcb_Builder.res +970 -956
  54. package/src/components/DcbEventLog/DcbEventLog.res +4 -4
  55. package/src/components/DcbEventLog/DcbEventLog_Builder.res +0 -1
  56. package/src/components/DcbEventLog/DcbEventLog_Operations.res +17 -18
  57. package/src/components/EventCollector/EventCollector_Builder.res +2 -1
  58. package/src/components/EventLog/EventLog.res +5 -1
  59. package/src/components/EventLog/EventLog_Operations.res +12 -8
  60. package/src/components/EventMapper/EventMapper.res +8 -10
  61. package/src/components/EventMapper/EventMapper_Builder.res +4 -1
  62. package/src/components/EventMapper/EventMapper_Callback.res +46 -31
  63. package/src/components/EventTopic/EventTopic.res +3 -3
  64. package/src/components/EventTopic/EventTopic_Builder.res +1 -1
  65. package/src/components/Extension/Extension.res +4 -1
  66. package/src/components/Extension/Extension_Operations.res +11 -3
  67. package/src/components/ExtensionPoint/ExtensionPoint.res +3 -3
  68. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +9 -10
  69. package/src/components/ExtensionPoint/ExtensionPoint_Callback.res +2 -6
  70. package/src/components/ExtensionPoint/ExtensionPoint_Operations.res +13 -5
  71. package/src/components/Heartbeat/Heartbeat_Callback.res +3 -3
  72. package/src/components/InboundTranslationSlice/InboundTranslationSlice.res +4 -4
  73. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +7 -10
  74. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice.res +4 -4
  75. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +15 -14
  76. package/src/components/QueryDb/QueryDb_Adapter.res +1 -3
  77. package/src/components/QueryDb/QueryDb_Operations.res +10 -10
  78. package/src/components/ReadModel/ReadModel.res +3 -3
  79. package/src/components/ReadModel/ReadModel_Builder.res +1 -2
  80. package/src/components/ReadModel/ReadModel_Callback.res +2 -1
  81. package/src/components/SideEffectHandler/SideEffectHandler_Callback.res +5 -2
  82. package/src/components/StateChangeSlice/StateChangeSlice.res +3 -3
  83. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +23 -4
  84. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +22 -6
  85. package/src/components/StateTopic.res +1 -3
  86. package/src/components/StateViewSlice/StateViewSlice.res +4 -4
  87. package/src/components/StateViewSlice/StateViewSlice_Builder.res +79 -68
  88. package/src/components/StateViewSlice/StateViewSlice_Callback.res +3 -1
  89. package/src/components/Task/Task.res +3 -3
  90. package/src/components/Task/Task_Adapter.res +4 -1
  91. package/src/components/Task/Task_Builder.res +24 -21
  92. package/src/plugin/api/PluginBaseFragment.res +9 -3
  93. package/src/plugin/component/Capability_Inference.res +8 -10
  94. package/src/plugin/component/Plugin.res +6 -6
  95. package/src/plugin/component/Plugin_Builder.res +54 -50
  96. package/src/plugin/component/Plugin_Callback.res +10 -6
  97. package/src/plugin/component/Plugin_Helpers.res +264 -230
  98. package/src/plugin/component/Plugin_Structure.res +370 -324
  99. package/src/plugin/component/Plugin_SubscriptionSchema.res +8 -6
  100. package/src/plugin/component/SchemaWalker.res +11 -12
  101. package/src/plugin/connect/PluginConnectExtension_Mapping.res +45 -50
  102. package/src/plugin/lifecycle/PluginBehavior.res +3 -4
  103. package/src/plugin/lifecycle/PluginSpec.res +1 -2
  104. package/src/plugin/lifecycle/PluginsProjection.res +16 -5
  105. package/src/plugin/lifecycle/PluginsReadModelSpec.res +0 -2
  106. package/src/util/CommandPublisher.res +9 -2
  107. package/src/util/CsvStream.res +3 -3
  108. package/src/util/Interstack.res +7 -15
  109. package/src/util/Interstack.resi +3 -3
  110. package/src/util/LogFormat.res +5 -9
  111. package/src/util/Logger.res +1 -2
  112. package/src/util/Lru.res +2 -1
  113. package/src/util/Lru.resi +2 -3
  114. package/src/util/ScheduleOps.res +24 -27
  115. package/src/util/StorePrefixCollision.res +6 -9
  116. package/src/util/Util_Promise.res +4 -1
  117. package/src/util/Util_Promise.res.mjs +1 -1
  118. package/tests/IdentityTest.res +166 -113
  119. package/tests/ResourceAttributionTest.res +28 -25
  120. package/tests/StorePrefixCollisionTest.res +2 -1
  121. package/tests/TaskBucketNamingTest.res +3 -2
  122. package/tests/adapter/EventLogProvisioningTest.res +51 -48
  123. package/tests/adapter/MonitoringTest.res +81 -38
  124. package/tests/adapter/QueryInterceptionTest.res +2 -2
  125. package/tests/adapter/RefusalVocabularyTest.res +31 -23
  126. package/tests/adapter/RuntimeExtensionHookReachTest.res +9 -8
  127. package/tests/adapter/RuntimeExtensionTest.res +5 -3
  128. package/tests/admin/AdminApiSchemaDriftTest.res +22 -16
  129. package/tests/admin/Platform_Admin_StructureTest.res +10 -11
  130. package/tests/admin/Platform_BakedManifestTest.res +31 -35
  131. package/tests/admin/Platform_ComponentDefinitionsApiTest.res +18 -15
  132. package/tests/admin/Platform_PluginStructuresApiTest.res +5 -3
  133. package/tests/admin/Platform_UIFragmentsApiTest.res +6 -3
  134. package/tests/aggregate/AggregateCacheTest.res +10 -12
  135. package/tests/aggregate/AggregateCallbackTest.res +75 -46
  136. package/tests/aggregate/AggregateCausationTest.res +19 -20
  137. package/tests/aggregate/AggregateConflictTest.res +41 -19
  138. package/tests/aggregate/AggregateFixtures.res +15 -5
  139. package/tests/aggregate/AggregateRejectionTest.res +97 -80
  140. package/tests/aggregate/AggregateSnapshotTest.res +44 -16
  141. package/tests/api/Api_IdsTest.res +10 -4
  142. package/tests/api/BrandedMarkerCompositionTest.res +48 -36
  143. package/tests/api/GeolocationSemanticTest.res +3 -3
  144. package/tests/api/GraphQL_FragmentGeneratorTest.res +66 -54
  145. package/tests/api/OwnerScopeDiagnosticsTest.res +31 -27
  146. package/tests/api/StorageRefFieldsTest.res +30 -18
  147. package/tests/api/SuryToJsonSchemaTest.res +1315 -1014
  148. package/tests/api/TaggedUnionSchemaTest.res +17 -24
  149. package/tests/commandgenerator/CommandGeneratorCallbackTest.res +235 -179
  150. package/tests/commandgenerator/CommandGeneratorFixtures.res +8 -13
  151. package/tests/commandgenerator/OwnerStampingTest.res +91 -76
  152. package/tests/commandtopic/CommandOutcomeHookTest.res +198 -155
  153. package/tests/commandtopic/CommandTopicCallbackFixtures.res +5 -4
  154. package/tests/commandtopic/CommandTopicCallbackTest.res +61 -43
  155. package/tests/commandtopic/CommandTopicHelpersRejectionTest.res +70 -55
  156. package/tests/counter/CounterCallbackTest.res +40 -34
  157. package/tests/counter/CounterFixtures.res +4 -4
  158. package/tests/dcb/DcbDecodeTest.res +115 -84
  159. package/tests/dcb/DcbEventLogOperationsTest.res +194 -143
  160. package/tests/dcb/DcbEventLogSchemaTest.res +13 -13
  161. package/tests/dcb/DcbFixtures.res +4 -5
  162. package/tests/dcb/DcbScopeInferenceTest.res +173 -114
  163. package/tests/dcb/DcbStateChangeSliceTest.res +391 -262
  164. package/tests/dcb/DcbTagTest.res +22 -11
  165. package/tests/dcb/DcbValidationTest.res +288 -218
  166. package/tests/eventlog/EventLogFixtures.res +4 -4
  167. package/tests/eventlog/EventLogOperationsTest.res +102 -67
  168. package/tests/eventlog/EventLogRetryTest.res +104 -65
  169. package/tests/eventmapper/EventMapperCallbackTest.res +118 -83
  170. package/tests/eventmapper/EventMapperFixtures.res +15 -23
  171. package/tests/eventmapper/EventMapperTest.res +54 -38
  172. package/tests/eventtopic/EventTopicFixtures.res +3 -4
  173. package/tests/eventtopic/EventTopicOperationsTest.res +41 -29
  174. package/tests/extensionpoint/ExtensionPointCallbackTest.res +58 -45
  175. package/tests/extensionpoint/ExtensionPointFixtures.res +16 -20
  176. package/tests/extensionpoint/ExtensionPointOperationsTest.res +70 -49
  177. package/tests/extensionpoint/PluginDisconnectScheduleTest.res +2 -1
  178. package/tests/logger/LogFormatTest.res +104 -82
  179. package/tests/logger/LoggerLazyTest.res +21 -12
  180. package/tests/message/MessageTest.res +96 -93
  181. package/tests/message/MetaEnvelopeTest.res +26 -30
  182. package/tests/plugin/HeartbeatDisconnectGraceTest.res +31 -25
  183. package/tests/plugin/ManifestVisibilityTest.res +20 -12
  184. package/tests/plugin/PluginDefinitionScalars.res +1 -2
  185. package/tests/plugin/PluginLifecycleCorpusTest.res +15 -12
  186. package/tests/plugin/PluginSpecExperiment.res +0 -1
  187. package/tests/plugin/PluginStructureTest.res +1529 -1045
  188. package/tests/plugin/Plugin_EventQuerySchemaTest.res +21 -10
  189. package/tests/plugin/SchemaWalkerTest.res +116 -70
  190. package/tests/plugin/StateChange/PsReserveStock.res +4 -4
  191. package/tests/plugin/StateView/PsAnnotatedView.res +4 -4
  192. package/tests/plugin/StateView/PsCustomersView.res +4 -4
  193. package/tests/plugin/StateView/PsShipmentsView.res +3 -2
  194. package/tests/projection/LifecycleTrailTest.res +1 -4
  195. package/tests/projection/ProjectionOptimizeTest.res +13 -9
  196. package/tests/querydb/QueryDbFixtures.res +0 -1
  197. package/tests/querydb/QueryDbOperationsTest.res +99 -64
  198. package/tests/querydb/TaggedUnionStampTest.res +10 -8
  199. package/tests/sideeffecthandler/SideEffectHandlerCallbackTest.res +50 -35
  200. package/tests/sideeffecthandler/SideEffectHandlerFixtures.res +4 -10
  201. package/tests/util/CommandPublisherTest.res +0 -1
  202. package/tests/util/CsvStreamTest.res +3 -3
  203. package/tests/util/LruTest.res +84 -56
@@ -129,8 +129,7 @@ module Make = (
129
129
  `OutboundTranslationSlice "${Spec.name}" declares sourceName "${sourceName}", ` ++
130
130
  `but no EventTopic with that key exists. ` ++
131
131
  `Available source names: [${availableNames}]. ` ++
132
- `A source is an Aggregate Spec.name or a DCB source name ` ++
133
- `(typically "<pluginName>DcbEventLog"); \`[]\` means this plugin's own DCB log.`,
132
+ `A source is an Aggregate Spec.name or a DCB source name ` ++ `(typically "<pluginName>DcbEventLog"); \`[]\` means this plugin's own DCB log.`,
134
133
  )
135
134
  }
136
135
  )
@@ -200,18 +199,20 @@ module Make = (
200
199
  let _ =
201
200
  Callback.phase2(publishJsonsFn, ~capabilities=Capabilities.capabilities())
202
201
  ->Promise.then(() => syncToQueryDb(queryDbOps))
203
- ->Promise.catch(exn => {
204
- let errMsg =
205
- exn
206
- ->JsExn.fromException
207
- ->Option.flatMap(JsExn.message)
208
- ->Option.getOr("unknown")
209
- EffectLogger.logError(
210
- ~comp=`OutboundTranslationSlice(${Spec.name})`,
211
- `detached phase 2 error: ${errMsg}`,
212
- )->Effect.runSync
213
- Promise.resolve()
214
- })
202
+ ->Promise.catch(
203
+ exn => {
204
+ let errMsg =
205
+ exn
206
+ ->JsExn.fromException
207
+ ->Option.flatMap(JsExn.message)
208
+ ->Option.getOr("unknown")
209
+ EffectLogger.logError(
210
+ ~comp=`OutboundTranslationSlice(${Spec.name})`,
211
+ `detached phase 2 error: ${errMsg}`,
212
+ )->Effect.runSync
213
+ Promise.resolve()
214
+ },
215
+ )
215
216
  },
216
217
  )
217
218
  )
@@ -25,9 +25,7 @@ module type Storage = {
25
25
  let make: storageMaker<api, role>
26
26
  }
27
27
 
28
- type queryEngineMaker = dict<QueryDb.outputs> => Pulumi.Output.t<
29
- Reventless.QueryEngine.operations,
30
- >
28
+ type queryEngineMaker = dict<QueryDb.outputs> => Pulumi.Output.t<Reventless.QueryEngine.operations>
31
29
 
32
30
  module type QueryEngineAdapter = {
33
31
  let make: queryEngineMaker
@@ -19,8 +19,7 @@ module Make = (ReadModelSpec: Reventless.ReadModel.Spec, Ops: Ops) => {
19
19
  }
20
20
 
21
21
  let loadStream = id =>
22
- Ops.jsonOps.loadStream(id->ReadModelSpec.Id.toString)
23
- ->Stream.mapEffect(json =>
22
+ Ops.jsonOps.loadStream(id->ReadModelSpec.Id.toString)->Stream.mapEffect(json =>
24
23
  switch decode(id, json) {
25
24
  | Ok(s) => Effect.succeed(s)
26
25
  | Error(e) => Effect.fail(e)
@@ -32,9 +31,7 @@ module Make = (ReadModelSpec: Reventless.ReadModel.Spec, Ops: Ops) => {
32
31
  | result =>
33
32
  result->Result.flatMap(states =>
34
33
  states->Array.reduce(Ok([]), (acc, state) =>
35
- acc->Result.flatMap(arr =>
36
- decode(id, state)->Result.map(s => arr->Array.concat([s]))
37
- )
34
+ acc->Result.flatMap(arr => decode(id, state)->Result.map(s => arr->Array.concat([s])))
38
35
  )
39
36
  )
40
37
  }
@@ -51,7 +48,7 @@ module Make = (ReadModelSpec: Reventless.ReadModel.Spec, Ops: Ops) => {
51
48
  dict->Dict.get(field)->Option.flatMap(JSON.Decode.string)->Option.getOr("")
52
49
  ReadModelSpec.config.indexes->Array.forEach(idx => {
53
50
  switch idx.pkFields {
54
- | Some(fs) when fs->Array.length > 1 =>
51
+ | Some(fs) if fs->Array.length > 1 =>
55
52
  let sep = idx.pkSep->Option.getOr("/")
56
53
  let value = fs->Array.map(getStr)->Array.join(sep)
57
54
  let attrName = idx.idField->Option.getOr("_pk")
@@ -59,7 +56,7 @@ module Make = (ReadModelSpec: Reventless.ReadModel.Spec, Ops: Ops) => {
59
56
  | _ => ()
60
57
  }
61
58
  switch idx.skFields {
62
- | Some(fs) when fs->Array.length > 1 =>
59
+ | Some(fs) if fs->Array.length > 1 =>
63
60
  let sep = idx.skSep->Option.getOr("/")
64
61
  let value = fs->Array.map(getStr)->Array.join(sep)
65
62
  let attrName = idx.subIdField->Option.getOr("_sk")
@@ -76,8 +73,9 @@ module Make = (ReadModelSpec: Reventless.ReadModel.Spec, Ops: Ops) => {
76
73
  // and left exactly as it was.
77
74
  // The union fields this view declares, read once. Empty for most views, and
78
75
  // the whole diagnostic below costs nothing when it is.
79
- let declaredUnionFields =
80
- Reventless.TaggedUnion.fieldsOf(ReadModelSpec.stateSchema->S.castToUnknown)
76
+ let declaredUnionFields = Reventless.TaggedUnion.fieldsOf(
77
+ ReadModelSpec.stateSchema->S.castToUnknown,
78
+ )
81
79
 
82
80
  // Logged once per instantiation, and unconditionally: "none" has to be
83
81
  // distinguishable from "never instantiated", because a schema that resolves no
@@ -104,7 +102,9 @@ module Make = (ReadModelSpec: Reventless.ReadModel.Spec, Ops: Ops) => {
104
102
  log.warn(
105
103
  ~comp="QueryDb",
106
104
  `${ReadModelSpec.name}.${field}: stored a union value with no ${Reventless.TaggedUnion.typenameKey} ` ++
107
- `(union ${unionName->Option.getOr("<unnamed>")}). The field will resolve to null and take its ` ++
105
+ `(union ${unionName->Option.getOr(
106
+ "<unnamed>",
107
+ )}). The field will resolve to null and take its ` ++
108
108
  `parent with it. Union fields seen on this spec: ${declaredUnionFields
109
109
  ->Array.map(((f, _)) => f)
110
110
  ->Array.join(", ")}`,
@@ -30,9 +30,9 @@ module type T = {
30
30
  let finish: unit => unit
31
31
  }
32
32
 
33
- let toResolvedOutputs = (
34
- outputs: outputs,
35
- ): Pulumi.Output.t<ReventlessInterop.ReadModel.resolvedOutputs> =>
33
+ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
34
+ ReventlessInterop.ReadModel.resolvedOutputs,
35
+ > =>
36
36
  outputs.queryDb.resources
37
37
  ->Adapter.resourcesToInterop
38
38
  ->Pulumi.Output.apply(queryDbResources => {
@@ -104,8 +104,7 @@ module Make = (
104
104
  `ReadModel "${Spec.name}" has a Mapping with sourceName "${sourceName}", ` ++
105
105
  `but no EventTopic with that key exists in allEventTopics. ` ++
106
106
  `Available source names: [${availableNames}]. ` ++
107
- `Check Mapping.Make's first arg matches an Aggregate Spec.name or a DCB ` ++
108
- `source name (typically "<pluginName>DcbEventLog").`,
107
+ `Check Mapping.Make's first arg matches an Aggregate Spec.name or a DCB ` ++ `source name (typically "<pluginName>DcbEventLog").`,
109
108
  )
110
109
  }
111
110
  )
@@ -42,7 +42,8 @@ module Make = (
42
42
  acc->Effect.flatMap(
43
43
  _ => {
44
44
  Effect.promise(
45
- () => Projection.handleAction(~comp, action, Spec.operations, ReadModelSpec.subIdConfig),
45
+ () =>
46
+ Projection.handleAction(~comp, action, Spec.operations, ReadModelSpec.subIdConfig),
46
47
  )->Effect.map(_ => ())
47
48
  },
48
49
  )
@@ -49,7 +49,10 @@ module Make = (Spec: Spec): T => {
49
49
  | exception err =>
50
50
  let errMsg =
51
51
  err->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("unknown")
52
- EffectLogger.logError(~comp="SideEffects", `map: Couldn't decode meta: ${errMsg}`)->Effect.runSync
52
+ EffectLogger.logError(
53
+ ~comp="SideEffects",
54
+ `map: Couldn't decode meta: ${errMsg}`,
55
+ )->Effect.runSync
53
56
  None
54
57
  | _ =>
55
58
  EffectLogger.logError(~comp="SideEffects", "map: Invalid JSON object")->Effect.runSync
@@ -107,7 +110,7 @@ module Make = (Spec: Spec): T => {
107
110
  )
108
111
  }
109
112
  )
110
- ->Effect.catchAll(errMsg => EffectLogger.logError(~comp="SideEffectHandler", errMsg))
113
+ ->Effect.catchAll(errMsg => EffectLogger.logError(~comp="SideEffectHandler", errMsg)),
111
114
  )
112
115
  | None => Effect.succeed()
113
116
  }
@@ -5,9 +5,9 @@ type outputs = ReventlessInfra.StateChangeSlice.outputs
5
5
  type operations = ReventlessInfra.StateChangeSlice.operations
6
6
  type component = Component.t<t, outputs, operations>
7
7
 
8
- let toResolvedOutputs = (
9
- outputs: outputs,
10
- ): Pulumi.Output.t<ReventlessInterop.StateChangeSlice.resolvedOutputs> =>
8
+ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
9
+ ReventlessInterop.StateChangeSlice.resolvedOutputs,
10
+ > =>
11
11
  outputs.resources
12
12
  ->Adapter.resourcesToInterop
13
13
  ->Pulumi.Output.apply(resources => {
@@ -10,7 +10,11 @@ module Make = (
10
10
  type component = StateChangeSlice.component
11
11
  module Callback = StateChangeSlice_Callback.Make(Spec, Behavior)
12
12
 
13
- let makeJsonHandler = (~tagKeysByEventType, ~crossPartitionTagKeys, dcbEventLogOps: DcbEventLog.operations) => {
13
+ let makeJsonHandler = (
14
+ ~tagKeysByEventType,
15
+ ~crossPartitionTagKeys,
16
+ dcbEventLogOps: DcbEventLog.operations,
17
+ ) => {
14
18
  let handler: CommandTopic.jsonCommandsHandler = stream => {
15
19
  let decodedStream =
16
20
  stream
@@ -35,7 +39,12 @@ module Make = (
35
39
  | None => Stream.empty
36
40
  }
37
41
  )
38
- Callback.handleCommands(~tagKeysByEventType, ~crossPartitionTagKeys, dcbEventLogOps, decodedStream)
42
+ Callback.handleCommands(
43
+ ~tagKeysByEventType,
44
+ ~crossPartitionTagKeys,
45
+ dcbEventLogOps,
46
+ decodedStream,
47
+ )
39
48
  }
40
49
  handler
41
50
  }
@@ -55,7 +64,11 @@ module Make = (
55
64
  dcbEventLog
56
65
  ->Component.operations
57
66
  ->Pulumi.Output.apply(dcbEventLogOps => {
58
- let jsonHandler = makeJsonHandler(~tagKeysByEventType, ~crossPartitionTagKeys, dcbEventLogOps)
67
+ let jsonHandler = makeJsonHandler(
68
+ ~tagKeysByEventType,
69
+ ~crossPartitionTagKeys,
70
+ dcbEventLogOps,
71
+ )
59
72
  CommandTopic.registerHandler(
60
73
  ~schema=commandSchema,
61
74
  ~handler=jsonHandler,
@@ -91,7 +104,13 @@ module Make = (
91
104
  Component.make(
92
105
  ~componentType=StateChangeSlice.componentType->ComponentType.toString,
93
106
  ~name=Spec.name,
94
- ~construct=construct(~dcbEventLog, ~publishJsons, ~tagKeysByEventType, ~crossPartitionTagKeys, ...),
107
+ ~construct=construct(
108
+ ~dcbEventLog,
109
+ ~publishJsons,
110
+ ~tagKeysByEventType,
111
+ ~crossPartitionTagKeys,
112
+ ...
113
+ ),
95
114
  ~opts,
96
115
  )
97
116
  }
@@ -307,7 +307,9 @@ module Make = (
307
307
  }
308
308
  EffectLogger.logInfo(
309
309
  ~comp,
310
- `read${cacheHit ? " (cached, delta)" : ""}: ${reads->Array.length->Int.toString} event(s)${reads->Array.length == 0
310
+ `read${cacheHit ? " (cached, delta)" : ""}: ${reads
311
+ ->Array.length
312
+ ->Int.toString} event(s)${reads->Array.length == 0
311
313
  ? ""
312
314
  : ` [${reads->Array.join(", ")}]`}`,
313
315
  )
@@ -337,8 +339,8 @@ module Make = (
337
339
  EffectLogger.logInfo(~comp, "no events produced")->Effect.map(_ => Ok("ok"))
338
340
  | Ok(newEvents) =>
339
341
  let rawEvents =
340
- newEvents->Array.map(e =>
341
- encodeEvent(~parentMeta=command'.meta, ~tagKeysByEventType, e)
342
+ newEvents->Array.map(
343
+ e => encodeEvent(~parentMeta=command'.meta, ~tagKeysByEventType, e),
342
344
  )
343
345
  let eventCount = rawEvents->Array.length->Int.toString
344
346
  let eventDetails =
@@ -393,7 +395,10 @@ module Make = (
393
395
  // Typed classification (was substring-matching the error string,
394
396
  // which disagreed with the backends' casing).
395
397
  let (errorCode, errDetail) = switch err {
396
- | ReventlessInfra.DcbEventLog.Conflict => ("Conflict", "conflict: condition check failed")
398
+ | ReventlessInfra.DcbEventLog.Conflict => (
399
+ "Conflict",
400
+ "conflict: condition check failed",
401
+ )
397
402
  | StorageFailure(msg) => ("AppendFailed", msg)
398
403
  }
399
404
  if retries > 0 {
@@ -413,6 +418,7 @@ module Make = (
413
418
  // Retries exhausted — drop any cached snapshot so the next
414
419
  // command for this entity takes the cold full-read path.
415
420
  cacheInvalidate()
421
+
416
422
  // A surfaced Conflict means the 3-retry loop could not absorb
417
423
  // the contention — the operator signal for "this slice is hot"
418
424
  // (consider sharding / async — Issue 10, §4 of the analysis).
@@ -465,10 +471,20 @@ module Make = (
465
471
 
466
472
  // CommandTopic handler — processes each command sequentially through handleSingleCommand,
467
473
  // returning Ok(reference) or Error(reference) per command.
468
- let handleCommands = (~tagKeysByEventType=Dict.make(), ~crossPartitionTagKeys=[], dcbEventLog, stream) =>
474
+ let handleCommands = (
475
+ ~tagKeysByEventType=Dict.make(),
476
+ ~crossPartitionTagKeys=[],
477
+ dcbEventLog,
478
+ stream,
479
+ ) =>
469
480
  stream
470
481
  ->Stream.mapEffect(({ReventlessInfra.CommandTopic.reference: reference, command}) =>
471
- handleSingleCommand(~tagKeysByEventType, ~crossPartitionTagKeys, dcbEventLog, command)->Effect.map(result =>
482
+ handleSingleCommand(
483
+ ~tagKeysByEventType,
484
+ ~crossPartitionTagKeys,
485
+ dcbEventLog,
486
+ command,
487
+ )->Effect.map(result =>
472
488
  switch result {
473
489
  | Ok(_) => Ok(reference)
474
490
  | Error(_) => Error(reference)
@@ -43,9 +43,7 @@ module Make = (
43
43
  type state
44
44
  },
45
45
  Publisher: Adapter.Publisher,
46
- ): (
47
- T with module Spec = Spec
48
- ) => {
46
+ ): (T with module Spec = Spec) => {
49
47
  module Spec = Spec
50
48
 
51
49
  type constructed
@@ -5,9 +5,9 @@ type outputs = ReventlessInfra.StateViewSlice.outputs
5
5
  type operations = ReventlessInfra.StateViewSlice.operations
6
6
  type component = Component.t<t, outputs, operations>
7
7
 
8
- let toResolvedOutputs = (
9
- outputs: outputs,
10
- ): Pulumi.Output.t<ReventlessInterop.StateViewSlice.resolvedOutputs> =>
8
+ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
9
+ ReventlessInterop.StateViewSlice.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.StateViewSlice.resolvedOutputs = {
18
- resources: resources,
18
+ resources,
19
19
  queryDb: {resources: queryDbResources},
20
20
  }
21
21
  resolved
@@ -38,9 +38,15 @@ module Make = (
38
38
  }
39
39
 
40
40
  module SpecificQueryDb = QueryDb_Builder.Make(SvQueryDbSpec, QueryDbStorage, QueryDbResolvers)
41
- module SpecificEventCollector = EventCollector_Builder.Make(RuntimeEnvironment, EventCollectorChannel)
42
-
43
- let toProjectionOps = (ops: SpecificQueryDb.operations): QueryDb.operations<string, Spec.state> => {
41
+ module SpecificEventCollector = EventCollector_Builder.Make(
42
+ RuntimeEnvironment,
43
+ EventCollectorChannel,
44
+ )
45
+
46
+ let toProjectionOps = (ops: SpecificQueryDb.operations): QueryDb.operations<
47
+ string,
48
+ Spec.state,
49
+ > => {
44
50
  load: id => ops.load(id->Reventless.Id.String.makeFromString),
45
51
  loadStream: id => ops.loadStream(id->Reventless.Id.String.makeFromString),
46
52
  save: (id, s, sm, ttl) => ops.save(id->Reventless.Id.String.makeFromString, s, sm, ttl),
@@ -94,32 +100,31 @@ module Make = (
94
100
  ->Effect.flatMap(events => {
95
101
  let total = events->Array.length->Int.toString
96
102
  events
97
- ->Array.mapWithIndex((json, i) => {
98
- let envelopeDict = json->JSON.Decode.object->Option.getOr(Dict.make())
99
- let rawEvent = envelopeDict->Dict.get("event")->Option.getOr(json)
100
- // Events arrive as `{id, meta, recordedAt, event}` envelopes
101
- // (Message.composeEventJson' / ProjectionCheckpoint catch-up).
102
- // Surface `meta` + `recordedAt` to the projection as `consumed`;
103
- // fall back defensively so a malformed envelope never drops the event.
104
- let meta = switch envelopeDict->Dict.get("meta") {
105
- | Some(m) =>
106
- switch m->Reventless.Util_Sury.fromJson(Message.metaSchema) {
107
- | parsed => parsed
108
- | exception _ => Message.generateMeta(~service=Spec.name)
103
+ ->Array.mapWithIndex(
104
+ (json, i) => {
105
+ let envelopeDict = json->JSON.Decode.object->Option.getOr(Dict.make())
106
+ let rawEvent = envelopeDict->Dict.get("event")->Option.getOr(json)
107
+ // Events arrive as `{id, meta, recordedAt, event}` envelopes
108
+ // (Message.composeEventJson' / ProjectionCheckpoint catch-up).
109
+ // Surface `meta` + `recordedAt` to the projection as `consumed`;
110
+ // fall back defensively so a malformed envelope never drops the event.
111
+ let meta = switch envelopeDict->Dict.get("meta") {
112
+ | Some(m) =>
113
+ switch m->Reventless.Util_Sury.fromJson(Message.metaSchema) {
114
+ | parsed => parsed
115
+ | exception _ => Message.generateMeta(~service=Spec.name)
116
+ }
117
+ | None => Message.generateMeta(~service=Spec.name)
109
118
  }
110
- | None => Message.generateMeta(~service=Spec.name)
111
- }
112
- let recordedAt =
113
- envelopeDict
114
- ->Dict.get("recordedAt")
115
- ->Option.flatMap(JSON.Decode.string)
116
- ->Option.getOr("")
117
- let (eventType, dataDict) = rawEvent->Message.splitMessage
118
- switch decoder.decode(~eventType, ~data=dataDict) {
119
- | Some(event) =>
120
- let actions =
121
- try Projection.project({event, meta, recordedAt})
122
- catch {
119
+ let recordedAt =
120
+ envelopeDict
121
+ ->Dict.get("recordedAt")
122
+ ->Option.flatMap(JSON.Decode.string)
123
+ ->Option.getOr("")
124
+ let (eventType, dataDict) = rawEvent->Message.splitMessage
125
+ switch decoder.decode(~eventType, ~data=dataDict) {
126
+ | Some(event) =>
127
+ let actions = try Projection.project({event, meta, recordedAt}) catch {
123
128
  | exn =>
124
129
  let errMsg =
125
130
  exn
@@ -132,46 +137,56 @@ module Make = (
132
137
  )->Effect.runSync
133
138
  []
134
139
  }
135
- let idxStr = (i + 1)->Int.toString
136
- let actionsStr = LogFormat.actionNames(actions)
137
- let eventData = dataDict->JSON.Encode.object
138
- let fieldsStr = {
139
- let f =
140
- dataDict
141
- ->Dict.toArray
142
- ->Array.map(((k, v)) => `${k}:${v->JSON.stringify}`)
143
- ->Array.join(",")
144
- f == "" ? "" : `({${f}})`
140
+ let idxStr = (i + 1)->Int.toString
141
+ let actionsStr = LogFormat.actionNames(actions)
142
+ let eventData = dataDict->JSON.Encode.object
143
+ let fieldsStr = {
144
+ let f =
145
+ dataDict
146
+ ->Dict.toArray
147
+ ->Array.map(((k, v)) => `${k}:${v->JSON.stringify}`)
148
+ ->Array.join(",")
149
+ f == "" ? "" : `({${f}})`
150
+ }
151
+ EffectLogger.logInfo(
152
+ ~comp,
153
+ ~detail=eventData,
154
+ `handling event ${idxStr}/${total}: ${LogFormat.bold(
155
+ eventType,
156
+ )}${fieldsStr} ${actionsStr}`,
157
+ )->Effect.runSync
158
+ // A slice's state carries the same synthetic `displayName` the
159
+ // ppx injects for a read model's, and the same lifecycle trail.
160
+ // Rewritten here rather than at the apply below because the
161
+ // trail entry is stamped with this envelope's own time.
162
+ actions->Array.map(
163
+ FrameworkProjection.rewriteAction(_, ~at=meta.time, Spec.stateSchema),
164
+ )
165
+ | None => []
145
166
  }
146
- EffectLogger.logInfo(
147
- ~comp,
148
- ~detail=eventData,
149
- `handling event ${idxStr}/${total}: ${LogFormat.bold(eventType)}${fieldsStr} ${actionsStr}`,
150
- )->Effect.runSync
151
- // A slice's state carries the same synthetic `displayName` the
152
- // ppx injects for a read model's, and the same lifecycle trail.
153
- // Rewritten here rather than at the apply below because the
154
- // trail entry is stamped with this envelope's own time.
155
- actions->Array.map(
156
- FrameworkProjection.rewriteAction(_, ~at=meta.time, Spec.stateSchema),
157
- )
158
- | None => []
159
- }
160
- })
167
+ },
168
+ )
161
169
  ->Array.flat
162
- ->Array.reduce(Effect.succeed(), (acc, action) =>
163
- acc->Effect.flatMap(_ => {
164
- Effect.promise(() =>
165
- FrameworkProjection.handleAction(~comp, action, projectionOps, Spec.subIdConfig)
166
- )->Effect.map(_ => ())
167
- })
170
+ ->Array.reduce(
171
+ Effect.succeed(),
172
+ (acc, action) =>
173
+ acc->Effect.flatMap(
174
+ _ => {
175
+ Effect.promise(
176
+ () =>
177
+ FrameworkProjection.handleAction(
178
+ ~comp,
179
+ action,
180
+ projectionOps,
181
+ Spec.subIdConfig,
182
+ ),
183
+ )->Effect.map(_ => ())
184
+ },
185
+ ),
168
186
  )
169
187
  })
170
188
 
171
- let handler = SpecificEventCollector.makeHandler(
172
- ~eventCollector=ec,
173
- ~jsonEventsHandler,
174
- )
189
+ let handler = SpecificEventCollector.makeHandler(~eventCollector=ec, ~jsonEventsHandler)
175
190
  let resources = (queryDb->Component.outputs).resources
176
191
  ec->EventCollectorRuntimeBuilder.forEventCollector(
177
192
  ~handler,
@@ -199,11 +214,7 @@ module Make = (
199
214
  self->Component.setOutputs(outputs)
200
215
  }
201
216
 
202
- let make = (
203
- ~dcbEventLog,
204
- ~runtime=?,
205
- ~opts=?,
206
- ): StateViewSlice.component =>
217
+ let make = (~dcbEventLog, ~runtime=?, ~opts=?): StateViewSlice.component =>
207
218
  Component.make(
208
219
  ~componentType=StateViewSlice.componentType->ComponentType.toString,
209
220
  ~name=Spec.name,
@@ -45,7 +45,9 @@ module Make = (
45
45
  EffectLogger.logInfo(
46
46
  ~comp,
47
47
  ~detail=raw.data,
48
- `handling event ${idx.contents->Int.toString}/${count}: ${LogFormat.bold(raw.eventType)}(${id}) ${actionsStr}`,
48
+ `handling event ${idx.contents->Int.toString}/${count}: ${LogFormat.bold(
49
+ raw.eventType,
50
+ )}(${id}) ${actionsStr}`,
49
51
  )->Effect.runSync
50
52
  allActions->Array.pushMany(
51
53
  actions->Array.map(
@@ -34,9 +34,9 @@ type maker = (
34
34
  ~opts: option<Pulumi.ComponentResource.options>,
35
35
  ) => component
36
36
 
37
- let toResolvedOutputs = (
38
- outputs: outputs,
39
- ): Pulumi.Output.t<ReventlessInterop.Task.resolvedOutputs> =>
37
+ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
38
+ ReventlessInterop.Task.resolvedOutputs,
39
+ > =>
40
40
  switch (outputs.bucketNames, outputs.sideEffectSources) {
41
41
  | (Some(bucketNames), Some(sideEffectSources)) =>
42
42
  bucketNames
@@ -1,4 +1,7 @@
1
- type bucket<'bucketParts> = {resources: array<ReventlessInfra.Adapter.resource>, parts: 'bucketParts}
1
+ type bucket<'bucketParts> = {
2
+ resources: array<ReventlessInfra.Adapter.resource>,
3
+ parts: 'bucketParts,
4
+ }
2
5
 
3
6
  type connect<'bucketParts, 'runtimeParts> = (
4
7
  ~name: string,
@@ -17,8 +17,8 @@ let pascalCase = s =>
17
17
  // Split words out of a PascalCase/camelCase run so kebab-casing keeps the word
18
18
  // boundaries. Two passes: `aB` splits an ordinary hump, `ABc` splits the tail of
19
19
  // an acronym off the word that follows it ("HTTPServer" -> "HTTP-Server").
20
- let humpBoundary = %re("/([a-z0-9])([A-Z])/g")
21
- let acronymBoundary = %re("/([A-Z]+)([A-Z][a-z])/g")
20
+ let humpBoundary = /([a-z0-9])([A-Z])/g
21
+ let acronymBoundary = /([A-Z]+)([A-Z][a-z])/g
22
22
 
23
23
  // Kebab-case an identifier for use in an S3 bucket name: "ImportProducts" and
24
24
  // "product-imports" both reduce to "import-products".
@@ -119,7 +119,10 @@ module Make = (
119
119
  // Task bucket callbacks default to the platform-supplied task-pod floor (a
120
120
  // large envelope for bulk import/export work); a plugin.json `runtime`
121
121
  // override raises memory above it and replaces timeout.
122
- let memorySize = ReventlessInfra.RuntimeHints.resolveMemory(runtime, ~default=Defaults.memorySize)
122
+ let memorySize = ReventlessInfra.RuntimeHints.resolveMemory(
123
+ runtime,
124
+ ~default=Defaults.memorySize,
125
+ )
123
126
  let timeout = ReventlessInfra.RuntimeHints.resolveTimeout(runtime, ~default=Defaults.timeout)
124
127
  let allCommandTopics = allAggregates->Aggregate.allCommandTopics
125
128
 
@@ -128,15 +131,14 @@ module Make = (
128
131
  // first command-topic resource's `id` — bundled adapters interpret it as
129
132
  // their channel address; adapters that don't need it (e.g. in-memory)
130
133
  // ignore the dict in their TaskRuntime_Builder.
131
- let publishToAggregatesQueueUrls =
132
- allAggregates->Dict.mapValues(agg =>
133
- agg.commandTopic->Pulumi.Output.flatMap(ct =>
134
- switch ct.resources->Array.get(0) {
135
- | Some(r) => r.id
136
- | None => Pulumi.Output.make("")
137
- }
138
- )
134
+ let publishToAggregatesQueueUrls = allAggregates->Dict.mapValues(agg =>
135
+ agg.commandTopic->Pulumi.Output.flatMap(ct =>
136
+ switch ct.resources->Array.get(0) {
137
+ | Some(r) => r.id
138
+ | None => Pulumi.Output.make("")
139
+ }
139
140
  )
141
+ )
140
142
 
141
143
  let publishCommands: Task.publishCommands = (aggregateName, cmdJsons) => {
142
144
  (publishToAggregates->Dict.get(aggregateName)->Option.getOrThrow)(cmdJsons)
@@ -218,17 +220,18 @@ module Make = (
218
220
  // scheduler's invoker URN. Bundled adapters thread these into the
219
221
  // deployed handler so it can talk to the underlying scheduler service;
220
222
  // adapters without a real scheduler ignore the dict.
221
- let schedulerConfig: option<TaskRuntime_Builder.schedulerConfig> =
222
- sideEffectHandler->Option.flatMap(seh => {
223
- let sehOutputs = seh->Component.outputs
224
- sehOutputs.eventCollector.resources
225
- ->Array.get(0)
226
- ->Option.map(r => {
227
- TaskRuntime_Builder.schedulerRoleUrn: schedulerRoleUrn,
228
- targetUrn: r.urn,
229
- targetName: r.name,
230
- })
223
+ let schedulerConfig: option<
224
+ TaskRuntime_Builder.schedulerConfig,
225
+ > = sideEffectHandler->Option.flatMap(seh => {
226
+ let sehOutputs = seh->Component.outputs
227
+ sehOutputs.eventCollector.resources
228
+ ->Array.get(0)
229
+ ->Option.map(r => {
230
+ TaskRuntime_Builder.schedulerRoleUrn,
231
+ targetUrn: r.urn,
232
+ targetName: r.name,
231
233
  })
234
+ })
232
235
 
233
236
  let bucketNames = config.buckets->Option.map(buckets =>
234
237
  buckets