@reventlessdev/reventless-aws 3.0.0-alpha.346 → 3.0.0-alpha.348
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 +34 -0
- package/package.json +17 -13
- package/rescript.json +2 -1
- package/run-bake-manifest.mjs +3 -0
- package/run-deploy-app.mjs +3 -0
- package/scripts/BakeManifest.res +395 -0
- package/scripts/BakeManifest.res.mjs +487 -0
- package/scripts/DeployApp.res +708 -0
- package/scripts/DeployApp.res.mjs +1015 -0
- package/scripts/DeployManifest.res +84 -0
- package/scripts/DeployManifest.res.mjs +112 -0
- package/scripts/ProvisionAccounts.res +60 -46
- package/scripts/ProvisionAccounts.res.mjs +51 -37
- package/scripts/PulumiCli.res +43 -0
- package/scripts/PulumiCli.res.mjs +106 -0
- package/src/Platform.res +19 -2
- package/src/Platform.res.mjs +12 -4
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res +1 -5
- package/src/adapter/Api/Platform_ComponentDefinitions_Lambda.res.mjs +1 -1
- package/src/adapter/Api/Platform_UIFragments_Lambda.res +1 -5
- package/src/adapter/Api/Platform_UIFragments_Lambda.res.mjs +1 -2
- package/src/adapter/Auth/Auth_ActiveRoleStore.res +1 -5
- package/src/adapter/Auth/Auth_ActiveRoleStore.res.mjs +1 -2
- package/src/adapter/Auth/Auth_ActiveRoleTrigger.res +1 -5
- package/src/adapter/Auth/Auth_ActiveRoleTrigger.res.mjs +1 -2
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +52 -31
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +75 -44
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res +1 -5
- package/src/adapter/EventLogSubscription/EventLogSubscription_AppSync.res.mjs +1 -2
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res +1 -5
- package/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver.res.mjs +1 -2
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +5 -4
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res.mjs +1 -1
- package/src/adapter/Postgres/PgMigration_Builder.res +1 -1
- package/src/adapter/Postgres/PgMigration_Builder.res.mjs +1 -2
- package/src/adapter/Runtime/CommandGeneratorEntryPoint_Ops.res +2 -0
- package/src/adapter/Runtime/CommandGeneratorEntryPoint_Ops.res.mjs +2 -2
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +15 -6
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +51 -30
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res.mjs +31 -14
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +1 -5
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +1 -1
- package/src/adapter/StateTopic/StateTopic_AppSync.res +1 -5
- package/src/adapter/StateTopic/StateTopic_AppSync.res.mjs +1 -1
- package/src/adapter/Task/TaskBucket_S3.res +1 -3
- package/src/adapter/Task/TaskBucket_S3.res.mjs +1 -1
- package/src/adapter/Upload/Upload_Claim_S3.res +1 -5
- package/src/adapter/Upload/Upload_Claim_S3.res.mjs +1 -1
- package/src/adapter/Upload/Upload_Presign_S3.res +1 -5
- package/src/adapter/Upload/Upload_Presign_S3.res.mjs +1 -2
- package/src/capability/Capability_Geocoding_AwsLocation.res +5 -1
- package/src/capability/Capability_Geocoding_AwsLocation.res.mjs +7 -1
- package/src/components/Api/AppSync_SdlDecorate.res +4 -2
- package/src/components/Api/AppSync_SdlDecorate.res.mjs +1 -1
- package/src/plugin/cloner/ClonerRunner_Fargate.res +1 -5
- package/src/plugin/cloner/ClonerRunner_Fargate.res.mjs +1 -1
- package/src/plugin/stack/Plugin_Stack.res +4 -0
- package/src/plugin/stack/Plugin_Stack.res.mjs +2 -0
- package/src/util/Util_DeadLetterQueue.res +1 -5
- package/src/util/Util_DeadLetterQueue.res.mjs +1 -2
- package/src/util/Util_StoreLayout.res +15 -2
- package/src/util/Util_StoreLayout.res.mjs +11 -3
- package/tests/BakeManifestTest.res +204 -0
- package/tests/BakeManifestTest.res.mjs +259 -0
- package/tests/DcbColdStartPartitionTest.res +32 -0
- package/tests/DcbColdStartPartitionTest.res.mjs +33 -0
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +88 -0
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res.mjs +112 -0
- package/tests/DcbUnresolvedPartitionSlice.res +28 -0
- package/tests/DcbUnresolvedPartitionSlice.res.mjs +38 -0
- package/tests/DeployAppTest.res +90 -0
- package/tests/DeployAppTest.res.mjs +133 -0
- package/tests/LambdaLayerLookupTest.res +104 -0
- package/tests/LambdaLayerLookupTest.res.mjs +117 -0
- package/tests/ProvisionAccountsTest.res +26 -0
- package/tests/ProvisionAccountsTest.res.mjs +31 -0
- package/tests/Util_StoreLayoutTest.res +6 -0
- package/tests/Util_StoreLayoutTest.res.mjs +7 -4
- package/tests/dcbColdStartPartition.mjs +66 -0
- package/tests/setup/layerArn.cjs +5 -0
package/src/Platform.res.mjs
CHANGED
|
@@ -873,7 +873,7 @@ function MakeWithConfig(Config) {
|
|
|
873
873
|
}
|
|
874
874
|
});
|
|
875
875
|
PluginRuntime_Builder$ReventlessAws.registerConfig(pluginEpEventTopicArn, pluginReadModelTableName, hooks_schedulerRoleUrn.contents, undefined, undefined, domainApiId, Config.cloner, undefined);
|
|
876
|
-
let offloadProtection = Util_StoreLayout$ReventlessAws.
|
|
876
|
+
let offloadProtection = Util_StoreLayout$ReventlessAws.protectionOfDeployedStack();
|
|
877
877
|
let offloadBucket = new (Aws.s3.Bucket)("reventless-offload", {
|
|
878
878
|
forceDestroy: offloadProtection === "Unprotected",
|
|
879
879
|
tags: AWS_Tags$ReventlessAws.make("reventless-offload", "Platform", {
|
|
@@ -892,6 +892,7 @@ function MakeWithConfig(Config) {
|
|
|
892
892
|
restrictPublicBuckets: true
|
|
893
893
|
});
|
|
894
894
|
Pulumi$Pulumi.$$export("offloadBucket", offloadBucketName);
|
|
895
|
+
Pulumi$Pulumi.$$export("platformStack", Pulumi.output(Pulumi.getOrganization() + `/` + Pulumi.getProject() + `/` + Pulumi.getStack()));
|
|
895
896
|
let componentDefinitions = pluginReadModelTableName !== undefined ? (AggregateRuntime_Builder_Single$ReventlessAws.setPluginReadModelTable(pluginReadModelTableName), Platform_ComponentDefinitions_Lambda$ReventlessAws.make(platformApi, pluginReadModelTableName, offloadBucketName, admin.adminSchemaPushed, Stdlib_Option.flatMap(hostUiBundle, cfg => cfg.bakedManifest), {})) : undefined;
|
|
896
897
|
let rm = admin.stateViewSlicesOutputs["UiFragments"];
|
|
897
898
|
if (rm !== undefined) {
|
|
@@ -969,7 +970,7 @@ function MakeWithConfig(Config) {
|
|
|
969
970
|
});
|
|
970
971
|
let stackName = Pulumi.getStack();
|
|
971
972
|
let storeLayout = Util_StoreLayout$ReventlessAws.layoutFor(stackName, Util_HostUiDomain$ReventlessAws.resolveProdStacks());
|
|
972
|
-
let storeProtection = Util_StoreLayout$ReventlessAws.
|
|
973
|
+
let storeProtection = Util_StoreLayout$ReventlessAws.protectionOfDeployedStack();
|
|
973
974
|
let declaredStores = Stdlib_Array.reduce(Stdlib_Array.filterMap(capabilities, c => {
|
|
974
975
|
if (typeof c !== "object") {
|
|
975
976
|
return;
|
|
@@ -1327,6 +1328,9 @@ function MakeWithConfig(Config) {
|
|
|
1327
1328
|
let startServers = () => {};
|
|
1328
1329
|
let deployPlugin = (plugin, apiTargetOpt) => {
|
|
1329
1330
|
let apiTarget = apiTargetOpt !== undefined ? apiTargetOpt : "Domain";
|
|
1331
|
+
if (Stdlib_Option.isNone(platformStackRef)) {
|
|
1332
|
+
Stdlib_JsError.throwWithMessage(`This plugin stack has no platform:stack setting, so it cannot find its platform. Set it to the platform's stack: pulumi config set platform:stack ` + (Pulumi.getOrganization() + `/<platform project>/` + Pulumi.getStack()));
|
|
1333
|
+
}
|
|
1330
1334
|
let tmp;
|
|
1331
1335
|
tmp = apiTarget === "Domain" ? "Domain" : "Platform";
|
|
1332
1336
|
log.info("Platform:deployPlugin", undefined, `target=` + tmp);
|
|
@@ -2260,7 +2264,7 @@ function Make($star) {
|
|
|
2260
2264
|
}
|
|
2261
2265
|
});
|
|
2262
2266
|
PluginRuntime_Builder$ReventlessAws.registerConfig(pluginEpEventTopicArn, pluginReadModelTableName, hooks_schedulerRoleUrn.contents, undefined, undefined, domainApiId, false, undefined);
|
|
2263
|
-
let offloadProtection = Util_StoreLayout$ReventlessAws.
|
|
2267
|
+
let offloadProtection = Util_StoreLayout$ReventlessAws.protectionOfDeployedStack();
|
|
2264
2268
|
let offloadBucket = new (Aws.s3.Bucket)("reventless-offload", {
|
|
2265
2269
|
forceDestroy: offloadProtection === "Unprotected",
|
|
2266
2270
|
tags: AWS_Tags$ReventlessAws.make("reventless-offload", "Platform", {
|
|
@@ -2279,6 +2283,7 @@ function Make($star) {
|
|
|
2279
2283
|
restrictPublicBuckets: true
|
|
2280
2284
|
});
|
|
2281
2285
|
Pulumi$Pulumi.$$export("offloadBucket", offloadBucketName);
|
|
2286
|
+
Pulumi$Pulumi.$$export("platformStack", Pulumi.output(Pulumi.getOrganization() + `/` + Pulumi.getProject() + `/` + Pulumi.getStack()));
|
|
2282
2287
|
let componentDefinitions = pluginReadModelTableName !== undefined ? (AggregateRuntime_Builder_Single$ReventlessAws.setPluginReadModelTable(pluginReadModelTableName), Platform_ComponentDefinitions_Lambda$ReventlessAws.make(platformApi, pluginReadModelTableName, offloadBucketName, admin.adminSchemaPushed, Stdlib_Option.flatMap(hostUiBundle, cfg => cfg.bakedManifest), {})) : undefined;
|
|
2283
2288
|
let rm = admin.stateViewSlicesOutputs["UiFragments"];
|
|
2284
2289
|
if (rm !== undefined) {
|
|
@@ -2350,7 +2355,7 @@ function Make($star) {
|
|
|
2350
2355
|
});
|
|
2351
2356
|
let stackName = Pulumi.getStack();
|
|
2352
2357
|
let storeLayout = Util_StoreLayout$ReventlessAws.layoutFor(stackName, Util_HostUiDomain$ReventlessAws.resolveProdStacks());
|
|
2353
|
-
let storeProtection = Util_StoreLayout$ReventlessAws.
|
|
2358
|
+
let storeProtection = Util_StoreLayout$ReventlessAws.protectionOfDeployedStack();
|
|
2354
2359
|
let declaredStores = Stdlib_Array.reduce(Stdlib_Array.filterMap(capabilities, c => {
|
|
2355
2360
|
if (typeof c !== "object") {
|
|
2356
2361
|
return;
|
|
@@ -2706,6 +2711,9 @@ function Make($star) {
|
|
|
2706
2711
|
let startServers = () => {};
|
|
2707
2712
|
let deployPlugin = (plugin, apiTargetOpt) => {
|
|
2708
2713
|
let apiTarget = apiTargetOpt !== undefined ? apiTargetOpt : "Domain";
|
|
2714
|
+
if (Stdlib_Option.isNone(platformStackRef)) {
|
|
2715
|
+
Stdlib_JsError.throwWithMessage(`This plugin stack has no platform:stack setting, so it cannot find its platform. Set it to the platform's stack: pulumi config set platform:stack ` + (Pulumi.getOrganization() + `/<platform project>/` + Pulumi.getStack()));
|
|
2716
|
+
}
|
|
2709
2717
|
let tmp;
|
|
2710
2718
|
tmp = apiTarget === "Domain" ? "Domain" : "Platform";
|
|
2711
2719
|
log.info("Platform:deployPlugin", undefined, `target=` + tmp);
|
|
@@ -217,11 +217,7 @@ let make = (
|
|
|
217
217
|
~bundleRuntimeExtensions=false,
|
|
218
218
|
)
|
|
219
219
|
|
|
220
|
-
let layers =
|
|
221
|
-
Lambda.reventlessLayerArn
|
|
222
|
-
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
223
|
-
->Option.getOr([])
|
|
224
|
-
->Pulumi.Input.make
|
|
220
|
+
let layers = Lambda.reventlessLayers()
|
|
225
221
|
|
|
226
222
|
// Created before the function that writes to it — see
|
|
227
223
|
// `Util_LambdaLogging.makeManagedLogGroup` for why the ordering matters.
|
|
@@ -116,7 +116,7 @@ function make(api, pluginReadModelTableName, offloadBucketName, schemaReady, bak
|
|
|
116
116
|
"adminEntry.json",
|
|
117
117
|
adminEntryJson
|
|
118
118
|
]]), false);
|
|
119
|
-
let layers =
|
|
119
|
+
let layers = Lambda$PulumiAws.reventlessLayers();
|
|
120
120
|
let logGroup = Util_LambdaLogging$ReventlessAws.makeManagedLogGroup(name + "Lambda", undefined, AWS_Tags$ReventlessAws.make(name + "LambdaLogGroup", "Platform", "Logs", "Platform", undefined, undefined, undefined, undefined), opts$1, undefined);
|
|
121
121
|
let lambda = new (Aws.lambda.Function)(name + "Lambda", {
|
|
122
122
|
handler: "index.handler",
|
|
@@ -89,11 +89,7 @@ let make = (
|
|
|
89
89
|
~bundleRuntimeExtensions=false,
|
|
90
90
|
)
|
|
91
91
|
|
|
92
|
-
let layers =
|
|
93
|
-
Lambda.reventlessLayerArn
|
|
94
|
-
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
95
|
-
->Option.getOr([])
|
|
96
|
-
->Pulumi.Input.make
|
|
92
|
+
let layers = Lambda.reventlessLayers()
|
|
97
93
|
|
|
98
94
|
// Created before the function that writes to it — see
|
|
99
95
|
// `Util_LambdaLogging.makeManagedLogGroup` for why the ordering matters.
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import * as Aws from "@pulumi/aws";
|
|
4
4
|
import * as IAM$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/IAM.res.mjs";
|
|
5
5
|
import * as Output$Pulumi from "@reventlessdev/rescript-pulumi-pulumi/src/Output.res.mjs";
|
|
6
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
6
|
import * as Pulumi from "@pulumi/pulumi";
|
|
8
7
|
import * as Lambda$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Lambda/Lambda.res.mjs";
|
|
9
8
|
import * as AWS$ReventlessAws from "../AWS.res.mjs";
|
|
@@ -53,7 +52,7 @@ function make(api, uiFragmentRegistryTableName, schemaReady, opts) {
|
|
|
53
52
|
Util_Bundle$ReventlessAws.resolvePackageRoot(undefined, "@reventlessdev/reventless-aws")
|
|
54
53
|
]]);
|
|
55
54
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Api/Platform_UIFragments_Lambda_Ops.res.mjs", packageDirs, undefined, false);
|
|
56
|
-
let layers =
|
|
55
|
+
let layers = Lambda$PulumiAws.reventlessLayers();
|
|
57
56
|
let logGroup = Util_LambdaLogging$ReventlessAws.makeManagedLogGroup(name + "Lambda", undefined, AWS_Tags$ReventlessAws.make(name + "LambdaLogGroup", "Platform", "Logs", "Platform", undefined, undefined, undefined, undefined), opts$1, undefined);
|
|
58
57
|
let lambda = new (Aws.lambda.Function)(name + "Lambda", {
|
|
59
58
|
handler: "index.handler",
|
|
@@ -261,11 +261,7 @@ let makeWriteDoor = (
|
|
|
261
261
|
~bundleRuntimeExtensions=false,
|
|
262
262
|
)
|
|
263
263
|
|
|
264
|
-
let layers =
|
|
265
|
-
Lambda.reventlessLayerArn
|
|
266
|
-
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
267
|
-
->Option.getOr([])
|
|
268
|
-
->Pulumi.Input.make
|
|
264
|
+
let layers = Lambda.reventlessLayers()
|
|
269
265
|
|
|
270
266
|
let logGroup = Util_LambdaLogging.makeManagedLogGroup(
|
|
271
267
|
~name=name ++ "Lambda",
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import * as Aws from "@pulumi/aws";
|
|
4
4
|
import * as IAM$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/IAM.res.mjs";
|
|
5
5
|
import * as Output$Pulumi from "@reventlessdev/rescript-pulumi-pulumi/src/Output.res.mjs";
|
|
6
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
6
|
import * as Pulumi from "@pulumi/pulumi";
|
|
8
7
|
import * as Lambda$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Lambda/Lambda.res.mjs";
|
|
9
8
|
import * as AWS$ReventlessAws from "../AWS.res.mjs";
|
|
@@ -136,7 +135,7 @@ function makeWriteDoor(api, table, cognitoUserPoolId, cognitoUserPoolArn, nameOp
|
|
|
136
135
|
Util_Bundle$ReventlessAws.resolvePackageRoot(undefined, "@reventlessdev/reventless-aws")
|
|
137
136
|
]]);
|
|
138
137
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Auth/Auth_ActiveRoleStore_Ops.res.mjs", packageDirs, undefined, false);
|
|
139
|
-
let layers =
|
|
138
|
+
let layers = Lambda$PulumiAws.reventlessLayers();
|
|
140
139
|
let logGroup = Util_LambdaLogging$ReventlessAws.makeManagedLogGroup(name + "Lambda", undefined, AWS_Tags$ReventlessAws.make(name + "LambdaLogGroup", "Platform", "Logs", "Platform", undefined, undefined, undefined, undefined), opts$1, undefined);
|
|
141
140
|
let lambda = new (Aws.lambda.Function)(name + "Lambda", {
|
|
142
141
|
handler: "index.handler",
|
|
@@ -99,11 +99,7 @@ let make = (
|
|
|
99
99
|
~bundleRuntimeExtensions=false,
|
|
100
100
|
)
|
|
101
101
|
|
|
102
|
-
let layers =
|
|
103
|
-
Lambda.reventlessLayerArn
|
|
104
|
-
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
105
|
-
->Option.getOr([])
|
|
106
|
-
->Pulumi.Input.make
|
|
102
|
+
let layers = Lambda.reventlessLayers()
|
|
107
103
|
|
|
108
104
|
let logGroup = Util_LambdaLogging.makeManagedLogGroup(
|
|
109
105
|
~name,
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Aws from "@pulumi/aws";
|
|
4
4
|
import * as IAM$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/IAM.res.mjs";
|
|
5
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
5
|
import * as Pulumi from "@pulumi/pulumi";
|
|
7
6
|
import * as Lambda$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Lambda/Lambda.res.mjs";
|
|
8
7
|
import * as AWS$ReventlessAws from "../AWS.res.mjs";
|
|
@@ -45,7 +44,7 @@ function make(activeRoleTableName, activeRoleTableArn, nameOpt, opts) {
|
|
|
45
44
|
]]);
|
|
46
45
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Auth/Auth_ActiveRoleTrigger_Ops.res.mjs", packageDirs, undefined, false);
|
|
47
46
|
let sourceCodeHash = match.sourceCodeHash;
|
|
48
|
-
let layers =
|
|
47
|
+
let layers = Lambda$PulumiAws.reventlessLayers();
|
|
49
48
|
let logGroup = Util_LambdaLogging$ReventlessAws.makeManagedLogGroup(name, undefined, AWS_Tags$ReventlessAws.make(name + "LogGroup", "Platform", "Logs", "Platform", undefined, undefined, undefined, undefined), opts$1, undefined);
|
|
50
49
|
let lambda = new (Aws.lambda.Function)(name, {
|
|
51
50
|
handler: "index.handler",
|
|
@@ -61,28 +61,55 @@ let compositeTagKey = (tags: array<Reventless.DcbTag.tag>) =>
|
|
|
61
61
|
|
|
62
62
|
// --- Partition Key Derivation ---
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
// The tag an event is filed under: the one named by its partition key. An event
|
|
65
|
+
// that lacks it throws — filing it under another tag would put it where no
|
|
66
|
+
// decision read of its entity looks. With no partition configured at all (a
|
|
67
|
+
// single-tag log), the event's only tag.
|
|
68
|
+
let partitionTagOfEvent = (
|
|
69
|
+
~partitionTag: option<Reventless.DcbTag.derivedPartitionTag>,
|
|
70
|
+
~eventType: string,
|
|
66
71
|
tags: array<Reventless.DcbTag.tag>,
|
|
67
|
-
):
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
switch partitionTag {
|
|
72
|
+
): option<Reventless.DcbTag.tag> => {
|
|
73
|
+
let byKey = key =>
|
|
74
|
+
switch tags->Array.find(t => t.key == key) {
|
|
75
|
+
| Some(t) => Some(t)
|
|
72
76
|
| None =>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
JsError.throwWithMessage(
|
|
78
|
+
`DCB event ${eventType} carries no ${key} tag (tags: ${tags
|
|
79
|
+
->Array.map(t => t.key)
|
|
80
|
+
->Array.join(", ")}) — it cannot be filed under its partition`,
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
switch (tags, partitionTag) {
|
|
84
|
+
| ([], _) | (_, Some(Composite(_))) => None
|
|
85
|
+
| (_, None) => tags->Array.get(0)
|
|
86
|
+
| (_, Some(Simple({key}))) => byKey(key)
|
|
87
|
+
| (_, Some(ByEventType(keys))) =>
|
|
88
|
+
switch keys->Dict.get(eventType) {
|
|
89
|
+
| Some(key) => byKey(key)
|
|
90
|
+
| None =>
|
|
91
|
+
JsError.throwWithMessage(
|
|
92
|
+
`DCB event ${eventType} has no partition key — no slice of this boundary writes it`,
|
|
93
|
+
)
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
96
|
}
|
|
85
97
|
|
|
98
|
+
let derivePartitionKey = (
|
|
99
|
+
~partitionTag: option<Reventless.DcbTag.derivedPartitionTag>=?,
|
|
100
|
+
~eventType: string,
|
|
101
|
+
tags: array<Reventless.DcbTag.tag>,
|
|
102
|
+
): string =>
|
|
103
|
+
switch (tags, partitionTag) {
|
|
104
|
+
| ([], _) => "dcb"
|
|
105
|
+
| (_, Some(Composite(spec))) => Reventless.DcbTag.getCompositePartitionKeyValue(tags, spec)
|
|
106
|
+
| _ =>
|
|
107
|
+
switch partitionTagOfEvent(~partitionTag, ~eventType, tags) {
|
|
108
|
+
| Some(tag) => `${tag.key}:${tag.value}`
|
|
109
|
+
| None => "dcb"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
86
113
|
// --- Item Conversion ---
|
|
87
114
|
|
|
88
115
|
let toItem = (
|
|
@@ -93,7 +120,10 @@ let toItem = (
|
|
|
93
120
|
): JSON.t => {
|
|
94
121
|
// Create base item
|
|
95
122
|
let item = Dict.make()
|
|
96
|
-
item->Dict.set(
|
|
123
|
+
item->Dict.set(
|
|
124
|
+
"id",
|
|
125
|
+
derivePartitionKey(~partitionTag?, ~eventType=event.eventType, event.tags)->JSON.Encode.string,
|
|
126
|
+
)
|
|
97
127
|
item->Dict.set("position", position->JSON.Encode.string)
|
|
98
128
|
item->Dict.set("event", event.eventType->JSON.Encode.string)
|
|
99
129
|
item->Dict.set("data", event.data)
|
|
@@ -985,20 +1015,11 @@ let eventPartitionTags = (
|
|
|
985
1015
|
): array<Reventless.DcbTag.tag> =>
|
|
986
1016
|
switch partitionTag {
|
|
987
1017
|
| Some(Composite(spec)) => [makeCompositeFenceTag(event.tags, spec)]
|
|
988
|
-
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
| Some(t) => [t]
|
|
994
|
-
| None => []
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
| None =>
|
|
998
|
-
switch event.tags->Array.get(0) {
|
|
999
|
-
| Some(t) => [t]
|
|
1000
|
-
| None => []
|
|
1001
|
-
}
|
|
1018
|
+
| _ =>
|
|
1019
|
+
partitionTagOfEvent(~partitionTag, ~eventType=event.eventType, event.tags)->Option.mapOr(
|
|
1020
|
+
[],
|
|
1021
|
+
t => [t],
|
|
1022
|
+
)
|
|
1002
1023
|
}
|
|
1003
1024
|
|
|
1004
1025
|
let collectEventPartitionTags = (
|
|
@@ -64,26 +64,60 @@ function compositeTagKey(tags) {
|
|
|
64
64
|
return tags.toSorted((a, b) => Primitive_string.compare(a.key, b.key)).map(t => t.key + `:` + t.value).join("#");
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
function
|
|
67
|
+
function partitionTagOfEvent(partitionTag, eventType, tags) {
|
|
68
|
+
let byKey = key => {
|
|
69
|
+
let t = tags.find(t => t.key === key);
|
|
70
|
+
if (t !== undefined) {
|
|
71
|
+
return t;
|
|
72
|
+
} else {
|
|
73
|
+
return Stdlib_JsError.throwWithMessage(`DCB event ` + eventType + ` carries no ` + key + ` tag (tags: ` + tags.map(t => t.key).join(", ") + `) — it cannot be filed under its partition`);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
if (tags.length === 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (partitionTag === undefined) {
|
|
80
|
+
return tags[0];
|
|
81
|
+
}
|
|
82
|
+
switch (partitionTag.TAG) {
|
|
83
|
+
case "Simple" :
|
|
84
|
+
return byKey(partitionTag._0.key);
|
|
85
|
+
case "Composite" :
|
|
86
|
+
return;
|
|
87
|
+
case "ByEventType" :
|
|
88
|
+
let key = partitionTag._0[eventType];
|
|
89
|
+
if (key !== undefined) {
|
|
90
|
+
return byKey(key);
|
|
91
|
+
} else {
|
|
92
|
+
return Stdlib_JsError.throwWithMessage(`DCB event ` + eventType + ` has no partition key — no slice of this boundary writes it`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function derivePartitionKey(partitionTag, eventType, tags) {
|
|
68
98
|
if (tags.length === 0) {
|
|
69
99
|
return "dcb";
|
|
70
100
|
}
|
|
71
101
|
if (partitionTag !== undefined) {
|
|
72
|
-
|
|
73
|
-
|
|
102
|
+
switch (partitionTag.TAG) {
|
|
103
|
+
case "Composite" :
|
|
104
|
+
return DcbTag$Reventless.getCompositePartitionKeyValue(tags, partitionTag._0);
|
|
105
|
+
case "Simple" :
|
|
106
|
+
case "ByEventType" :
|
|
107
|
+
break;
|
|
74
108
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
109
|
+
}
|
|
110
|
+
let tag = partitionTagOfEvent(partitionTag, eventType, tags);
|
|
111
|
+
if (tag !== undefined) {
|
|
78
112
|
return tag.key + `:` + tag.value;
|
|
113
|
+
} else {
|
|
114
|
+
return "dcb";
|
|
79
115
|
}
|
|
80
|
-
let tag$1 = tags[0];
|
|
81
|
-
return tag$1.key + `:` + tag$1.value;
|
|
82
116
|
}
|
|
83
117
|
|
|
84
118
|
function toItem(position, event, partitionTag, recordedAt) {
|
|
85
119
|
let item = {};
|
|
86
|
-
item["id"] = derivePartitionKey(partitionTag, event.tags);
|
|
120
|
+
item["id"] = derivePartitionKey(partitionTag, event.eventType, event.tags);
|
|
87
121
|
item["position"] = position;
|
|
88
122
|
item["event"] = event.eventType;
|
|
89
123
|
item["data"] = event.data;
|
|
@@ -733,27 +767,15 @@ function makeCompositeFenceTag(tags, spec) {
|
|
|
733
767
|
|
|
734
768
|
function eventPartitionTags(event, partitionTag) {
|
|
735
769
|
if (partitionTag !== undefined) {
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
return [t];
|
|
743
|
-
}
|
|
744
|
-
let t$1 = event.tags[0];
|
|
745
|
-
if (t$1 !== undefined) {
|
|
746
|
-
return [t$1];
|
|
747
|
-
} else {
|
|
748
|
-
return [];
|
|
770
|
+
switch (partitionTag.TAG) {
|
|
771
|
+
case "Composite" :
|
|
772
|
+
return [makeCompositeFenceTag(event.tags, partitionTag._0)];
|
|
773
|
+
case "Simple" :
|
|
774
|
+
case "ByEventType" :
|
|
775
|
+
break;
|
|
749
776
|
}
|
|
750
777
|
}
|
|
751
|
-
|
|
752
|
-
if (t$2 !== undefined) {
|
|
753
|
-
return [t$2];
|
|
754
|
-
} else {
|
|
755
|
-
return [];
|
|
756
|
-
}
|
|
778
|
+
return Stdlib_Option.mapOr(partitionTagOfEvent(partitionTag, event.eventType, event.tags), [], t => [t]);
|
|
757
779
|
}
|
|
758
780
|
|
|
759
781
|
function collectEventPartitionTags(events, partitionTag) {
|
|
@@ -790,22 +812,30 @@ function partitionTypesByTag(events, partitionTag) {
|
|
|
790
812
|
function buildConditionalTransactItems(table, events, cond, basePosition, partitionTag, crossPartitionTagKeysOpt) {
|
|
791
813
|
let crossPartitionTagKeys = crossPartitionTagKeysOpt !== undefined ? crossPartitionTagKeysOpt : [];
|
|
792
814
|
let cond$1;
|
|
793
|
-
if (partitionTag !== undefined
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
815
|
+
if (partitionTag !== undefined) {
|
|
816
|
+
switch (partitionTag.TAG) {
|
|
817
|
+
case "Composite" :
|
|
818
|
+
let spec = partitionTag._0;
|
|
819
|
+
let newrecord = {...cond};
|
|
820
|
+
newrecord.query = cond.query.map(qi => {
|
|
821
|
+
let clauseTags = qi.tags;
|
|
822
|
+
if (clauseTags === undefined) {
|
|
823
|
+
return qi;
|
|
824
|
+
}
|
|
825
|
+
if (clauseTags.length <= 1) {
|
|
826
|
+
return qi;
|
|
827
|
+
}
|
|
828
|
+
let newrecord = {...qi};
|
|
829
|
+
newrecord.tags = [makeCompositeFenceTag(clauseTags, spec)];
|
|
830
|
+
return newrecord;
|
|
831
|
+
});
|
|
832
|
+
cond$1 = newrecord;
|
|
833
|
+
break;
|
|
834
|
+
case "Simple" :
|
|
835
|
+
case "ByEventType" :
|
|
836
|
+
cond$1 = cond;
|
|
837
|
+
break;
|
|
838
|
+
}
|
|
809
839
|
} else {
|
|
810
840
|
cond$1 = cond;
|
|
811
841
|
}
|
|
@@ -1166,6 +1196,7 @@ export {
|
|
|
1166
1196
|
compositeIndexName,
|
|
1167
1197
|
indexKeepsFullProjection,
|
|
1168
1198
|
compositeTagKey,
|
|
1199
|
+
partitionTagOfEvent,
|
|
1169
1200
|
derivePartitionKey,
|
|
1170
1201
|
toItem,
|
|
1171
1202
|
fromItem,
|
|
@@ -173,11 +173,7 @@ let make = (
|
|
|
173
173
|
~bundleRuntimeExtensions=false,
|
|
174
174
|
)
|
|
175
175
|
|
|
176
|
-
let layers =
|
|
177
|
-
Lambda.reventlessLayerArn
|
|
178
|
-
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
179
|
-
->Option.getOr([])
|
|
180
|
-
->Pulumi.Input.make
|
|
176
|
+
let layers = Lambda.reventlessLayers()
|
|
181
177
|
|
|
182
178
|
let appsyncEndpoint = AppSync_EventsApi.httpEndpoint(eventsApi)
|
|
183
179
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Aws from "@pulumi/aws";
|
|
4
4
|
import * as IAM$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/IAM.res.mjs";
|
|
5
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
5
|
import * as Pulumi from "@pulumi/pulumi";
|
|
7
6
|
import * as Lambda$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Lambda/Lambda.res.mjs";
|
|
8
7
|
import * as AWS$ReventlessAws from "../AWS.res.mjs";
|
|
@@ -90,7 +89,7 @@ function make(name, topicName, eventTopicOutputs, eventsApi, opts) {
|
|
|
90
89
|
Util_Bundle$ReventlessAws.resolvePackageRoot(undefined, "@reventlessdev/reventless-aws")
|
|
91
90
|
]]);
|
|
92
91
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/EventLogSubscription/EventLogSubscription_AppSync_Ops.res.mjs", packageDirs, undefined, false);
|
|
93
|
-
let layers =
|
|
92
|
+
let layers = Lambda$PulumiAws.reventlessLayers();
|
|
94
93
|
let appsyncEndpoint = AppSync_EventsApi$ReventlessAws.httpEndpoint(eventsApi);
|
|
95
94
|
let lambda = new (Aws.lambda.Function)(name + "EventLogSubscriber", {
|
|
96
95
|
handler: "index.handler",
|
|
@@ -115,11 +115,7 @@ let make = (
|
|
|
115
115
|
~bundleRuntimeExtensions=false,
|
|
116
116
|
)
|
|
117
117
|
|
|
118
|
-
let layers =
|
|
119
|
-
Lambda.reventlessLayerArn
|
|
120
|
-
->Option.map(arn => [arn->Pulumi.Input.make])
|
|
121
|
-
->Option.getOr([])
|
|
122
|
-
->Pulumi.Input.make
|
|
118
|
+
let layers = Lambda.reventlessLayers()
|
|
123
119
|
|
|
124
120
|
// Created before the function that writes to it — see
|
|
125
121
|
// `Util_LambdaLogging.makeManagedLogGroup` for why the ordering matters.
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import * as Aws from "@pulumi/aws";
|
|
4
4
|
import * as IAM$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/IAM.res.mjs";
|
|
5
5
|
import * as Output$Pulumi from "@reventlessdev/rescript-pulumi-pulumi/src/Output.res.mjs";
|
|
6
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
7
6
|
import * as Pulumi from "@pulumi/pulumi";
|
|
8
7
|
import * as Lambda$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Lambda/Lambda.res.mjs";
|
|
9
8
|
import * as AWS$ReventlessAws from "../AWS.res.mjs";
|
|
@@ -57,7 +56,7 @@ function make(api, placeIndexName, nameOpt, opts) {
|
|
|
57
56
|
Util_Bundle$ReventlessAws.resolvePackageRoot(undefined, "@reventlessdev/reventless-aws")
|
|
58
57
|
]]);
|
|
59
58
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Geocoder/Geocoder_AwsLocation_Resolver_Ops.res.mjs", packageDirs, undefined, false);
|
|
60
|
-
let layers =
|
|
59
|
+
let layers = Lambda$PulumiAws.reventlessLayers();
|
|
61
60
|
let logGroup = Util_LambdaLogging$ReventlessAws.makeManagedLogGroup(name + "Lambda", undefined, AWS_Tags$ReventlessAws.make(name + "LambdaLogGroup", "Platform", "Logs", "Platform", undefined, undefined, undefined, undefined), opts$1, undefined);
|
|
62
61
|
let lambda = new (Aws.lambda.Function)(name + "Lambda", {
|
|
63
62
|
handler: "index.handler",
|
|
@@ -27,6 +27,7 @@ let toEventCollectorJson = (
|
|
|
27
27
|
"id",
|
|
28
28
|
DcbEventLogStorage_DynamoDb_Runtime.derivePartitionKey(
|
|
29
29
|
~partitionTag?,
|
|
30
|
+
~eventType=event.eventType,
|
|
30
31
|
event.tags,
|
|
31
32
|
)->JSON.Encode.string,
|
|
32
33
|
)
|
|
@@ -55,10 +56,10 @@ let relayWithPool = async (
|
|
|
55
56
|
~pool: ReventlessPostgres.PgDriver.pool,
|
|
56
57
|
~logName: string,
|
|
57
58
|
~subscriber: string,
|
|
58
|
-
// ~partitionTagJson: the DCB log's partition
|
|
59
|
-
// by the relay builder (B2.3d). Parsed
|
|
60
|
-
// so the `id` the relay emits matches
|
|
61
|
-
// single-tag log derives the same id
|
|
59
|
+
// ~partitionTagJson: the DCB log's partition (the per-event-type key map, or a
|
|
60
|
+
// composite), sury-encoded into HANDLER_CONFIG by the relay builder (B2.3d). Parsed
|
|
61
|
+
// once via the shared derivedPartitionTagSchema so the `id` the relay emits matches
|
|
62
|
+
// the DynamoDB-stream path. Absent → None (a single-tag log derives the same id).
|
|
62
63
|
~partitionTagJson: option<JSON.t>=?,
|
|
63
64
|
~sendBatch: array<JSON.t> => promise<unit>,
|
|
64
65
|
): int => {
|
|
@@ -14,7 +14,7 @@ import * as DcbEventLogStorage_DynamoDb_Runtime$ReventlessAws from "../DcbEventL
|
|
|
14
14
|
|
|
15
15
|
function toEventCollectorJson(event, partitionTag) {
|
|
16
16
|
let item = {};
|
|
17
|
-
item["id"] = DcbEventLogStorage_DynamoDb_Runtime$ReventlessAws.derivePartitionKey(partitionTag, event.tags);
|
|
17
|
+
item["id"] = DcbEventLogStorage_DynamoDb_Runtime$ReventlessAws.derivePartitionKey(partitionTag, event.eventType, event.tags);
|
|
18
18
|
item["position"] = event.position;
|
|
19
19
|
item["event"] = event.eventType;
|
|
20
20
|
item["data"] = event.data;
|
|
@@ -88,7 +88,7 @@ let make = (
|
|
|
88
88
|
|
|
89
89
|
// Re-invoke whenever the migration code or the Reventless layer (which ships
|
|
90
90
|
// PgSchema's DDL) changes; idempotent DDL makes an unchanged re-run a no-op.
|
|
91
|
-
let layerArn = PulumiAws.Lambda.reventlessLayerArn
|
|
91
|
+
let layerArn = PulumiAws.Lambda.reventlessLayerArn()
|
|
92
92
|
let inputJson =
|
|
93
93
|
[("trigger", `${sourceCodeHash}:${layerArn}`->JSON.Encode.string)]
|
|
94
94
|
->Dict.fromArray
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import * as Aws from "@pulumi/aws";
|
|
4
4
|
import * as Output$Pulumi from "@reventlessdev/rescript-pulumi-pulumi/src/Output.res.mjs";
|
|
5
|
-
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
5
|
import * as Pulumi from "@pulumi/pulumi";
|
|
7
6
|
import * as Lambda$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/Lambda/Lambda.res.mjs";
|
|
8
7
|
import * as Adapter$ReventlessInfra from "@reventlessdev/reventless-infra/src/adapter/Adapter.res.mjs";
|
|
@@ -34,7 +33,7 @@ function make(name, handlerConfig, secretArn, securityGroupId, subnetIds, opts)
|
|
|
34
33
|
}]))),
|
|
35
34
|
role: runtime.parts.lambdaRole.id
|
|
36
35
|
});
|
|
37
|
-
let layerArn =
|
|
36
|
+
let layerArn = Lambda$PulumiAws.reventlessLayerArn();
|
|
38
37
|
let inputJson = JSON.stringify(Object.fromEntries([[
|
|
39
38
|
"trigger",
|
|
40
39
|
sourceCodeHash + `:` + layerArn
|
|
@@ -22,6 +22,7 @@ let makeCommandGenerator = (
|
|
|
22
22
|
~commandSchema,
|
|
23
23
|
~componentKind: ReventlessCore.CommandGenerator_Callback.commandComponentKind,
|
|
24
24
|
~stripIdFromParams: bool,
|
|
25
|
+
~partitionTag: option<Reventless.DcbTag.derivedPartitionTag>=?,
|
|
25
26
|
): ReventlessCore.CommandGenerator.commandGenerator =>
|
|
26
27
|
ReventlessCore.CommandGenerator_Callback.makeGenerateCommand(
|
|
27
28
|
~publishJsons,
|
|
@@ -30,4 +31,5 @@ let makeCommandGenerator = (
|
|
|
30
31
|
~commandSchema,
|
|
31
32
|
~componentKind,
|
|
32
33
|
~stripIdFromParams,
|
|
34
|
+
~partitionTag?,
|
|
33
35
|
)
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import * as CommandGenerator_Callback$ReventlessCore from "@reventlessdev/reventless-core/src/components/CommandGenerator/CommandGenerator_Callback.res.mjs";
|
|
4
4
|
|
|
5
|
-
function makeCommandGenerator(publishJsons, publishJsonsAndWait, serviceName, commandSchema, componentKind, stripIdFromParams) {
|
|
6
|
-
return CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(publishJsons, publishJsonsAndWait, serviceName, commandSchema, componentKind, stripIdFromParams);
|
|
5
|
+
function makeCommandGenerator(publishJsons, publishJsonsAndWait, serviceName, commandSchema, componentKind, stripIdFromParams, partitionTag) {
|
|
6
|
+
return CommandGenerator_Callback$ReventlessCore.makeGenerateCommand(publishJsons, publishJsonsAndWait, serviceName, commandSchema, componentKind, stripIdFromParams, partitionTag);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export {
|