@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.
- package/CHANGELOG.md +8 -0
- package/package.json +11 -11
- package/scripts/ProvisionIdentity.res +8 -3
- package/src/Platform.res +327 -328
- package/src/Platform.res.mjs +4 -2
- package/src/Platform_Casts.res +13 -4
- package/src/adapter/Api/AppSyncEventsSigner_Ops.res +8 -4
- package/src/adapter/Api/AppSync_EventsApi.res +12 -14
- package/src/adapter/Api/AppSync_Resolver_Native.res +3 -4
- package/src/adapter/Api/AppSync_Resolver_Retrying.res +78 -70
- package/src/adapter/Api/AppSync_SourceApiAssociation_Retrying.res +11 -8
- package/src/adapter/Api/Platform_AdminScan_Ops.res +15 -14
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +10 -2
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda_Ops.res +40 -50
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +39 -32
- package/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res +5 -2
- package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +0 -1
- package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -2
- package/src/adapter/Auth/Auth_ActiveRoleStore_Schema.res +1 -4
- package/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res +5 -2
- package/src/adapter/Auth/Auth_Cognito.res +3 -9
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync.res +1 -4
- package/src/adapter/CommandGenerator/CommandGeneratorResolvers_AppSync_NoOp.res +3 -1
- package/src/adapter/CommandGenerator/InboundTranslationResolvers_AppSync.res +1 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS.res +7 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Async.res +6 -1
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_FIFO.res +7 -4
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res +24 -18
- package/src/adapter/CommandTopic/CommandTopicChannel_SQS_Sync.res +9 -4
- package/src/adapter/CommandTopic/CommandTopicRegistry.res +1 -4
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res +15 -15
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb.res +9 -5
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +179 -213
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +5 -5
- package/src/adapter/EventCollector/EventCollectorChannel_Helpers.res +6 -2
- package/src/adapter/EventCollector/EventCollectorChannel_SQS.res +14 -7
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_FIFO.res +14 -7
- package/src/adapter/EventCollector/EventCollectorChannel_SQS_Runtime.res +6 -3
- package/src/adapter/EventLog/EventLogStorage_DynamoDbStream.res +6 -1
- package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +13 -17
- package/src/adapter/EventLog/EventLogStorage_Postgres.res +7 -4
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +12 -7
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res +4 -2
- package/src/adapter/EventTopic/EventTopicPublisher_DynamoDbStream.res +3 -2
- package/src/adapter/EventTopic/EventTopicPublisher_SNS.res +20 -12
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_FIFO.res +21 -9
- package/src/adapter/EventTopic/EventTopicPublisher_SNS_Runtime.res +5 -3
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +6 -3
- package/src/adapter/Mcp/MCP_Lambda.res +31 -46
- package/src/adapter/Messaging/Messaging_Ses_Backend.res +11 -7
- package/src/adapter/Messaging/Messaging_Ses_Backend.res.mjs +2 -4
- package/src/adapter/Monitoring/Monitoring_CloudWatch.res +16 -16
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +5 -10
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +4 -2
- package/src/adapter/Postgres/PgConnection.res +6 -5
- package/src/adapter/Postgres/PgMigration_Builder.res +4 -8
- package/src/adapter/Postgres/PgRuntime.res +4 -7
- package/src/adapter/QueryDb/PgQueryResolver_Builder.res +9 -11
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +22 -21
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +114 -111
- package/src/adapter/QueryDb/QueryDbResolvers_Lambda.res +1 -7
- package/src/adapter/QueryDb/QueryDbStorage.res +4 -2
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb.res +23 -24
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDbStream.res +8 -2
- package/src/adapter/QueryDb/QueryDbStorage_DynamoDb_Runtime.res +71 -73
- package/src/adapter/QueryDb/QueryDbStorage_Postgres.res +5 -2
- package/src/adapter/QueryDb/QueryInterceptor_Provisioning.res +1 -4
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +8 -2
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +73 -81
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res +72 -78
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res +44 -67
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res +44 -67
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +53 -82
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +47 -77
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +18 -11
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res +80 -97
- package/src/adapter/Runtime/CounterEntryPoint_Ops.res +2 -7
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +16 -10
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +24 -15
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +17 -37
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +31 -57
- package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +18 -24
- package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +1 -5
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +4 -3
- package/src/adapter/Runtime/HeartbeatEntryPoint.res +0 -1
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.res +4 -2
- package/src/adapter/Runtime/PgMigrationEntryPoint.res +0 -1
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +3 -2
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +1 -2
- package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +4 -5
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +22 -10
- package/src/adapter/Runtime/RuntimeExtensionEntryPoint_Ops.res +8 -2
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res +14 -31
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +16 -17
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +10 -9
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +46 -52
- package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +36 -41
- package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +31 -37
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res +6 -7
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents.res +4 -6
- package/src/adapter/ScheduledPublisher/ScheduledPublisher_CloudWatchEvents_Runtime.res +2 -6
- package/src/adapter/StateTopic/StateTopic_AppSync.res +21 -16
- package/src/adapter/StateTopic/StateTopic_AppSync_Ops.res +36 -32
- package/src/adapter/Task/TaskBucket_S3.res +6 -1
- package/src/adapter/Upload/Upload_Claim_S3.res +17 -20
- package/src/adapter/Upload/Upload_Claim_S3_Ops.res +5 -2
- package/src/adapter/Upload/Upload_Presign_S3.res +51 -49
- package/src/capability/Capability_Geocoding_AwsLocation.res +4 -1
- package/src/capability/Capability_Messaging.res +4 -5
- package/src/capability/Capability_Messaging_Ses.res +3 -1
- package/src/capability/Capability_ObjectStore_S3.res +1 -7
- package/src/components/Api/AppSync_Adapter.res +28 -41
- package/src/components/Api/AppSync_SdlDecorate.res +38 -30
- package/src/components/AutomationSlice_Builder.res +6 -4
- package/src/components/ExtensionPoint_Builder.res +9 -10
- package/src/components/InboundTranslationSlice_Builder.res +7 -8
- package/src/components/OutboundTranslationSlice_Builder.res +14 -8
- package/src/components/OutboundTranslationSlice_Builder.res.mjs +1 -1
- package/src/components/SideEffectHandler_Single.res +4 -4
- package/src/components/StateViewSlice_Builder.res +6 -4
- package/src/components/StateViewSlice_Builder_Stream.res +6 -4
- package/src/components/Task_Builder_PerBucket.res +10 -11
- package/src/plugin/cloner/ClonerRunner_Fargate.res +3 -10
- package/src/plugin/cloner/ClonerRunner_Fargate_Runtime.res +1 -4
- package/src/plugin/heartbeat/HeartbeatRunner_CloudWatchEvents.res +5 -5
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res +19 -21
- package/src/plugin/runtime/PluginRuntime_Builder.res +167 -188
- package/src/plugin/runtime/Util_PluginMessage_Runtime.res +6 -5
- package/src/plugin/stack/Plugin_Stack.res +104 -103
- package/src/util/Util_AlarmSpec.res +2 -1
- package/src/util/Util_AppSync.res +8 -2
- package/src/util/Util_AppSync_Caller.res +15 -14
- package/src/util/Util_Bundle.res +46 -42
- package/src/util/Util_CognitoGroupUser_Runtime.res +32 -34
- package/src/util/Util_Cognito_Runtime.res +11 -7
- package/src/util/Util_DeadLetterQueue.res +12 -2
- package/src/util/Util_DynamoDb.res +5 -3
- package/src/util/Util_DynamoDbStream.res +7 -3
- package/src/util/Util_DynamoDbStream_Runtime.res +1 -2
- package/src/util/Util_DynamoDb_Runtime.res +23 -41
- package/src/util/Util_HostUiDomain.res +6 -1
- package/src/util/Util_Kinesis_Runtime.res +10 -11
- package/src/util/Util_Lambda.res +12 -5
- package/src/util/Util_LambdaEnvBudget.res +5 -5
- package/src/util/Util_LambdaLogging.res +1 -2
- package/src/util/Util_LogGroup_Adopting.res +1 -4
- package/src/util/Util_ResourceNaming.res +1 -2
- package/src/util/Util_SNS.res +8 -3
- package/src/util/Util_SNS_FIFO.res +1 -1
- package/src/util/Util_SNS_Runtime.res +11 -10
- package/src/util/Util_SQS.res +4 -2
- package/src/util/Util_SQS_FIFO.res +5 -2
- package/src/util/Util_SQS_Runtime.res +37 -36
- package/src/util/Util_ShellConfig.res +3 -2
- package/src/util/Util_StaticBundle.res +1 -3
- package/src/util/Util_StoreLayout.res +4 -1
- package/tests/AWS_TagsTest.res +16 -5
- package/tests/AppSyncEventsSigner_OpsTest.res +11 -2
- package/tests/AppSync_AdapterTest.res +203 -224
- package/tests/AppSync_Resolver_RetryingTest.res +64 -44
- package/tests/AppSync_RetirementNarrowingTest.res +59 -46
- package/tests/AppSync_SdlDecorateTest.res +22 -20
- package/tests/AppSync_SourceApiAssociation_RetryingTest.res +40 -22
- package/tests/Auth_ActiveRolePoolAttachmentTest.res +114 -107
- package/tests/Auth_ActiveRoleStoreTest.res +12 -9
- package/tests/Auth_ActiveRoleStore_SchemaTest.res +2 -1
- package/tests/Auth_ActiveRoleTrigger_OpsTest.res +20 -16
- package/tests/Auth_CognitoTest.res +31 -46
- package/tests/AutomationSliceEntryPoint_OpsTest.res +69 -67
- package/tests/BakeConvergenceTest.res +22 -25
- package/tests/Capability_MessagingTest.res +28 -12
- package/tests/CommandTopicQueuePolicyTest.res +1 -2
- package/tests/CounterEntryPoint_OpsTest.res +3 -7
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +306 -210
- package/tests/EventCollectorConnectLambdaPreviewTest.res +14 -7
- package/tests/EventCollectorEntryPoint_OpsTest.res +12 -4
- package/tests/EventCollectorPluginDefinitionAssetTest.res +18 -11
- package/tests/EventCollectorReadyGateTest.res +5 -4
- package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +1 -2
- package/tests/EventMapperEntryPoint_OpsTest.res +1 -3
- package/tests/ExtensionPointEntryPoint_OpsTest.res +1 -4
- package/tests/HandlerFactoryDispatchTest.res +97 -70
- package/tests/MCP_LambdaTest.res +16 -27
- package/tests/PgChangeFeedRelay_IntegrationTest.res +123 -93
- package/tests/PgChangeFeedRelay_RuntimeTest.res +13 -10
- package/tests/PgMigrationEntryPoint_IntegrationTest.res +0 -1
- package/tests/PgPipeline_IntegrationTest.res +80 -66
- package/tests/PgQueryDbUnion_IntegrationTest.res +1 -2
- package/tests/PgQueryResolverEntryPoint_OpsTest.res +2 -6
- package/tests/PgQueryResolver_LambdaTest.res +41 -24
- package/tests/Platform_AdminScan_OpsTest.res +4 -1
- package/tests/Platform_ComponentDefinitions_Lambda_OpsTest.res +137 -129
- package/tests/ProjectionEntryPoint_DisplayNameTest.res +7 -3
- package/tests/ProjectionEntryPoint_UnionStampTest.res +3 -2
- package/tests/ProvisionIdentityTest.res +2 -6
- package/tests/QueryDbOwnerIndexTableTest.res +6 -4
- package/tests/QueryDbResolvers_AppSyncTest.res +23 -16
- package/tests/QueryInterceptor_LambdaTest.res +11 -13
- package/tests/ReadModelEntryPoint_OpsTest.res +43 -41
- package/tests/RuntimeExtensionEntryPoint_OpsTest.res +4 -3
- package/tests/SideEffectEntryPoint_OpsTest.res +23 -18
- package/tests/StateChangeDescriptorParityTest.res +28 -26
- package/tests/StateTopicKeySchemaTest.res +18 -15
- package/tests/StateViewSliceEntryPoint_OpsTest.res +55 -44
- package/tests/TaskBucketEntryPoint_OpsTest.res +13 -13
- package/tests/Upload_ClaimTest.res +3 -3
- package/tests/Util_AwsErrorTest.res +4 -7
- package/tests/Util_BundleDependencyClosureTest.res +15 -3
- package/tests/Util_BundleEsmLoaderTest.res +3 -3
- package/tests/Util_BundleResolveTest.res +4 -6
- package/tests/Util_BundleRuntimeExtensionTest.res +17 -18
- package/tests/Util_DcbMetricsTest.res +6 -6
- package/tests/Util_DynamoDbStreamTest.res +4 -5
- package/tests/Util_DynamoDbTest.res +3 -2
- package/tests/Util_LambdaEnvBudgetTest.res +22 -18
- package/tests/Util_LambdaLoggingTest.res +9 -8
- package/tests/Util_LogGroup_AdoptingTest.res +10 -5
- package/tests/Util_LogRetentionTest.res +6 -2
- package/tests/Util_OwnerScopeEnvTest.res +10 -8
- package/tests/Util_SQS_RuntimeTest.res +5 -7
- package/tests/Util_ShellConfigTest.res +7 -17
- package/tests/Util_StaticBundleTest.res +3 -8
- package/tests/Util_StoreLayoutTest.res +17 -12
- package/tests/integration/AggregateEntryPoint_IntegrationTest.res +1 -4
- package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +15 -15
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +296 -232
- package/tests/integration/DcbIntegrationHarness.res +8 -8
- package/tests/integration/EpCompositeSlice.res +16 -8
- package/tests/integration/QueryDbUnion_DynamoDb_IntegrationTest.res +8 -10
- package/tests/integration/StateViewSliceEntryPoint_IntegrationTest.res +10 -10
- package/tests/integration/SvsTestSlice_Projection.res +1 -3
- package/tests/util/Util_AlarmSpecTest.res +62 -49
|
@@ -4,7 +4,10 @@ open ReventlessInfra.Adapter
|
|
|
4
4
|
|
|
5
5
|
let log = ReventlessCore.Logger.fromEnv()
|
|
6
6
|
|
|
7
|
-
let toResourceInfo: table => Pulumi.Output.t<ReventlessInfra.Adapter.resourceInfo> = ({
|
|
7
|
+
let toResourceInfo: table => Pulumi.Output.t<ReventlessInfra.Adapter.resourceInfo> = ({
|
|
8
|
+
hashKey,
|
|
9
|
+
rangeKey,
|
|
10
|
+
}) =>
|
|
8
11
|
(hashKey, rangeKey)
|
|
9
12
|
->Pulumi.Output.all2
|
|
10
13
|
->Pulumi.Output.apply(((hashKey, rangeKey)) => ReventlessInfra.Adapter.StorageKeys({
|
|
@@ -33,10 +36,9 @@ let toResource = (~tags=?, {id, name, arn} as table) =>
|
|
|
33
36
|
~service=name->Pulumi.Output.apply(_ => AWS.DynamoDb.service),
|
|
34
37
|
~resourceInfo=table->toResourceInfo,
|
|
35
38
|
~resourceType="aws:dynamodb:Table"->Pulumi.Output.make,
|
|
36
|
-
~tags
|
|
39
|
+
~tags?,
|
|
37
40
|
)
|
|
38
41
|
|
|
39
|
-
|
|
40
42
|
let arn2tableName = arn =>
|
|
41
43
|
switch arn->String.split(":") {
|
|
42
44
|
| [_, _, _service, _region, _account, tableName] => tableName
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
let toResourceInfo = (table: PulumiAws.DynamoDb.Table.t) =>
|
|
2
|
-
table.streamArn->Pulumi.Output.apply(streamArn => ReventlessInfra.Adapter.StreamSource({
|
|
2
|
+
table.streamArn->Pulumi.Output.apply(streamArn => ReventlessInfra.Adapter.StreamSource({
|
|
3
|
+
sourceUrn: streamArn,
|
|
4
|
+
}))
|
|
3
5
|
|
|
4
6
|
// The table name rides IN the apply rather than being read with `Output.get` on
|
|
5
7
|
// the failure arm: `get` throws "Cannot call '.get' during update or preview" on
|
|
@@ -23,10 +25,12 @@ let toResource = (~tags=?, table: PulumiAws.DynamoDb.Table.t): ReventlessInfra.A
|
|
|
23
25
|
~service=table.name->Pulumi.Output.apply(_ => AWS.DynamoDbStream.service),
|
|
24
26
|
~resourceInfo=table->toResourceInfo,
|
|
25
27
|
~resourceType="aws:dynamodb:Table"->Pulumi.Output.make,
|
|
26
|
-
~tags
|
|
28
|
+
~tags?,
|
|
27
29
|
)
|
|
28
30
|
|
|
29
|
-
let toStreamResource = (
|
|
31
|
+
let toStreamResource = (
|
|
32
|
+
table: ReventlessInfra.Adapter.resource,
|
|
33
|
+
): ReventlessInfra.Adapter.resource => {
|
|
30
34
|
let streamArn = table->streamArnFromDynamoDbTableResource
|
|
31
35
|
|
|
32
36
|
ReventlessInfra.Adapter.make(
|
|
@@ -37,8 +37,7 @@ let buildJsonEvent' = dict => {
|
|
|
37
37
|
// Carry the stored `recorded_at` column into the envelope so StateViewSlice
|
|
38
38
|
// projections receive it as `consumed.recordedAt` (the authoritative storage
|
|
39
39
|
// time on the AWS path). Absent on non-event rows → empty string.
|
|
40
|
-
let recordedAt =
|
|
41
|
-
dict->Dict.get("recordedAt")->Option.getOr(""->JSON.Encode.string)
|
|
40
|
+
let recordedAt = dict->Dict.get("recordedAt")->Option.getOr(""->JSON.Encode.string)
|
|
42
41
|
Some(
|
|
43
42
|
[
|
|
44
43
|
("id", dict->Dict.get("id")->Option.getOrThrow),
|
|
@@ -31,19 +31,16 @@ let putWithRetries = (table, id, item) => {
|
|
|
31
31
|
ReventlessCore.EffectLogger.logError(
|
|
32
32
|
~comp=__MODULE__,
|
|
33
33
|
`putWithRetries: id=${id}: ${msg}`,
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
| StaleState(msg) =>
|
|
37
|
-
Effect.succeed(Error(`Stale State: id=${id}: ${msg}`))
|
|
34
|
+
)->Effect.map(_ => Error(`put id=${id} failed: ${msg}`))
|
|
35
|
+
| StaleState(msg) => Effect.succeed(Error(`Stale State: id=${id}: ${msg}`))
|
|
38
36
|
}
|
|
39
37
|
)
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
let putIfNotExistsWithRetries = (~idKey, ~sortKey=?, table, id, item) => {
|
|
43
41
|
let item = item->injectId(idKey, id)
|
|
44
|
-
Effect.tryPromise(
|
|
45
|
-
|
|
46
|
-
() => putIfNotExists(table.name, idKey, sortKey, item),
|
|
42
|
+
Effect.tryPromise(~catch=DynamoDb_Error.classify, () =>
|
|
43
|
+
putIfNotExists(table.name, idKey, sortKey, item)
|
|
47
44
|
)
|
|
48
45
|
->Effect.map(_ => Ok())
|
|
49
46
|
->Effect.retry(DynamoDb_Error.retrySchedule)
|
|
@@ -54,8 +51,7 @@ let putIfNotExistsWithRetries = (~idKey, ~sortKey=?, table, id, item) => {
|
|
|
54
51
|
ReventlessCore.EffectLogger.logError(
|
|
55
52
|
~comp=__MODULE__,
|
|
56
53
|
`putIfNotExistsWithRetries: id=${id}: ${msg}`,
|
|
57
|
-
)
|
|
58
|
-
->Effect.map(_ => Error(`putIfNotExists id=${id} failed: ${msg}`))
|
|
54
|
+
)->Effect.map(_ => Error(`putIfNotExists id=${id} failed: ${msg}`))
|
|
59
55
|
}
|
|
60
56
|
)
|
|
61
57
|
}
|
|
@@ -65,10 +61,7 @@ let delete = (table, ~sort=?, id) => {
|
|
|
65
61
|
}
|
|
66
62
|
|
|
67
63
|
let deleteWithRetries = (~sort=?, table, id) =>
|
|
68
|
-
Effect.tryPromise(
|
|
69
|
-
~catch=DynamoDb_Error.classify,
|
|
70
|
-
() => table->delete(id, ~sort?),
|
|
71
|
-
)
|
|
64
|
+
Effect.tryPromise(~catch=DynamoDb_Error.classify, () => table->delete(id, ~sort?))
|
|
72
65
|
->Effect.map(_ => Ok())
|
|
73
66
|
->Effect.retry(DynamoDb_Error.retrySchedule)
|
|
74
67
|
->Effect.catchAll(err => {
|
|
@@ -76,24 +69,20 @@ let deleteWithRetries = (~sort=?, table, id) =>
|
|
|
76
69
|
ReventlessCore.EffectLogger.logError(
|
|
77
70
|
~comp=__MODULE__,
|
|
78
71
|
`delete: id=${id}: ${msg}`,
|
|
79
|
-
)
|
|
80
|
-
->Effect.map(_ => Error(`delete id=${id} failed: ${msg}`))
|
|
72
|
+
)->Effect.map(_ => Error(`delete id=${id} failed: ${msg}`))
|
|
81
73
|
})
|
|
82
74
|
|
|
83
75
|
// Streams all items matching a QueryCommand, fetching one DynamoDB page at a time.
|
|
84
76
|
// Each page fetch retries independently on transient errors.
|
|
85
77
|
let queryStream = (params: QueryCommand.input): Stream.t<JSON.t, DynamoDb_Error.t, unit> =>
|
|
86
78
|
Stream.paginateEffect((None: option<dict<JSON.t>>), cursor =>
|
|
87
|
-
Effect.tryPromise(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
QueryCommand.send(p->QueryCommand.make)
|
|
95
|
-
},
|
|
96
|
-
)
|
|
79
|
+
Effect.tryPromise(~catch=DynamoDb_Error.classify, () => {
|
|
80
|
+
let p = switch cursor {
|
|
81
|
+
| None => params
|
|
82
|
+
| Some(key) => {...params, exclusiveStartKey: key}
|
|
83
|
+
}
|
|
84
|
+
QueryCommand.send(p->QueryCommand.make)
|
|
85
|
+
})
|
|
97
86
|
->Effect.retry(DynamoDb_Error.retrySchedule)
|
|
98
87
|
->Effect.map(res => (
|
|
99
88
|
res.items->Option.getOr([]),
|
|
@@ -105,16 +94,13 @@ let queryStream = (params: QueryCommand.input): Stream.t<JSON.t, DynamoDb_Error.
|
|
|
105
94
|
// Each page fetch retries independently on transient errors.
|
|
106
95
|
let scanStream = (params: ScanCommand.input): Stream.t<JSON.t, DynamoDb_Error.t, unit> =>
|
|
107
96
|
Stream.paginateEffect((None: option<dict<JSON.t>>), cursor =>
|
|
108
|
-
Effect.tryPromise(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
ScanCommand.send(ScanCommand.make(p))
|
|
116
|
-
},
|
|
117
|
-
)
|
|
97
|
+
Effect.tryPromise(~catch=DynamoDb_Error.classify, () => {
|
|
98
|
+
let p = switch cursor {
|
|
99
|
+
| None => params
|
|
100
|
+
| Some(key) => {...params, exclusiveStartKey: key}
|
|
101
|
+
}
|
|
102
|
+
ScanCommand.send(ScanCommand.make(p))
|
|
103
|
+
})
|
|
118
104
|
->Effect.retry(DynamoDb_Error.retrySchedule)
|
|
119
105
|
->Effect.map(res => (
|
|
120
106
|
res.items->Option.getOr([]),
|
|
@@ -180,10 +166,7 @@ let hasUnprocessedItems = writeOutput =>
|
|
|
180
166
|
let batchWriteWithRetries = batchWriteRequests => {
|
|
181
167
|
let all = batchWriteRequests->Dict.valuesToArray->Array.flat->Array.length->Int.toString
|
|
182
168
|
let rec attempt = (retry, requests) =>
|
|
183
|
-
Effect.tryPromise(
|
|
184
|
-
~catch=DynamoDb_Error.classify,
|
|
185
|
-
() => batchWrite(requests),
|
|
186
|
-
)
|
|
169
|
+
Effect.tryPromise(~catch=DynamoDb_Error.classify, () => batchWrite(requests))
|
|
187
170
|
->Effect.retry(DynamoDb_Error.retrySchedule)
|
|
188
171
|
->Effect.flatMap(writeOutput =>
|
|
189
172
|
if writeOutput->hasUnprocessedItems {
|
|
@@ -192,8 +175,7 @@ let batchWriteWithRetries = batchWriteRequests => {
|
|
|
192
175
|
ReventlessCore.EffectLogger.logInfo(
|
|
193
176
|
~comp=__MODULE__,
|
|
194
177
|
`batchWriteWithRetries: retry ${retry->Int.toString}: ${count} unprocessed items`,
|
|
195
|
-
)
|
|
196
|
-
->Effect.flatMap(_ => attempt(retry + 1, unprocessedRequests))
|
|
178
|
+
)->Effect.flatMap(_ => attempt(retry + 1, unprocessedRequests))
|
|
197
179
|
} else {
|
|
198
180
|
Effect.succeed(Ok())
|
|
199
181
|
}
|
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
let defaultProdStacks = ["prod", "main"]
|
|
14
14
|
|
|
15
15
|
/** Pure FQDN derivation. */
|
|
16
|
-
let deriveFqdn = (
|
|
16
|
+
let deriveFqdn = (
|
|
17
|
+
~baseName: string,
|
|
18
|
+
~stack: string,
|
|
19
|
+
~baseDomain: string,
|
|
20
|
+
~prodStacks: array<string>,
|
|
21
|
+
): string =>
|
|
17
22
|
prodStacks->Array.includes(stack)
|
|
18
23
|
? `${baseName}.${baseDomain}`
|
|
19
24
|
: `${baseName}-${stack}.${baseDomain}`
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
let putRecord = (stream, ~data) =>
|
|
2
|
-
Effect.tryPromise(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
partitionKey: "",
|
|
10
|
-
})->AwsSdk.Kinesis.PutRecordCommand.send,
|
|
2
|
+
Effect.tryPromise(~catch=Kinesis_Error.classify, () =>
|
|
3
|
+
AwsSdk.Kinesis.PutRecordCommand.make({
|
|
4
|
+
data,
|
|
5
|
+
//FIXME: remove JST after merge of rescript-v11 upgrade
|
|
6
|
+
streamName: stream["name"]->Pulumi.Output.get,
|
|
7
|
+
partitionKey: "",
|
|
8
|
+
})->AwsSdk.Kinesis.PutRecordCommand.send
|
|
11
9
|
)
|
|
12
10
|
->Effect.map(_ => ())
|
|
13
11
|
->Effect.retry(Kinesis_Error.retrySchedule)
|
|
14
12
|
->Effect.catchAll(err => {
|
|
15
13
|
let msg = Kinesis_Error.message(err)
|
|
16
|
-
ReventlessCore.EffectLogger.logError(~comp=__MODULE__, `putRecord: ${msg}`)
|
|
17
|
-
|
|
14
|
+
ReventlessCore.EffectLogger.logError(~comp=__MODULE__, `putRecord: ${msg}`)->Effect.flatMap(_ =>
|
|
15
|
+
Effect.fail(msg)
|
|
16
|
+
)
|
|
18
17
|
})
|
|
19
18
|
->Effect.runPromise
|
|
20
19
|
/* TODO partitionKey */
|
package/src/util/Util_Lambda.res
CHANGED
|
@@ -3,16 +3,20 @@ type runtimeParts = {
|
|
|
3
3
|
lambdaRole: PulumiAws.IAM.Role.t,
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
let findResource = resources =>
|
|
6
|
+
let findResource = resources =>
|
|
7
|
+
resources->ReventlessCore.Util.Adapter.findResource(AWS.Lambda.service)
|
|
7
8
|
|
|
8
|
-
let toResource = (
|
|
9
|
+
let toResource = (
|
|
10
|
+
~tags=?,
|
|
11
|
+
{id, name, arn}: PulumiAws.Lambda.Function.t,
|
|
12
|
+
): ReventlessInfra.Adapter.resource =>
|
|
9
13
|
ReventlessInfra.Adapter.make(
|
|
10
14
|
~name,
|
|
11
15
|
~id,
|
|
12
16
|
~urn=arn,
|
|
13
17
|
~service=name->Pulumi.Output.apply(_ => AWS.Lambda.service),
|
|
14
18
|
~resourceType="aws:lambda:Function"->Pulumi.Output.make,
|
|
15
|
-
~tags
|
|
19
|
+
~tags?,
|
|
16
20
|
)
|
|
17
21
|
|
|
18
22
|
let fromResource = ({id, name}: ReventlessInfra.Adapter.resource) => {
|
|
@@ -41,12 +45,15 @@ let fromOutput = (output: Pulumi.Output.t<PulumiAws.Lambda.Function.t>) => {
|
|
|
41
45
|
let updateLanded = (lambda: Pulumi.Output.t<PulumiAws.Lambda.Function.t>): Pulumi.Output.t<unit> =>
|
|
42
46
|
lambda->Pulumi.Output.flatMap(({lastModified}) => lastModified)->Pulumi.Output.apply(_ => ())
|
|
43
47
|
|
|
44
|
-
let functionToResource = (
|
|
48
|
+
let functionToResource = (
|
|
49
|
+
~tags=?,
|
|
50
|
+
{id, name, arn}: PulumiAws.Lambda.Function.t,
|
|
51
|
+
): ReventlessInfra.Adapter.resource =>
|
|
45
52
|
ReventlessInfra.Adapter.make(
|
|
46
53
|
~name,
|
|
47
54
|
~id,
|
|
48
55
|
~urn=arn,
|
|
49
56
|
~service=name->Pulumi.Output.apply(_ => AWS.Lambda.service),
|
|
50
57
|
~resourceType="aws:lambda:Function"->Pulumi.Output.make,
|
|
51
|
-
~tags
|
|
58
|
+
~tags?,
|
|
52
59
|
)
|
|
@@ -59,16 +59,16 @@ let check = (
|
|
|
59
59
|
`${outputValuedKeys->Array.length->Int.toString} queue-URL vars are resolved, over the ` ++
|
|
60
60
|
`${limit->Int.toString}-byte limit. HANDLER_CONFIG is ${handlerConfigBytes->Int.toString} ` ++
|
|
61
61
|
`bytes of it — move the term that grows with the plugin into a code-archive asset ` ++
|
|
62
|
-
`(Util_Bundle.buildCodeArchive ~extraStringAssets), as pluginDefinition.json and ` ++
|
|
63
|
-
`sliceModules.json already are.`,
|
|
62
|
+
`(Util_Bundle.buildCodeArchive ~extraStringAssets), as pluginDefinition.json and ` ++ `sliceModules.json already are.`,
|
|
64
63
|
)
|
|
65
64
|
} else if estimated > limit {
|
|
66
65
|
log.warn(
|
|
67
66
|
~comp="Util_LambdaEnvBudget",
|
|
68
67
|
`${lambdaName}: Lambda environment is about ${estimated->Int.toString} bytes ` ++
|
|
69
|
-
`(${exact->Int.toString} exact + ${outputValuedKeys
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
`(${exact->Int.toString} exact + ${outputValuedKeys
|
|
69
|
+
->Array.length
|
|
70
|
+
->Int.toString} queue-URL ` ++
|
|
71
|
+
`vars), at or over the ${limit->Int.toString}-byte limit. The deploy may fail on ` ++ `UpdateFunctionConfiguration; move a plugin-sized term out of HANDLER_CONFIG.`,
|
|
72
72
|
)
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -131,8 +131,7 @@ let makeManagedLogGroup = (
|
|
|
131
131
|
Kept here, beside `logGroupNameFor`, so both naming shapes a Lambda's logs can
|
|
132
132
|
take live in the one module that owns log-group naming and neither is
|
|
133
133
|
reconstructed at a call site. */
|
|
134
|
-
let autoCreatedLogGroupNameFor = (~physicalName: string): string =>
|
|
135
|
-
`/aws/lambda/${physicalName}`
|
|
134
|
+
let autoCreatedLogGroupNameFor = (~physicalName: string): string => `/aws/lambda/${physicalName}`
|
|
136
135
|
|
|
137
136
|
/** Where a function's logs actually land, for a caller that wants to point
|
|
138
137
|
somebody at them (a monitoring backend stamping an address into an alert).
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
run the **serialised** version, not current source. A fix here reaches a
|
|
39
39
|
given resource only once that resource is next created or updated. Keep each
|
|
40
40
|
step able to handle state written by earlier versions. */
|
|
41
|
-
|
|
42
41
|
let log = ReventlessCore.Logger.fromEnv()
|
|
43
42
|
|
|
44
43
|
// ── AWS SDK bindings (lazily imported — see AppSync_SourceApiAssociation_Retrying) ──
|
|
@@ -266,9 +265,7 @@ let create = async (inputs: providerInputs): createResultOut => {
|
|
|
266
265
|
let {logGroupName, retentionInDays, tags} = inputs
|
|
267
266
|
|
|
268
267
|
let adopted = try {
|
|
269
|
-
await runWithRetry(() =>
|
|
270
|
-
client->sendCreate(newCommand(sdk.createCtor, {logGroupName, tags}))
|
|
271
|
-
)
|
|
268
|
+
await runWithRetry(() => client->sendCreate(newCommand(sdk.createCtor, {logGroupName, tags})))
|
|
272
269
|
false
|
|
273
270
|
} catch {
|
|
274
271
|
| exn if exn->JsExn.fromException->Option.mapOr(false, isAlreadyExistsError) => true
|
|
@@ -5,8 +5,7 @@ let invalidNameChars = /[^.\-_a-zA-Z0-9]/g
|
|
|
5
5
|
let validateName = String.replaceRegExp(_, invalidNameChars, "_")
|
|
6
6
|
|
|
7
7
|
// Example ARN: arn:aws:sqs:eu-west-1:xxxxxx:MarketplaceServiceExtensionPointCommandTopic-0101023
|
|
8
|
-
let urnName: string => string = arn =>
|
|
9
|
-
arn->String.split(":")->Array.get(5)->Option.getOr("unknown")
|
|
8
|
+
let urnName: string => string = arn => arn->String.split(":")->Array.get(5)->Option.getOr("unknown")
|
|
10
9
|
|
|
11
10
|
// Export as operations interface
|
|
12
11
|
let operations: ReventlessInfra.ResourceNaming.operations = {
|
package/src/util/Util_SNS.res
CHANGED
|
@@ -7,14 +7,17 @@ let toResolvedTopicOutput = ({name, id, arn}: PulumiAws.SNS.Topic.t) =>
|
|
|
7
7
|
arn,
|
|
8
8
|
})
|
|
9
9
|
|
|
10
|
-
let toResource = (
|
|
10
|
+
let toResource = (
|
|
11
|
+
~tags=?,
|
|
12
|
+
{id, name, arn}: PulumiAws.SNS.Topic.t,
|
|
13
|
+
): ReventlessInfra.Adapter.resource =>
|
|
11
14
|
ReventlessInfra.Adapter.make(
|
|
12
15
|
~name,
|
|
13
16
|
~id,
|
|
14
17
|
~urn=arn,
|
|
15
18
|
~service=name->Pulumi.Output.apply(_ => AWS.SNS.service),
|
|
16
19
|
~resourceType="aws:sns:Topic"->Pulumi.Output.make,
|
|
17
|
-
~tags
|
|
20
|
+
~tags?,
|
|
18
21
|
)
|
|
19
22
|
|
|
20
23
|
let findResolvedResource = resources =>
|
|
@@ -23,7 +26,9 @@ let findResolvedResource = resources =>
|
|
|
23
26
|
let log = ReventlessCore.Logger.fromEnv()
|
|
24
27
|
|
|
25
28
|
let findTopicInResolvedResources = resources =>
|
|
26
|
-
switch resources->ReventlessCore.Util_Adapter.filterSupportedResolvedResources([
|
|
29
|
+
switch resources->ReventlessCore.Util_Adapter.filterSupportedResolvedResources([
|
|
30
|
+
AWS.SNS.service,
|
|
31
|
+
]) {
|
|
27
32
|
| [] =>
|
|
28
33
|
let err = "Couldn't find SNS Topic in resources"
|
|
29
34
|
log.error(~comp="SNS", err)
|
|
@@ -5,7 +5,7 @@ let toResource = (~tags=?, {PulumiAws.SNS.Topic.id: id, name, arn}) =>
|
|
|
5
5
|
~urn=arn,
|
|
6
6
|
~service=name->Pulumi.Output.apply(_ => AWS.SNS_FIFO.service),
|
|
7
7
|
~resourceType="aws:sns:Topic"->Pulumi.Output.make,
|
|
8
|
-
~tags
|
|
8
|
+
~tags?,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
let findTopicInResolvedResources = resources =>
|
|
@@ -5,29 +5,30 @@ type resolvedTopic = {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
let publish = (topic, message) =>
|
|
8
|
-
Effect.tryPromise(
|
|
9
|
-
~
|
|
10
|
-
() => AwsSdk.SNS_Helpers.publish(~topicArn=topic.arn, message),
|
|
8
|
+
Effect.tryPromise(~catch=SNS_Error.classify, () =>
|
|
9
|
+
AwsSdk.SNS_Helpers.publish(~topicArn=topic.arn, message)
|
|
11
10
|
)
|
|
12
11
|
->Effect.map(_ => ())
|
|
13
12
|
->Effect.retry(SNS_Error.retrySchedule)
|
|
14
13
|
->Effect.catchAll(err => {
|
|
15
14
|
let msg = SNS_Error.message(err)
|
|
16
|
-
ReventlessCore.EffectLogger.logError(~comp=__MODULE__, "publish: " ++ msg)
|
|
17
|
-
|
|
15
|
+
ReventlessCore.EffectLogger.logError(~comp=__MODULE__, "publish: " ++ msg)->Effect.flatMap(_ =>
|
|
16
|
+
Effect.fail(msg)
|
|
17
|
+
)
|
|
18
18
|
})
|
|
19
19
|
->Effect.runPromise
|
|
20
20
|
|
|
21
21
|
let publishFifo = (topic, ~messageGroupId, ~message) =>
|
|
22
|
-
Effect.tryPromise(
|
|
23
|
-
~
|
|
24
|
-
() => AwsSdk.SNS_Helpers.publish(~topicArn=topic.arn, ~messageGroupId, message),
|
|
22
|
+
Effect.tryPromise(~catch=SNS_Error.classify, () =>
|
|
23
|
+
AwsSdk.SNS_Helpers.publish(~topicArn=topic.arn, ~messageGroupId, message)
|
|
25
24
|
)
|
|
26
25
|
->Effect.map(_ => ())
|
|
27
26
|
->Effect.retry(SNS_Error.retrySchedule)
|
|
28
27
|
->Effect.catchAll(err => {
|
|
29
28
|
let msg = SNS_Error.message(err)
|
|
30
|
-
ReventlessCore.EffectLogger.logError(
|
|
31
|
-
|
|
29
|
+
ReventlessCore.EffectLogger.logError(
|
|
30
|
+
~comp=__MODULE__,
|
|
31
|
+
"publishFifo: " ++ msg,
|
|
32
|
+
)->Effect.flatMap(_ => Effect.fail(msg))
|
|
32
33
|
})
|
|
33
34
|
->Effect.runPromise
|
package/src/util/Util_SQS.res
CHANGED
|
@@ -18,7 +18,7 @@ let toResource = (~tags=?, queue: PulumiAws.SQS.Queue.t): ReventlessInfra.Adapte
|
|
|
18
18
|
~urn=queue.arn,
|
|
19
19
|
~service=queue.name->Pulumi.Output.apply(_ => AWS.SQS.service),
|
|
20
20
|
~resourceType="aws:sqs:Queue"->Pulumi.Output.make,
|
|
21
|
-
~tags
|
|
21
|
+
~tags?,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
let fromResource = ({id, name}: ReventlessInfra.Adapter.resource) => {
|
|
@@ -59,7 +59,9 @@ let findResolvedResource = resources =>
|
|
|
59
59
|
resources->ReventlessCore.Util.AdapterRuntime.findResolvedResource(AWS.SQS.service)
|
|
60
60
|
|
|
61
61
|
module Subscription = {
|
|
62
|
-
let toResource = (
|
|
62
|
+
let toResource = (
|
|
63
|
+
{eventSourceMapping: {id, arn}}: PulumiAws.SQS.Queue.eventSubscription,
|
|
64
|
+
): ReventlessInfra.Adapter.resource =>
|
|
63
65
|
ReventlessInfra.Adapter.make(
|
|
64
66
|
~name=id,
|
|
65
67
|
~id,
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
let toResource = (
|
|
1
|
+
let toResource = (
|
|
2
|
+
~tags=?,
|
|
3
|
+
{id, name, arn}: PulumiAws.SQS_Queue.t,
|
|
4
|
+
): ReventlessInfra.Adapter.resource =>
|
|
2
5
|
ReventlessInfra.Adapter.make(
|
|
3
6
|
~name,
|
|
4
7
|
~id,
|
|
5
8
|
~urn=arn,
|
|
6
9
|
~service=name->Pulumi.Output.apply(_ => AWS.SQS_FIFO.service),
|
|
7
10
|
~resourceType="aws:sqs:Queue"->Pulumi.Output.make,
|
|
8
|
-
~tags
|
|
11
|
+
~tags?,
|
|
9
12
|
)
|
|
10
13
|
|
|
11
14
|
let fromResource = ({id, name}: ReventlessInfra.Adapter.resource) => {
|
|
@@ -31,25 +31,24 @@ let sendFifoMessage = (queue, ~delay=?, ~messageGroupId, messageBody) =>
|
|
|
31
31
|
|
|
32
32
|
let send = (queue, queueService, commandJson) => {
|
|
33
33
|
let messageBody = commandJson->toMessageBody
|
|
34
|
-
Effect.tryPromise(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
queue->sendMessage(~delay=?commandJson.delay, messageBody)
|
|
45
|
-
},
|
|
34
|
+
Effect.tryPromise(~catch=SQS_Error.classify, () =>
|
|
35
|
+
if queueService == AWS.SQS_FIFO {
|
|
36
|
+
queue->sendFifoMessage(
|
|
37
|
+
~messageGroupId=safeGroupId(commandJson.id),
|
|
38
|
+
~delay=?commandJson.delay,
|
|
39
|
+
messageBody,
|
|
40
|
+
)
|
|
41
|
+
} else {
|
|
42
|
+
queue->sendMessage(~delay=?commandJson.delay, messageBody)
|
|
43
|
+
}
|
|
46
44
|
)
|
|
47
45
|
->Effect.map(_ => ())
|
|
48
46
|
->Effect.retry(SQS_Error.sendRetrySchedule)
|
|
49
47
|
->Effect.catchAll(err => {
|
|
50
48
|
let msg = SQS_Error.message(err)
|
|
51
|
-
ReventlessCore.EffectLogger.logError(~comp=__MODULE__, "send: " ++ msg)
|
|
52
|
-
|
|
49
|
+
ReventlessCore.EffectLogger.logError(~comp=__MODULE__, "send: " ++ msg)->Effect.flatMap(_ =>
|
|
50
|
+
Effect.fail(msg)
|
|
51
|
+
)
|
|
53
52
|
})
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -58,7 +57,12 @@ let makeEntry = (queueService, commandJson) => {
|
|
|
58
57
|
let messageBody = commandJson->toMessageBody
|
|
59
58
|
|
|
60
59
|
if queueService == AWS.SQS_FIFO {
|
|
61
|
-
SQS_Helpers.makeBatchEntryFifo(
|
|
60
|
+
SQS_Helpers.makeBatchEntryFifo(
|
|
61
|
+
~groupId=safeGroupId(id),
|
|
62
|
+
~messageId,
|
|
63
|
+
~messageBody,
|
|
64
|
+
~delay=?commandJson.delay,
|
|
65
|
+
)
|
|
62
66
|
} else {
|
|
63
67
|
SQS_Helpers.makeBatchEntry(~messageId, ~messageBody, ~delay=?commandJson.delay)
|
|
64
68
|
}
|
|
@@ -68,12 +72,10 @@ let sendMessagesMaxRetries = 5
|
|
|
68
72
|
|
|
69
73
|
let sendMessages = (queue, queueService, commandJsons) => {
|
|
70
74
|
let rec attempt = (retry, toSend) =>
|
|
71
|
-
Effect.tryPromise(
|
|
72
|
-
|
|
73
|
-
(
|
|
74
|
-
|
|
75
|
-
->Array.map(commandJson => makeEntry(queueService, commandJson))
|
|
76
|
-
->SQS_Helpers.sendMessagesParallel(~queueId=queue.id),
|
|
75
|
+
Effect.tryPromise(~catch=SQS_Error.classify, () =>
|
|
76
|
+
toSend
|
|
77
|
+
->Array.map(commandJson => makeEntry(queueService, commandJson))
|
|
78
|
+
->SQS_Helpers.sendMessagesParallel(~queueId=queue.id)
|
|
77
79
|
)
|
|
78
80
|
->Effect.retry(SQS_Error.retrySchedule)
|
|
79
81
|
->Effect.flatMap(result =>
|
|
@@ -88,19 +90,19 @@ let sendMessages = (queue, queueService, commandJsons) => {
|
|
|
88
90
|
ReventlessCore.EffectLogger.logInfo(
|
|
89
91
|
~comp=__MODULE__,
|
|
90
92
|
`sendMessages: ${failedIds->Array.length->Int.toString} failed ids, retrying subset`,
|
|
91
|
-
)
|
|
92
|
-
->Effect.flatMap(_ => attempt(retry + 1, commandJsonsToRetry))
|
|
93
|
+
)->Effect.flatMap(_ => attempt(retry + 1, commandJsonsToRetry))
|
|
93
94
|
} else {
|
|
94
95
|
let ids = failedIds->Array.joinUnsafe(", ")
|
|
95
96
|
Effect.fail(SQS_Error.Permanent(`sendMessages failed for ids: ${ids}`))
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
)
|
|
99
|
-
attempt(0, commandJsons)
|
|
100
|
-
->Effect.catchAll(err => {
|
|
100
|
+
attempt(0, commandJsons)->Effect.catchAll(err => {
|
|
101
101
|
let msg = SQS_Error.message(err)
|
|
102
|
-
ReventlessCore.EffectLogger.logError(
|
|
103
|
-
|
|
102
|
+
ReventlessCore.EffectLogger.logError(
|
|
103
|
+
~comp=__MODULE__,
|
|
104
|
+
`sendMessages: ${msg}`,
|
|
105
|
+
)->Effect.flatMap(_ => Effect.fail(msg))
|
|
104
106
|
})
|
|
105
107
|
}
|
|
106
108
|
|
|
@@ -117,9 +119,8 @@ let deleteMessagesMaxRetries = 5
|
|
|
117
119
|
|
|
118
120
|
let deleteMessages = (entries, queue) => {
|
|
119
121
|
let rec attempt = (retry, toDelete) =>
|
|
120
|
-
Effect.tryPromise(
|
|
121
|
-
~
|
|
122
|
-
() => SQS_Helpers.deleteMessagesParallel(~queueId=queue.id, toDelete),
|
|
122
|
+
Effect.tryPromise(~catch=SQS_Error.classify, () =>
|
|
123
|
+
SQS_Helpers.deleteMessagesParallel(~queueId=queue.id, toDelete)
|
|
123
124
|
)
|
|
124
125
|
->Effect.retry(SQS_Error.retrySchedule)
|
|
125
126
|
->Effect.flatMap(result =>
|
|
@@ -140,19 +141,19 @@ let deleteMessages = (entries, queue) => {
|
|
|
140
141
|
ReventlessCore.EffectLogger.logInfo(
|
|
141
142
|
~comp=__MODULE__,
|
|
142
143
|
`deleteMessages: ${failedIds->Array.length->Int.toString} failed ids, retrying subset`,
|
|
143
|
-
)
|
|
144
|
-
->Effect.flatMap(_ => attempt(retry + 1, entriesToRetry))
|
|
144
|
+
)->Effect.flatMap(_ => attempt(retry + 1, entriesToRetry))
|
|
145
145
|
} else {
|
|
146
146
|
let ids = failedIds->Array.joinUnsafe(", ")
|
|
147
147
|
Effect.fail(SQS_Error.Permanent(`deleteMessages failed for ids: ${ids}`))
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
)
|
|
151
|
-
attempt(0, entries)
|
|
152
|
-
->Effect.catchAll(err => {
|
|
151
|
+
attempt(0, entries)->Effect.catchAll(err => {
|
|
153
152
|
let msg = SQS_Error.message(err)
|
|
154
|
-
ReventlessCore.EffectLogger.logError(
|
|
155
|
-
|
|
153
|
+
ReventlessCore.EffectLogger.logError(
|
|
154
|
+
~comp=__MODULE__,
|
|
155
|
+
`deleteMessages: ${msg}`,
|
|
156
|
+
)->Effect.flatMap(_ => Effect.fail(msg))
|
|
156
157
|
})
|
|
157
158
|
}
|
|
158
159
|
|
|
@@ -156,8 +156,9 @@ let fields = (
|
|
|
156
156
|
if collisions->Array.length > 0 {
|
|
157
157
|
failwith(
|
|
158
158
|
"host UI config.json: shellConfig sets key(s) the deploy already computes — " ++
|
|
159
|
-
collisions->Array.join(
|
|
160
|
-
|
|
159
|
+
collisions->Array.join(
|
|
160
|
+
", ",
|
|
161
|
+
) ++ ". Remove them from shellConfig; a passthrough cannot redirect a computed key.",
|
|
161
162
|
)
|
|
162
163
|
}
|
|
163
164
|
extra->Dict.forEachWithKey((v, k) => out->Dict.set(k, v))
|
|
@@ -44,9 +44,7 @@ let rec walkInto = (~dir: string, ~prefix: string, acc: array<fileEntry>): unit
|
|
|
44
44
|
*/
|
|
45
45
|
let walk = (assetsDir: string): array<fileEntry> => {
|
|
46
46
|
if !NodeFs.existsSync(assetsDir) {
|
|
47
|
-
JsError.throwWithMessage(
|
|
48
|
-
`Util_StaticBundle.walk: assetsDir does not exist: ${assetsDir}`,
|
|
49
|
-
)
|
|
47
|
+
JsError.throwWithMessage(`Util_StaticBundle.walk: assetsDir does not exist: ${assetsDir}`)
|
|
50
48
|
}
|
|
51
49
|
let acc: array<fileEntry> = []
|
|
52
50
|
walkInto(~dir=assetsDir, ~prefix="", acc)
|
|
@@ -88,7 +88,10 @@ Destroy semantics follow disposability, **not** layout.
|
|
|
88
88
|
field rename may destroy a bucket by accident. Only stacks that are routinely
|
|
89
89
|
torn down are unprotected.
|
|
90
90
|
*/
|
|
91
|
-
let protectionFor = (
|
|
91
|
+
let protectionFor = (
|
|
92
|
+
~stack: string,
|
|
93
|
+
~ephemeralPrefixes: array<string>=defaultEphemeralPrefixes,
|
|
94
|
+
): protection =>
|
|
92
95
|
ephemeralPrefixes->Array.some(p => stack->String.startsWith(p)) ? Unprotected : Protected
|
|
93
96
|
|
|
94
97
|
/**
|