@reventlessdev/reventless-aws 3.0.0-alpha.344 → 3.0.0-alpha.345

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 (232) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/package.json +11 -11
  3. package/scripts/ProvisionIdentity.res +8 -3
  4. package/src/Platform.res +327 -328
  5. package/src/Platform.res.mjs +4 -2
  6. package/src/Platform_Casts.res +13 -4
  7. package/src/adapter/Api/AppSyncEventsSigner_Ops.res +8 -4
  8. package/src/adapter/Api/AppSync_EventsApi.res +12 -14
  9. package/src/adapter/Api/AppSync_Resolver_Native.res +3 -4
  10. package/src/adapter/Api/AppSync_Resolver_Retrying.res +78 -70
  11. package/src/adapter/Api/AppSync_SourceApiAssociation_Retrying.res +11 -8
  12. package/src/adapter/Api/Platform_AdminScan_Ops.res +15 -14
  13. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +10 -2
  14. package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +40 -50
  15. package/src/adapter/Api/Platform_UIFragments_Lambda.res +39 -32
  16. package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +5 -2
  17. package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +0 -1
  18. package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -2
  19. package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res +1 -4
  20. package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +5 -2
  21. package/src/adapter/Auth/Auth_Cognito.res +3 -9
  22. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res +1 -4
  23. package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res +3 -1
  24. package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res +1 -4
  25. package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +7 -4
  26. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +6 -1
  27. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +7 -4
  28. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res +24 -18
  29. package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +9 -4
  30. package/src/adapter/CommandTopic/CommandTopicRegistry.res +1 -4
  31. package/src/adapter/Counter/CounterHandler_DynamoDbStream.res +15 -15
  32. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res +9 -5
  33. package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +179 -213
  34. package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +5 -5
  35. package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res +6 -2
  36. package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +14 -7
  37. package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +14 -7
  38. package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res +6 -3
  39. package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res +6 -1
  40. package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +13 -17
  41. package/src/adapter/EventLog/EventLogStorage_Postgres.res +7 -4
  42. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +12 -7
  43. package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +4 -2
  44. package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res +3 -2
  45. package/src/adapter/EventTopic/EventTopicPublisher_SNS.res +20 -12
  46. package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res +21 -9
  47. package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res +5 -3
  48. package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +6 -3
  49. package/src/adapter/Mcp/MCP_Lambda.res +31 -46
  50. package/src/adapter/Messaging/Messaging_Ses_Backend.res +11 -7
  51. package/src/adapter/Messaging/Messaging_Ses_Backend.res.mjs +2 -4
  52. package/src/adapter/Monitoring/Monitoring_CloudWatch.res +16 -16
  53. package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +5 -10
  54. package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +4 -2
  55. package/src/adapter/Postgres/PgConnection.res +6 -5
  56. package/src/adapter/Postgres/PgMigration_Builder.res +4 -8
  57. package/src/adapter/Postgres/PgRuntime.res +4 -7
  58. package/src/adapter/QueryDb/PgQueryResolver_Builder.res +9 -11
  59. package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +22 -21
  60. package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +114 -111
  61. package/src/adapter/QueryDb/QueryDbResolvers_Lambda.res +1 -7
  62. package/src/adapter/QueryDb/QueryDbStorage.res +4 -2
  63. package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res +23 -24
  64. package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res +8 -2
  65. package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res +71 -73
  66. package/src/adapter/QueryDb/QueryDbStorage_Postgres.res +5 -2
  67. package/src/adapter/QueryDb/QueryInterceptor_Provisioning.res +1 -4
  68. package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +8 -2
  69. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +73 -81
  70. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +72 -78
  71. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +44 -67
  72. package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res +44 -67
  73. package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +53 -82
  74. package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +47 -77
  75. package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +18 -11
  76. package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -97
  77. package/src/adapter/Runtime/CounterEntryPoint_Ops.res +2 -7
  78. package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -10
  79. package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +24 -15
  80. package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +17 -37
  81. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +31 -57
  82. package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +18 -24
  83. package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +1 -5
  84. package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +4 -3
  85. package/src/adapter/Runtime/HeartbeatEntryPoint.res +0 -1
  86. package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +4 -2
  87. package/src/adapter/Runtime/PgMigrationEntryPoint.res +0 -1
  88. package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +3 -2
  89. package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +1 -2
  90. package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +4 -5
  91. package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +22 -10
  92. package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +8 -2
  93. package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res +14 -31
  94. package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +16 -17
  95. package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +10 -9
  96. package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +46 -52
  97. package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +36 -41
  98. package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +31 -37
  99. package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +6 -7
  100. package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res +4 -6
  101. package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res +2 -6
  102. package/src/adapter/StateTopic/StateTopic_AppSync.res +21 -16
  103. package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +36 -32
  104. package/src/adapter/Task/TaskBucket_S3.res +6 -1
  105. package/src/adapter/Upload/Upload_Claim_S3.res +17 -20
  106. package/src/adapter/Upload/Upload_Claim_S3_Ops.res +5 -2
  107. package/src/adapter/Upload/Upload_Presign_S3.res +51 -49
  108. package/src/capability/Capability_Geocoding_AwsLocation.res +4 -1
  109. package/src/capability/Capability_Messaging.res +4 -5
  110. package/src/capability/Capability_Messaging_Ses.res +3 -1
  111. package/src/capability/Capability_ObjectStore_S3.res +1 -7
  112. package/src/components/Api/AppSync_Adapter.res +28 -41
  113. package/src/components/Api/AppSync_SdlDecorate.res +38 -30
  114. package/src/components/AutomationSlice_Builder.res +6 -4
  115. package/src/components/ExtensionPoint_Builder.res +9 -10
  116. package/src/components/InboundTranslationSlice_Builder.res +7 -8
  117. package/src/components/OutboundTranslationSlice_Builder.res +14 -8
  118. package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
  119. package/src/components/SideEffectHandler_Single.res +4 -4
  120. package/src/components/StateViewSlice_Builder.res +6 -4
  121. package/src/components/StateViewSlice_Builder_Stream.res +6 -4
  122. package/src/components/Task_Builder_PerBucket.res +10 -11
  123. package/src/plugin/cloner/ClonerRunner_Fargate.res +3 -10
  124. package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res +1 -4
  125. package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res +5 -5
  126. package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +19 -21
  127. package/src/plugin/runtime/PluginRuntime_Builder.res +167 -188
  128. package/src/plugin/runtime/Util_PluginMessage_Runtime.res +6 -5
  129. package/src/plugin/stack/Plugin_Stack.res +104 -103
  130. package/src/util/Util_AlarmSpec.res +2 -1
  131. package/src/util/Util_AppSync.res +8 -2
  132. package/src/util/Util_AppSync_Caller.res +15 -14
  133. package/src/util/Util_Bundle.res +46 -42
  134. package/src/util/Util_CognitoGroupUser_Runtime.res +32 -34
  135. package/src/util/Util_Cognito_Runtime.res +11 -7
  136. package/src/util/Util_DeadLetterQueue.res +12 -2
  137. package/src/util/Util_DynamoDb.res +5 -3
  138. package/src/util/Util_DynamoDbStream.res +7 -3
  139. package/src/util/Util_DynamoDbStream_Runtime.res +1 -2
  140. package/src/util/Util_DynamoDb_Runtime.res +23 -41
  141. package/src/util/Util_HostUiDomain.res +6 -1
  142. package/src/util/Util_Kinesis_Runtime.res +10 -11
  143. package/src/util/Util_Lambda.res +12 -5
  144. package/src/util/Util_LambdaEnvBudget.res +5 -5
  145. package/src/util/Util_LambdaLogging.res +1 -2
  146. package/src/util/Util_LogGroup_Adopting.res +1 -4
  147. package/src/util/Util_ResourceNaming.res +1 -2
  148. package/src/util/Util_SNS.res +8 -3
  149. package/src/util/Util_SNS_FIFO.res +1 -1
  150. package/src/util/Util_SNS_Runtime.res +11 -10
  151. package/src/util/Util_SQS.res +4 -2
  152. package/src/util/Util_SQS_FIFO.res +5 -2
  153. package/src/util/Util_SQS_Runtime.res +37 -36
  154. package/src/util/Util_ShellConfig.res +3 -2
  155. package/src/util/Util_StaticBundle.res +1 -3
  156. package/src/util/Util_StoreLayout.res +4 -1
  157. package/tests/AWS_TagsTest.res +16 -5
  158. package/tests/AppSyncEventsSigner_OpsTest.res +11 -2
  159. package/tests/AppSync_AdapterTest.res +203 -224
  160. package/tests/AppSync_Resolver_RetryingTest.res +64 -44
  161. package/tests/AppSync_RetirementNarrowingTest.res +59 -46
  162. package/tests/AppSync_SdlDecorateTest.res +22 -20
  163. package/tests/AppSync_SourceApiAssociation_RetryingTest.res +40 -22
  164. package/tests/Auth_ActiveRolePoolAttachmentTest.res +114 -107
  165. package/tests/Auth_ActiveRoleStoreTest.res +12 -9
  166. package/tests/Auth_ActiveRoleStore_SchemaTest.res +2 -1
  167. package/tests/Auth_ActiveRoleTrigger_OpsTest.res +20 -16
  168. package/tests/Auth_CognitoTest.res +31 -46
  169. package/tests/AutomationSliceEntryPoint_OpsTest.res +69 -67
  170. package/tests/BakeConvergenceTest.res +22 -25
  171. package/tests/Capability_MessagingTest.res +28 -12
  172. package/tests/CommandTopicQueuePolicyTest.res +1 -2
  173. package/tests/CounterEntryPoint_OpsTest.res +3 -7
  174. package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +306 -210
  175. package/tests/EventCollectorConnectLambdaPreviewTest.res +14 -7
  176. package/tests/EventCollectorEntryPoint_OpsTest.res +12 -4
  177. package/tests/EventCollectorPluginDefinitionAssetTest.res +18 -11
  178. package/tests/EventCollectorReadyGateTest.res +5 -4
  179. package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +1 -2
  180. package/tests/EventMapperEntryPoint_OpsTest.res +1 -3
  181. package/tests/ExtensionPointEntryPoint_OpsTest.res +1 -4
  182. package/tests/HandlerFactoryDispatchTest.res +97 -70
  183. package/tests/MCP_LambdaTest.res +16 -27
  184. package/tests/PgChangeFeedRelay_IntegrationTest.res +123 -93
  185. package/tests/PgChangeFeedRelay_RuntimeTest.res +13 -10
  186. package/tests/PgMigrationEntryPoint_IntegrationTest.res +0 -1
  187. package/tests/PgPipeline_IntegrationTest.res +80 -66
  188. package/tests/PgQueryDbUnion_IntegrationTest.res +1 -2
  189. package/tests/PgQueryResolverEntryPoint_OpsTest.res +2 -6
  190. package/tests/PgQueryResolver_LambdaTest.res +41 -24
  191. package/tests/Platform_AdminScan_OpsTest.res +4 -1
  192. package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res +137 -129
  193. package/tests/ProjectionEntryPoint_DisplayNameTest.res +7 -3
  194. package/tests/ProjectionEntryPoint_UnionStampTest.res +3 -2
  195. package/tests/ProvisionIdentityTest.res +2 -6
  196. package/tests/QueryDbOwnerIndexTableTest.res +6 -4
  197. package/tests/QueryDbResolvers_AppSyncTest.res +23 -16
  198. package/tests/QueryInterceptor_LambdaTest.res +11 -13
  199. package/tests/ReadModelEntryPoint_OpsTest.res +43 -41
  200. package/tests/RuntimeExtensionEntryPoint_OpsTest.res +4 -3
  201. package/tests/SideEffectEntryPoint_OpsTest.res +23 -18
  202. package/tests/StateChangeDescriptorParityTest.res +28 -26
  203. package/tests/StateTopicKeySchemaTest.res +18 -15
  204. package/tests/StateViewSliceEntryPoint_OpsTest.res +55 -44
  205. package/tests/TaskBucketEntryPoint_OpsTest.res +13 -13
  206. package/tests/Upload_ClaimTest.res +3 -3
  207. package/tests/Util_AwsErrorTest.res +4 -7
  208. package/tests/Util_BundleDependencyClosureTest.res +15 -3
  209. package/tests/Util_BundleEsmLoaderTest.res +3 -3
  210. package/tests/Util_BundleResolveTest.res +4 -6
  211. package/tests/Util_BundleRuntimeExtensionTest.res +17 -18
  212. package/tests/Util_DcbMetricsTest.res +6 -6
  213. package/tests/Util_DynamoDbStreamTest.res +4 -5
  214. package/tests/Util_DynamoDbTest.res +3 -2
  215. package/tests/Util_LambdaEnvBudgetTest.res +22 -18
  216. package/tests/Util_LambdaLoggingTest.res +9 -8
  217. package/tests/Util_LogGroup_AdoptingTest.res +10 -5
  218. package/tests/Util_LogRetentionTest.res +6 -2
  219. package/tests/Util_OwnerScopeEnvTest.res +10 -8
  220. package/tests/Util_SQS_RuntimeTest.res +5 -7
  221. package/tests/Util_ShellConfigTest.res +7 -17
  222. package/tests/Util_StaticBundleTest.res +3 -8
  223. package/tests/Util_StoreLayoutTest.res +17 -12
  224. package/tests/integration/AggregateEntryPoint_IntegrationTest.res +1 -4
  225. package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +15 -15
  226. package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +296 -232
  227. package/tests/integration/DcbIntegrationHarness.res +8 -8
  228. package/tests/integration/EpCompositeSlice.res +16 -8
  229. package/tests/integration/QueryDbUnion_DynamoDb_IntegrationTest.res +8 -10
  230. package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +10 -10
  231. package/tests/integration/SvsTestSlice_Projection.res +1 -3
  232. package/tests/util/Util_AlarmSpecTest.res +62 -49
@@ -34,10 +34,9 @@ let make: ReventlessCore.DcbEventLog_Adapter.storageMaker = (
34
34
  let globalSecondaryIndexes =
35
35
  indexes
36
36
  ->Array.map(indexName => {
37
- let projectionType =
38
- DcbEventLogStorage_DynamoDb_Runtime.indexKeepsFullProjection(indexName)
39
- ? PulumiAws.DynamoDb.Table.ALL
40
- : PulumiAws.DynamoDb.Table.KEYS_ONLY
37
+ let projectionType = DcbEventLogStorage_DynamoDb_Runtime.indexKeepsFullProjection(indexName)
38
+ ? PulumiAws.DynamoDb.Table.ALL
39
+ : PulumiAws.DynamoDb.Table.KEYS_ONLY
41
40
  {
42
41
  PulumiAws.DynamoDb.Table.name: indexName,
43
42
  hashKey: indexName,
@@ -50,7 +49,12 @@ let make: ReventlessCore.DcbEventLog_Adapter.storageMaker = (
50
49
 
51
50
  // Create DynamoDB table with stream enabled — EventTopicPublisher_DynamoDbStream
52
51
  // needs a DynamoDbStream resource to connect the EventTopic.
53
- let tags = AWS.Tags.make(~name, ~kind=ReventlessCore.ComponentType.Plugin, ~role=DcbEventLog, ~scope=Plugin)
52
+ let tags = AWS.Tags.make(
53
+ ~name,
54
+ ~kind=ReventlessCore.ComponentType.Plugin,
55
+ ~role=DcbEventLog,
56
+ ~scope=Plugin,
57
+ )
54
58
  let table = Util_DynamoDbStream.makeTable(
55
59
  name,
56
60
  ~attributes,
@@ -78,8 +78,7 @@ let derivePartitionKey = (
78
78
  | None => tags->Array.getUnsafe(0)
79
79
  }
80
80
  `${tag.key}:${tag.value}`
81
- | Some(Composite(spec)) =>
82
- Reventless.DcbTag.getCompositePartitionKeyValue(tags, spec)
81
+ | Some(Composite(spec)) => Reventless.DcbTag.getCompositePartitionKeyValue(tags, spec)
83
82
  }
84
83
  }
85
84
  }
@@ -102,10 +101,7 @@ let toItem = (
102
101
 
103
102
  // Add tags array
104
103
  let tagsJson = event.tags->Array.map(tag =>
105
- [
106
- ("key", tag.key->JSON.Encode.string),
107
- ("value", tag.value->JSON.Encode.string),
108
- ]
104
+ [("key", tag.key->JSON.Encode.string), ("value", tag.value->JSON.Encode.string)]
109
105
  ->Dict.fromArray
110
106
  ->JSON.Encode.object
111
107
  )
@@ -150,36 +146,39 @@ let fromItem = (item: JSON.t): ReventlessCore.DcbEventLog_Adapter.rawSequencedEv
150
146
  switch item->JSON.Decode.object {
151
147
  | None => JsError.throwWithMessage("Invalid DcbEventLog item: not an object")
152
148
  | Some(obj) =>
153
- let position = obj
154
- ->Dict.get("position")
155
- ->Option.flatMap(JSON.Decode.string)
156
- ->Option.getOrThrow
149
+ let position =
150
+ obj
151
+ ->Dict.get("position")
152
+ ->Option.flatMap(JSON.Decode.string)
153
+ ->Option.getOrThrow
157
154
 
158
- let eventType = obj
159
- ->Dict.get("event")
160
- ->Option.flatMap(JSON.Decode.string)
161
- ->Option.getOrThrow
155
+ let eventType =
156
+ obj
157
+ ->Dict.get("event")
158
+ ->Option.flatMap(JSON.Decode.string)
159
+ ->Option.getOrThrow
162
160
 
163
161
  let data = obj->Dict.get("data")->Option.getOrThrow
164
162
 
165
- let tags = obj
166
- ->Dict.get("tags")
167
- ->Option.flatMap(JSON.Decode.array)
168
- ->Option.mapOr([], tagArray =>
169
- tagArray->Array.filterMap(tagJson =>
170
- switch tagJson->JSON.Decode.object {
171
- | None => None
172
- | Some(tagObj) => {
173
- let key = tagObj->Dict.get("key")->Option.flatMap(JSON.Decode.string)
174
- let value = tagObj->Dict.get("value")->Option.flatMap(JSON.Decode.string)
175
- switch (key, value) {
176
- | (Some(k), Some(v)) => Some({Reventless.DcbTag.key: k, value: v})
177
- | _ => None
163
+ let tags =
164
+ obj
165
+ ->Dict.get("tags")
166
+ ->Option.flatMap(JSON.Decode.array)
167
+ ->Option.mapOr([], tagArray =>
168
+ tagArray->Array.filterMap(tagJson =>
169
+ switch tagJson->JSON.Decode.object {
170
+ | None => None
171
+ | Some(tagObj) => {
172
+ let key = tagObj->Dict.get("key")->Option.flatMap(JSON.Decode.string)
173
+ let value = tagObj->Dict.get("value")->Option.flatMap(JSON.Decode.string)
174
+ switch (key, value) {
175
+ | (Some(k), Some(v)) => Some({Reventless.DcbTag.key: k, value: v})
176
+ | _ => None
177
+ }
178
178
  }
179
179
  }
180
- }
180
+ )
181
181
  )
182
- )
183
182
 
184
183
  let recordedAt =
185
184
  obj
@@ -213,9 +212,7 @@ let queryByCompositeTags = async (
213
212
  let composite = compositeTagKey(tags)
214
213
  let indexName = "tag_composite"
215
214
 
216
- let expressionAttributeValues = Dict.fromArray([
217
- (":composite", composite->JSON.Encode.string),
218
- ])
215
+ let expressionAttributeValues = Dict.fromArray([(":composite", composite->JSON.Encode.string)])
219
216
 
220
217
  let (keyConditionExpression, expressionAttributeNames) = switch after {
221
218
  | None => ("tag_composite = :composite", None)
@@ -227,9 +224,9 @@ let queryByCompositeTags = async (
227
224
 
228
225
  let queryParams: QueryCommand.input = {
229
226
  tableName: table.name,
230
- indexName: indexName,
231
- keyConditionExpression: keyConditionExpression,
232
- expressionAttributeValues: expressionAttributeValues,
227
+ indexName,
228
+ keyConditionExpression,
229
+ expressionAttributeValues,
233
230
  ?expressionAttributeNames,
234
231
  }
235
232
 
@@ -315,9 +312,7 @@ let buildQueryByPartitionKeyInput = (
315
312
  ~after: option<string>=?,
316
313
  ~strongConsistency: bool=false,
317
314
  ): QueryCommand.input => {
318
- let expressionAttributeValues = Dict.fromArray([
319
- (":pk", partitionKey->JSON.Encode.string),
320
- ])
315
+ let expressionAttributeValues = Dict.fromArray([(":pk", partitionKey->JSON.Encode.string)])
321
316
  let (keyConditionExpression, expressionAttributeNames) = switch after {
322
317
  | None => ("id = :pk", None)
323
318
  | Some(afterPos) => {
@@ -401,16 +396,13 @@ let queryBySingleTagCrossPartitionStreamIndexed = (
401
396
  expressionAttributeNames,
402
397
  }
403
398
  Stream.paginateEffect((None: option<dict<JSON.t>>), cursor =>
404
- Effect.tryPromise(
405
- ~catch=DynamoDb_Error.classify,
406
- () => {
407
- let params = switch cursor {
408
- | None => baseParams
409
- | Some(key) => {...baseParams, exclusiveStartKey: key}
410
- }
411
- QueryCommand.send(params->QueryCommand.make)
412
- },
413
- )
399
+ Effect.tryPromise(~catch=DynamoDb_Error.classify, () => {
400
+ let params = switch cursor {
401
+ | None => baseParams
402
+ | Some(key) => {...baseParams, exclusiveStartKey: key}
403
+ }
404
+ QueryCommand.send(params->QueryCommand.make)
405
+ })
414
406
  ->Effect.retry(DynamoDb_Error.retrySchedule)
415
407
  ->Effect.catchAll(err => Effect.fail(DynamoDb_Error.message(err)))
416
408
  ->Effect.map(result => (
@@ -458,12 +450,10 @@ let executeQueryItem = async (
458
450
  await queryBySingleTagCrossPartitionStream(table, tag, ~after?)
459
451
  ->Stream.runCollect
460
452
  ->Effect.runPromise
461
- | Some([tag]) =>
462
- await queryByPartitionKey(table, `${tag.key}:${tag.value}`, ~after?)
453
+ | Some([tag]) => await queryByPartitionKey(table, `${tag.key}:${tag.value}`, ~after?)
463
454
 
464
455
  // Multiple tags: use composite GSI
465
- | Some(tags) if tags->Array.length > 1 =>
466
- await queryByCompositeTags(table, tags, ~after?)
456
+ | Some(tags) if tags->Array.length > 1 => await queryByCompositeTags(table, tags, ~after?)
467
457
 
468
458
  // No tags (or empty): fall back to scan
469
459
  | None | Some([]) | Some(_) =>
@@ -513,17 +503,13 @@ let initSlot = (
513
503
  Queue.bounded(1)->Effect.flatMap(queue => {
514
504
  let producer =
515
505
  stream
516
- ->Stream.runForEach(event =>
517
- Queue.offer(queue, Some(event))->Effect.map(_ => ())
518
- )
506
+ ->Stream.runForEach(event => Queue.offer(queue, Some(event))->Effect.map(_ => ()))
519
507
  // Always push the None sentinel so the merge loop can detect exhaustion,
520
508
  // even if the stream fails (stream error is suppressed to prevent an
521
509
  // unhandled-fiber-failure warning).
522
510
  ->Effect.ensuring(Queue.offer(queue, None)->Effect.map(_ => ()))
523
- ->Effect.catchAll(_ => Effect.succeed(()))
524
- Effect.fork(producer)->Effect.flatMap(_ =>
525
- Queue.take(queue)->Effect.map(head => {queue, head})
526
- )
511
+ ->Effect.catchAll(_ => Effect.succeed())
512
+ Effect.fork(producer)->Effect.flatMap(_ => Queue.take(queue)->Effect.map(head => {queue, head}))
527
513
  })
528
514
 
529
515
  // Returns the index of the slot with the smallest position, or None if all exhausted.
@@ -536,8 +522,7 @@ let findMinSlotIdx = (slots: array<mergeSlot>) =>
536
522
  let minSlot = slots->Array.getUnsafe(minIdx)
537
523
  switch minSlot.head {
538
524
  | None => Some(idx)
539
- | Some(minHead) =>
540
- String.compare(head.position, minHead.position) < 0. ? Some(idx) : minOpt
525
+ | Some(minHead) => String.compare(head.position, minHead.position) < 0. ? Some(idx) : minOpt
541
526
  }
542
527
  }
543
528
  )
@@ -550,7 +535,7 @@ let dedupByPosition = (
550
535
  let lastPos: ref<option<string>> = ref(None)
551
536
  stream->Stream.filter(event =>
552
537
  switch lastPos.contents {
553
- | Some(pos) when pos == event.position => false
538
+ | Some(pos) if pos == event.position => false
554
539
  | _ =>
555
540
  lastPos := Some(event.position)
556
541
  true
@@ -576,17 +561,20 @@ let mergeSortedEvents = (
576
561
  | Some(idx) =>
577
562
  let slot = slots->Array.getUnsafe(idx)
578
563
  let emitEvent = slot.head->Option.getOrThrow
579
- Queue.take(slot.queue)->Effect.map(nextHead => {
580
- let newSlots = slots->Array.mapWithIndex((s, i) =>
581
- if i == idx {
582
- {...s, head: nextHead}
583
- } else {
584
- s
585
- }
586
- )
587
- let hasActive = newSlots->Array.some(s => s.head->Option.isSome)
588
- ([emitEvent], hasActive ? Some(newSlots) : None)
589
- })
564
+ Queue.take(slot.queue)->Effect.map(
565
+ nextHead => {
566
+ let newSlots = slots->Array.mapWithIndex(
567
+ (s, i) =>
568
+ if i == idx {
569
+ {...s, head: nextHead}
570
+ } else {
571
+ s
572
+ },
573
+ )
574
+ let hasActive = newSlots->Array.some(s => s.head->Option.isSome)
575
+ ([emitEvent], hasActive ? Some(newSlots) : None)
576
+ },
577
+ )
590
578
  }
591
579
  )
592
580
  )
@@ -594,10 +582,7 @@ let mergeSortedEvents = (
594
582
  // --- Main Operations ---
595
583
 
596
584
  let read = (table: resolvedTable, ~crossPartitionTagKeys: array<string>=[]) =>
597
- async (
598
- ~query: Reventless.DcbTag.query,
599
- ~after=?,
600
- ) => {
585
+ async (~query: Reventless.DcbTag.query, ~after=?) => {
601
586
  // Execute queries for each queryItem
602
587
  let queryResults = await query
603
588
  ->Array.map(queryItem => executeQueryItem(table, queryItem, ~after?, ~crossPartitionTagKeys))
@@ -609,15 +594,15 @@ let read = (table: resolvedTable, ~crossPartitionTagKeys: array<string>=[]) =>
609
594
  let deduplicatedEvents = deduplicateByPosition(allEvents)
610
595
 
611
596
  // Sort by position
612
- let sortedEvents = deduplicatedEvents->Array.toSorted((a, b) =>
613
- String.compare(a.position, b.position)
614
- )
597
+ let sortedEvents =
598
+ deduplicatedEvents->Array.toSorted((a, b) => String.compare(a.position, b.position))
615
599
 
616
600
  // Get head position (latest position)
617
- let headPosition = sortedEvents
618
- ->Array.toReversed
619
- ->Array.at(0)
620
- ->Option.map(event => event.position)
601
+ let headPosition =
602
+ sortedEvents
603
+ ->Array.toReversed
604
+ ->Array.at(0)
605
+ ->Option.map(event => event.position)
621
606
 
622
607
  {
623
608
  ReventlessCore.DcbEventLog_Adapter.events: sortedEvents,
@@ -679,9 +664,9 @@ let collectQueryTags = (query: Reventless.DcbTag.query): array<Reventless.DcbTag
679
664
  acc
680
665
  }
681
666
 
682
- let collectEventTags = (
683
- events: array<ReventlessCore.DcbEventLog_Adapter.rawStoredEvent>,
684
- ): array<Reventless.DcbTag.tag> => {
667
+ let collectEventTags = (events: array<ReventlessCore.DcbEventLog_Adapter.rawStoredEvent>): array<
668
+ Reventless.DcbTag.tag,
669
+ > => {
685
670
  let seen = Set.make()
686
671
  let acc = []
687
672
  events->Array.forEach(event =>
@@ -722,9 +707,9 @@ let dedupStrings = (xs: array<string>): array<string> => {
722
707
  // tagKey ("key:value") -> distinct event types among `events` that CARRY the tag.
723
708
  // Used to advance the fences of composite query tags and cross-partition tags
724
709
  // (bumped by every carrier), and by `appendUnconditional`.
725
- let carriedTypesByTag = (
726
- events: array<ReventlessCore.DcbEventLog_Adapter.rawStoredEvent>,
727
- ): Dict.t<array<string>> => {
710
+ let carriedTypesByTag = (events: array<ReventlessCore.DcbEventLog_Adapter.rawStoredEvent>): Dict.t<
711
+ array<string>,
712
+ > => {
728
713
  let d = Dict.make()
729
714
  events->Array.forEach(e =>
730
715
  e.tags->Array.forEach((t: Reventless.DcbTag.tag) => {
@@ -897,7 +882,7 @@ let buildEventPuts = (
897
882
  let recordedAt = ReventlessCore.Message.nowAsISOString()
898
883
  let item = toItem(position, event, ~partitionTag?, ~recordedAt)
899
884
  let put: TransactWriteCommand.put = {
900
- TransactWriteCommand.item: item,
885
+ TransactWriteCommand.item,
901
886
  tableName: table.name,
902
887
  }
903
888
  {TransactWriteCommand.put: put}
@@ -908,7 +893,9 @@ let runTransactWrite = async (
908
893
  basePosition: string,
909
894
  ~errorPrefix: string,
910
895
  ) =>
911
- await Effect.tryPromise(~catch=DynamoDb_Error.classify, () => input->TransactWriteCommand.make->TransactWriteCommand.send)
896
+ await Effect.tryPromise(~catch=DynamoDb_Error.classify, () =>
897
+ input->TransactWriteCommand.make->TransactWriteCommand.send
898
+ )
912
899
  ->Effect.map(_ => Ok(basePosition))
913
900
  ->Effect.catchAll(err =>
914
901
  switch err {
@@ -945,20 +932,19 @@ let appendUnconditional = async (
945
932
  let basePosition = generatePosition()
946
933
  let carriedMap = carriedTypesByTag(events)
947
934
  let putItems = buildEventPuts(table, events, basePosition, ~partitionTag?)
948
- let updateItems =
949
- eventTags->Array.filterMap(tag => {
950
- let producedTypes = carriedMap->Dict.get(`${tag.key}:${tag.value}`)->Option.getOr([])
951
- producedTypes->Array.length == 0
952
- ? None
953
- : Some({
954
- TransactWriteCommand.update: buildUnconditionalFenceUpdate(
955
- table.name,
956
- tag,
957
- ~producedTypes,
958
- ~newPosition=basePosition,
959
- ),
960
- })
961
- })
935
+ let updateItems = eventTags->Array.filterMap(tag => {
936
+ let producedTypes = carriedMap->Dict.get(`${tag.key}:${tag.value}`)->Option.getOr([])
937
+ producedTypes->Array.length == 0
938
+ ? None
939
+ : Some({
940
+ TransactWriteCommand.update: buildUnconditionalFenceUpdate(
941
+ table.name,
942
+ tag,
943
+ ~producedTypes,
944
+ ~newPosition=basePosition,
945
+ ),
946
+ })
947
+ })
962
948
  let input: TransactWriteCommand.input = {
963
949
  transactItems: Array.concat(putItems, updateItems),
964
950
  }
@@ -1002,7 +988,8 @@ let eventPartitionTags = (
1002
988
  | Some(Simple(pt)) =>
1003
989
  switch event.tags->Array.find(t => t.key == pt.key) {
1004
990
  | Some(t) => [t]
1005
- | None => switch event.tags->Array.get(0) {
991
+ | None =>
992
+ switch event.tags->Array.get(0) {
1006
993
  | Some(t) => [t]
1007
994
  | None => []
1008
995
  }
@@ -1246,54 +1233,51 @@ let buildConditionalTransactItems = (
1246
1233
  })
1247
1234
 
1248
1235
  let putItems = buildEventPuts(table, events, basePosition, ~partitionTag?)
1249
- let updateItems =
1250
- conditionalUpdateTags->Array.filterMap(tag => {
1251
- let producedTypes = producedTypesFor(tag)
1252
- // A conditional Update must advance ≥1 produced type; partition / composite /
1253
- // cross-partition carriers always have one. If none (a misconfigured clause),
1254
- // skip rather than emit an empty `SET`.
1255
- producedTypes->Array.length == 0
1256
- ? None
1257
- : Some({
1258
- TransactWriteCommand.update: buildConditionalFenceUpdate(
1259
- table.name,
1260
- tag,
1261
- ~consumedTypes=consumedTypesFor(tag),
1262
- ~producedTypes,
1263
- ~newPosition=basePosition,
1264
- ~after=cond.after,
1265
- ),
1266
- })
1267
- })
1268
- let checkItems =
1269
- conditionCheckTags->Array.filterMap(tag => {
1270
- let consumedTypes = consumedTypesFor(tag)
1271
- // A vacuous clause (no consumed type carries the tag) matches nothing — skip.
1272
- consumedTypes->Array.length == 0
1273
- ? None
1274
- : Some({
1275
- TransactWriteCommand.conditionCheck: buildFenceConditionCheck(
1276
- table.name,
1277
- tag,
1278
- ~consumedTypes,
1279
- ~after=cond.after,
1280
- ),
1281
- })
1282
- })
1283
- let bumpItems =
1284
- bumpTags->Array.filterMap(tag => {
1285
- let producedTypes = producedTypesFor(tag)
1286
- producedTypes->Array.length == 0
1287
- ? None
1288
- : Some({
1289
- TransactWriteCommand.update: buildUnconditionalFenceUpdate(
1290
- table.name,
1291
- tag,
1292
- ~producedTypes,
1293
- ~newPosition=basePosition,
1294
- ),
1295
- })
1296
- })
1236
+ let updateItems = conditionalUpdateTags->Array.filterMap(tag => {
1237
+ let producedTypes = producedTypesFor(tag)
1238
+ // A conditional Update must advance ≥1 produced type; partition / composite /
1239
+ // cross-partition carriers always have one. If none (a misconfigured clause),
1240
+ // skip rather than emit an empty `SET`.
1241
+ producedTypes->Array.length == 0
1242
+ ? None
1243
+ : Some({
1244
+ TransactWriteCommand.update: buildConditionalFenceUpdate(
1245
+ table.name,
1246
+ tag,
1247
+ ~consumedTypes=consumedTypesFor(tag),
1248
+ ~producedTypes,
1249
+ ~newPosition=basePosition,
1250
+ ~after=cond.after,
1251
+ ),
1252
+ })
1253
+ })
1254
+ let checkItems = conditionCheckTags->Array.filterMap(tag => {
1255
+ let consumedTypes = consumedTypesFor(tag)
1256
+ // A vacuous clause (no consumed type carries the tag) matches nothing — skip.
1257
+ consumedTypes->Array.length == 0
1258
+ ? None
1259
+ : Some({
1260
+ TransactWriteCommand.conditionCheck: buildFenceConditionCheck(
1261
+ table.name,
1262
+ tag,
1263
+ ~consumedTypes,
1264
+ ~after=cond.after,
1265
+ ),
1266
+ })
1267
+ })
1268
+ let bumpItems = bumpTags->Array.filterMap(tag => {
1269
+ let producedTypes = producedTypesFor(tag)
1270
+ producedTypes->Array.length == 0
1271
+ ? None
1272
+ : Some({
1273
+ TransactWriteCommand.update: buildUnconditionalFenceUpdate(
1274
+ table.name,
1275
+ tag,
1276
+ ~producedTypes,
1277
+ ~newPosition=basePosition,
1278
+ ),
1279
+ })
1280
+ })
1297
1281
 
1298
1282
  Array.concat(putItems, Array.concat(updateItems, Array.concat(checkItems, bumpItems)))
1299
1283
  }
@@ -1315,7 +1299,14 @@ let appendConditional = async (
1315
1299
  )
1316
1300
  } else {
1317
1301
  let basePosition = generatePosition()
1318
- let transactItems = buildConditionalTransactItems(table, events, cond, basePosition, ~partitionTag?, ~crossPartitionTagKeys)
1302
+ let transactItems = buildConditionalTransactItems(
1303
+ table,
1304
+ events,
1305
+ cond,
1306
+ basePosition,
1307
+ ~partitionTag?,
1308
+ ~crossPartitionTagKeys,
1309
+ )
1319
1310
  let totalItems = transactItems->Array.length
1320
1311
  if totalItems > transactWriteItemsLimit {
1321
1312
  Error(
@@ -1331,13 +1322,11 @@ let appendConditional = async (
1331
1322
  }
1332
1323
 
1333
1324
  let append = (table: resolvedTable, ~partitionTag=?, ~crossPartitionTagKeys: array<string>=[]) =>
1334
- async (
1335
- events: array<ReventlessCore.DcbEventLog_Adapter.rawStoredEvent>,
1336
- ~condition=?,
1337
- ) => {
1325
+ async (events: array<ReventlessCore.DcbEventLog_Adapter.rawStoredEvent>, ~condition=?) => {
1338
1326
  switch condition {
1339
1327
  | None => await appendUnconditional(table, events, ~partitionTag?)
1340
- | Some(cond) => await appendConditional(table, events, cond, ~partitionTag?, ~crossPartitionTagKeys)
1328
+ | Some(cond) =>
1329
+ await appendConditional(table, events, cond, ~partitionTag?, ~crossPartitionTagKeys)
1341
1330
  }
1342
1331
  }
1343
1332
 
@@ -1349,23 +1338,15 @@ let queryByPartitionKeyStream = (
1349
1338
  ~after: option<string>=?,
1350
1339
  ~strongConsistency: bool=false,
1351
1340
  ) => {
1352
- let baseParams = buildQueryByPartitionKeyInput(
1353
- table,
1354
- partitionKey,
1355
- ~after?,
1356
- ~strongConsistency,
1357
- )
1341
+ let baseParams = buildQueryByPartitionKeyInput(table, partitionKey, ~after?, ~strongConsistency)
1358
1342
  Stream.paginateEffect((None: option<dict<JSON.t>>), cursor =>
1359
- Effect.tryPromise(
1360
- ~catch=DynamoDb_Error.classify,
1361
- () => {
1362
- let params = switch cursor {
1363
- | None => baseParams
1364
- | Some(key) => {...baseParams, exclusiveStartKey: key}
1365
- }
1366
- QueryCommand.send(params->QueryCommand.make)
1367
- },
1368
- )
1343
+ Effect.tryPromise(~catch=DynamoDb_Error.classify, () => {
1344
+ let params = switch cursor {
1345
+ | None => baseParams
1346
+ | Some(key) => {...baseParams, exclusiveStartKey: key}
1347
+ }
1348
+ QueryCommand.send(params->QueryCommand.make)
1349
+ })
1369
1350
  ->Effect.retry(DynamoDb_Error.retrySchedule)
1370
1351
  ->Effect.catchAll(err => Effect.fail(DynamoDb_Error.message(err)))
1371
1352
  ->Effect.map(result => (
@@ -1381,9 +1362,7 @@ let queryByCompositeTagsStream = (
1381
1362
  ~after: option<string>=?,
1382
1363
  ) => {
1383
1364
  let composite = compositeTagKey(tags)
1384
- let expressionAttributeValues = Dict.fromArray([
1385
- (":composite", composite->JSON.Encode.string),
1386
- ])
1365
+ let expressionAttributeValues = Dict.fromArray([(":composite", composite->JSON.Encode.string)])
1387
1366
  let (keyConditionExpression, expressionAttributeNames) = switch after {
1388
1367
  | None => ("tag_composite = :composite", None)
1389
1368
  | Some(afterPos) => {
@@ -1394,21 +1373,18 @@ let queryByCompositeTagsStream = (
1394
1373
  let baseParams: QueryCommand.input = {
1395
1374
  tableName: table.name,
1396
1375
  indexName: "tag_composite",
1397
- keyConditionExpression: keyConditionExpression,
1398
- expressionAttributeValues: expressionAttributeValues,
1376
+ keyConditionExpression,
1377
+ expressionAttributeValues,
1399
1378
  ?expressionAttributeNames,
1400
1379
  }
1401
1380
  Stream.paginateEffect((None: option<dict<JSON.t>>), cursor =>
1402
- Effect.tryPromise(
1403
- ~catch=DynamoDb_Error.classify,
1404
- () => {
1405
- let params = switch cursor {
1406
- | None => baseParams
1407
- | Some(key) => {...baseParams, exclusiveStartKey: key}
1408
- }
1409
- QueryCommand.send(params->QueryCommand.make)
1410
- },
1411
- )
1381
+ Effect.tryPromise(~catch=DynamoDb_Error.classify, () => {
1382
+ let params = switch cursor {
1383
+ | None => baseParams
1384
+ | Some(key) => {...baseParams, exclusiveStartKey: key}
1385
+ }
1386
+ QueryCommand.send(params->QueryCommand.make)
1387
+ })
1412
1388
  ->Effect.retry(DynamoDb_Error.retrySchedule)
1413
1389
  ->Effect.catchAll(err => Effect.fail(DynamoDb_Error.message(err)))
1414
1390
  ->Effect.map(result => (
@@ -1435,16 +1411,13 @@ let scanWithFilterStream = (
1435
1411
  // position cannot appear in FilterExpression (it is the table's sort key).
1436
1412
  // Filter by position in application code after each page is fetched.
1437
1413
  let baseStream = Stream.paginateEffect((None: option<dict<JSON.t>>), cursor =>
1438
- Effect.tryPromise(
1439
- ~catch=DynamoDb_Error.classify,
1440
- () => {
1441
- let params = switch cursor {
1442
- | None => baseParams
1443
- | Some(key) => {...baseParams, exclusiveStartKey: key}
1444
- }
1445
- ScanCommand.send(ScanCommand.make(params))
1446
- },
1447
- )
1414
+ Effect.tryPromise(~catch=DynamoDb_Error.classify, () => {
1415
+ let params = switch cursor {
1416
+ | None => baseParams
1417
+ | Some(key) => {...baseParams, exclusiveStartKey: key}
1418
+ }
1419
+ ScanCommand.send(ScanCommand.make(params))
1420
+ })
1448
1421
  ->Effect.retry(DynamoDb_Error.retrySchedule)
1449
1422
  ->Effect.catchAll(err => Effect.fail(DynamoDb_Error.message(err)))
1450
1423
  ->Effect.map(result => (
@@ -1483,16 +1456,10 @@ let executeQueryItemStream = (
1483
1456
  | Some([tag]) if crossPartitionTagKeys->Array.includes(tag.key) =>
1484
1457
  queryBySingleTagCrossPartitionStream(table, tag, ~after?)
1485
1458
  | Some([tag]) =>
1486
- queryByPartitionKeyStream(
1487
- table,
1488
- `${tag.key}:${tag.value}`,
1489
- ~after?,
1490
- ~strongConsistency,
1491
- )
1459
+ queryByPartitionKeyStream(table, `${tag.key}:${tag.value}`, ~after?, ~strongConsistency)
1492
1460
 
1493
1461
  // Multiple tags: use composite GSI
1494
- | Some(tags) if tags->Array.length > 1 =>
1495
- queryByCompositeTagsStream(table, tags, ~after?)
1462
+ | Some(tags) if tags->Array.length > 1 => queryByCompositeTagsStream(table, tags, ~after?)
1496
1463
 
1497
1464
  // No tags (or empty): fall back to scan
1498
1465
  | None | Some([]) | Some(_) =>
@@ -1511,7 +1478,7 @@ let readStream = (table: resolvedTable, ~crossPartitionTagKeys: array<string>=[]
1511
1478
  )
1512
1479
  switch streams->Array.length {
1513
1480
  | 0 => Stream.empty
1514
- | 1 => (streams->Array.getUnsafe(0))->Stream.map(fromItem)
1481
+ | 1 => streams->Array.getUnsafe(0)->Stream.map(fromItem)
1515
1482
  | _ =>
1516
1483
  // Scan sub-queries (tags = None) return items in unspecified order, so
1517
1484
  // a lazy k-way merge is not possible. Fall back to eager collect + sort.
@@ -1531,8 +1498,7 @@ let readStream = (table: resolvedTable, ~crossPartitionTagKeys: array<string>=[]
1531
1498
  // All sub-streams are tag-based GSI queries — items arrive in position
1532
1499
  // order (rangeKey = "position"). Merge lazily: DynamoDB pages are only
1533
1500
  // fetched as the consumer requests more elements.
1534
- mergeSortedEvents(streams->Array.map(s => s->Stream.map(fromItem)))
1535
- ->dedupByPosition
1501
+ mergeSortedEvents(streams->Array.map(s => s->Stream.map(fromItem)))->dedupByPosition
1536
1502
  }
1537
1503
  }
1538
1504
  }
@@ -27,11 +27,11 @@ let connect = (
27
27
  lambda->connectLambda(name, lambdaRole, queues, eventTopics, resources, opts)
28
28
  }
29
29
 
30
- let make: ReventlessCore.EventCollector_Adapter.channelMaker<callbackEvent, 'context, channelParts> = (
31
- ~name as _,
32
- ~eventTopics,
33
- ~owner as _, ~opts as _,
34
- ) => {
30
+ let make: ReventlessCore.EventCollector_Adapter.channelMaker<
31
+ callbackEvent,
32
+ 'context,
33
+ channelParts,
34
+ > = (~name as _, ~eventTopics, ~owner as _, ~opts as _) => {
35
35
  // Postgres-backed event logs have NO storage resources (no table, no stream) —
36
36
  // skip them instead of producing undefined entries; their events arrive via the
37
37
  // PgProjectionFeed SQS queue (B3.0), not a stream ESM.