@reventlessdev/reventless-aws 3.0.0-alpha.174 → 3.0.0-alpha.176
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 +21 -0
- package/package.json +10 -10
- package/src/Platform.res +115 -31
- package/src/Platform.res.mjs +217 -44
- package/src/adapter/DcbEventLog/DcbBackend.res +2 -2
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res +4 -1
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res.mjs +1 -1
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res +14 -4
- package/src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res.mjs +19 -14
- package/src/adapter/EventLog/EventLogBackend.res +82 -0
- package/src/adapter/EventLog/EventLogBackend.res.mjs +53 -0
- package/src/adapter/EventLog/EventLogStorage.res +15 -0
- package/src/adapter/EventLog/EventLogStorage.res.mjs +20 -1
- package/src/adapter/EventLog/EventLogStorage_Postgres.res +37 -0
- package/src/adapter/EventLog/EventLogStorage_Postgres.res.mjs +21 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +26 -11
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res.mjs +15 -6
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +78 -7
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res.mjs +30 -2
- package/src/adapter/Postgres/PgProjectionFeed.res +100 -0
- package/src/adapter/Postgres/PgProjectionFeed.res.mjs +54 -0
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res +192 -0
- package/src/adapter/QueryDb/PgQueryResolver_Lambda.res.mjs +141 -0
- package/src/adapter/QueryDb/QueryDbBackend.res +52 -0
- package/src/adapter/QueryDb/QueryDbBackend.res.mjs +44 -0
- package/src/adapter/QueryDb/QueryDbResolvers.res +48 -0
- package/src/adapter/QueryDb/QueryDbResolvers.res.mjs +17 -1
- package/src/adapter/QueryDb/QueryDbStorage.res +44 -0
- package/src/adapter/QueryDb/QueryDbStorage.res.mjs +34 -1
- package/src/adapter/QueryDb/QueryDbStorage_Postgres.res +43 -0
- package/src/adapter/QueryDb/QueryDbStorage_Postgres.res.mjs +21 -0
- package/src/adapter/QueryDb/QueryDbStorage_Postgres_Runtime.res +19 -0
- package/src/adapter/QueryDb/QueryDbStorage_Postgres_Runtime.res.mjs +15 -0
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +12 -1
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res.mjs +2 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res +83 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res.mjs +46 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res +83 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res.mjs +48 -3
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +130 -5
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +66 -6
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.mjs +15 -10
- package/src/adapter/Runtime/ReadModelEntryPoint.mjs +32 -15
- package/src/adapter/Runtime/StateViewSliceEntryPoint.mjs +26 -12
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res +138 -8
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res.mjs +76 -11
- package/src/components/Aggregate_Builder_Single.res +12 -5
- package/src/components/Aggregate_Builder_Single.res.mjs +12 -6
- package/src/components/Aggregate_Builder_Single_Async.res +12 -5
- package/src/components/Aggregate_Builder_Single_Async.res.mjs +12 -6
- package/src/components/ReadModel_Builder_NoResolver.res.mjs +1 -1
- package/src/components/ReadModel_Builder_NoResolver_Stream.res +13 -4
- package/src/components/ReadModel_Builder_NoResolver_Stream.res.mjs +14 -9
- package/src/components/ReadModel_Builder_Single.res +14 -5
- package/src/components/ReadModel_Builder_Single.res.mjs +15 -12
- package/src/components/ReadModel_Builder_Single_Stream.res +14 -5
- package/src/components/ReadModel_Builder_Single_Stream.res.mjs +15 -12
- package/src/components/StateViewSlice_Builder.res +10 -4
- package/src/components/StateViewSlice_Builder.res.mjs +8 -10
- package/src/components/StateViewSlice_Builder_Stream.res +10 -4
- package/src/components/StateViewSlice_Builder_Stream.res.mjs +8 -10
- package/src/plugin/runtime/PluginRuntime_Builder.res +12 -0
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +4 -0
- package/tests/EventCollectorChannelStreamRuntimeTest.res +55 -0
- package/tests/EventCollectorChannelStreamRuntimeTest.res.mjs +78 -0
- package/tests/PgChangeFeedRelay_IntegrationTest.res +259 -0
- package/tests/PgChangeFeedRelay_IntegrationTest.res.mjs +238 -0
- package/tests/PgPipeline_IntegrationTest.res +208 -0
- package/tests/PgPipeline_IntegrationTest.res.mjs +260 -0
- package/tests/PgQueryResolver_LambdaTest.res +206 -0
- package/tests/PgQueryResolver_LambdaTest.res.mjs +259 -0
|
@@ -16,8 +16,8 @@ module Make = (
|
|
|
16
16
|
Spec,
|
|
17
17
|
Mappings,
|
|
18
18
|
RuntimeEnvironment,
|
|
19
|
-
QueryDbStorage.
|
|
20
|
-
QueryDbResolvers.
|
|
19
|
+
QueryDbStorage.Selectable,
|
|
20
|
+
QueryDbResolvers.Selectable,
|
|
21
21
|
EventCollectorChannel,
|
|
22
22
|
EventCollectorRuntimeBuilder,
|
|
23
23
|
)
|
|
@@ -31,15 +31,24 @@ module Make = (
|
|
|
31
31
|
let make = (~api, ~apiRole, ~allEventTopics, ~opts=?): component => {
|
|
32
32
|
let readModel = Inner.make(~api, ~apiRole, ~allEventTopics, ~opts?)
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
// On the Postgres backend there is no DynamoDB table (resources is empty) —
|
|
35
|
+
// the read-model spec name is the stable `qdb_<name>` discriminator, both
|
|
36
|
+
// here and in the entry point's Postgres branch.
|
|
37
|
+
let pgBacked = QueryDbBackend.isPostgresFor(Spec.name)
|
|
38
|
+
let queryDbTableName = if pgBacked {
|
|
39
|
+
Pulumi.Output.make(Spec.name)
|
|
40
|
+
} else {
|
|
41
|
+
let queryDbOutputs = (readModel->Inner.outputs).queryDb
|
|
42
|
+
let tableResource = queryDbOutputs.resources->Array.getUnsafe(0)
|
|
43
|
+
tableResource.name
|
|
44
|
+
}
|
|
37
45
|
|
|
38
46
|
EventCollectorRuntimeBuilder.registerReadModel(
|
|
39
47
|
~readModelName=Spec.name,
|
|
40
48
|
~specModulePath=Util_Bundle.getModuleSpecifier(Spec.moduleUrl),
|
|
41
49
|
~mappingsModulePath=Util_Bundle.getModuleSpecifier(Mappings.moduleUrl),
|
|
42
50
|
~queryDbTableName,
|
|
51
|
+
~pgBacked,
|
|
43
52
|
)
|
|
44
53
|
|
|
45
54
|
readModel
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
3
4
|
import * as Util_Bundle$ReventlessAws from "../util/Util_Bundle.res.mjs";
|
|
5
|
+
import * as QueryDbBackend$ReventlessAws from "../adapter/QueryDb/QueryDbBackend.res.mjs";
|
|
6
|
+
import * as QueryDbStorage$ReventlessAws from "../adapter/QueryDb/QueryDbStorage.res.mjs";
|
|
7
|
+
import * as QueryDbResolvers$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers.res.mjs";
|
|
4
8
|
import * as ReadModel_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/ReadModel/ReadModel_Builder.res.mjs";
|
|
5
|
-
import * as QueryDbStorage_DynamoDb$ReventlessAws from "../adapter/QueryDb/QueryDbStorage_DynamoDb.res.mjs";
|
|
6
|
-
import * as QueryDbResolvers_AppSync$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs";
|
|
7
9
|
import * as RuntimeEnvironment_Lambda$ReventlessAws from "../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
|
|
8
10
|
import * as EventCollectorChannel_DynamoDbStream$ReventlessAws from "../adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res.mjs";
|
|
9
11
|
import * as EventCollectorRuntime_Builder_Single$ReventlessAws from "../adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs";
|
|
@@ -16,11 +18,7 @@ function Make(Spec) {
|
|
|
16
18
|
extractCorrelationId: RuntimeEnvironment_Lambda$ReventlessAws.extractCorrelationId,
|
|
17
19
|
asEventHandler: prim => prim,
|
|
18
20
|
asEffectHandler: prim => prim
|
|
19
|
-
})({
|
|
20
|
-
make: QueryDbStorage_DynamoDb$ReventlessAws.make
|
|
21
|
-
})({
|
|
22
|
-
make: QueryDbResolvers_AppSync$ReventlessAws.make
|
|
23
|
-
})({
|
|
21
|
+
})(QueryDbStorage$ReventlessAws.Selectable)(QueryDbResolvers$ReventlessAws.Selectable)({
|
|
24
22
|
make: EventCollectorChannel_DynamoDbStream$ReventlessAws.make,
|
|
25
23
|
connect: EventCollectorChannel_DynamoDbStream$ReventlessAws.connect
|
|
26
24
|
})({
|
|
@@ -33,10 +31,15 @@ function Make(Spec) {
|
|
|
33
31
|
});
|
|
34
32
|
let make = (api, apiRole, allEventTopics, opts) => {
|
|
35
33
|
let readModel = Inner.make(api, apiRole, allEventTopics, opts);
|
|
36
|
-
let
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
let pgBacked = QueryDbBackend$ReventlessAws.isPostgresFor(Inner.Spec.name);
|
|
35
|
+
let queryDbTableName;
|
|
36
|
+
if (pgBacked) {
|
|
37
|
+
queryDbTableName = Pulumi.output(Inner.Spec.name);
|
|
38
|
+
} else {
|
|
39
|
+
let queryDbOutputs = Inner.outputs(readModel).queryDb;
|
|
40
|
+
queryDbTableName = queryDbOutputs.resources[0].name;
|
|
41
|
+
}
|
|
42
|
+
EventCollectorRuntime_Builder_Single$ReventlessAws.registerReadModel(Inner.Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Inner.Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Mappings.moduleUrl), queryDbTableName, pgBacked);
|
|
40
43
|
return readModel;
|
|
41
44
|
};
|
|
42
45
|
let finish = () => EventCollectorRuntime_Builder_Single$ReventlessAws.finish();
|
|
@@ -64,4 +67,4 @@ export {
|
|
|
64
67
|
EventCollectorRuntimeBuilder,
|
|
65
68
|
Make,
|
|
66
69
|
}
|
|
67
|
-
/*
|
|
70
|
+
/* @pulumi/pulumi Not a pure module */
|
|
@@ -24,8 +24,8 @@ module Make = (
|
|
|
24
24
|
Spec,
|
|
25
25
|
Mappings,
|
|
26
26
|
RuntimeEnvironment,
|
|
27
|
-
|
|
28
|
-
QueryDbResolvers.
|
|
27
|
+
QueryDbStorage.SelectableStream,
|
|
28
|
+
QueryDbResolvers.Selectable,
|
|
29
29
|
EventCollectorChannel,
|
|
30
30
|
EventCollectorRuntimeBuilder,
|
|
31
31
|
)
|
|
@@ -39,15 +39,24 @@ module Make = (
|
|
|
39
39
|
let make = (~api, ~apiRole, ~allEventTopics, ~opts=?): component => {
|
|
40
40
|
let readModel = Inner.make(~api, ~apiRole, ~allEventTopics, ~opts?)
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
// On the Postgres backend there is no DynamoDB table (resources is empty) —
|
|
43
|
+
// the read-model spec name is the stable `qdb_<name>` discriminator, both
|
|
44
|
+
// here and in the entry point's Postgres branch.
|
|
45
|
+
let pgBacked = QueryDbBackend.isPostgresFor(Spec.name)
|
|
46
|
+
let queryDbTableName = if pgBacked {
|
|
47
|
+
Pulumi.Output.make(Spec.name)
|
|
48
|
+
} else {
|
|
49
|
+
let queryDbOutputs = (readModel->Inner.outputs).queryDb
|
|
50
|
+
let tableResource = queryDbOutputs.resources->Array.getUnsafe(0)
|
|
51
|
+
tableResource.name
|
|
52
|
+
}
|
|
45
53
|
|
|
46
54
|
EventCollectorRuntimeBuilder.registerReadModel(
|
|
47
55
|
~readModelName=Spec.name,
|
|
48
56
|
~specModulePath=Util_Bundle.getModuleSpecifier(Spec.moduleUrl),
|
|
49
57
|
~mappingsModulePath=Util_Bundle.getModuleSpecifier(Mappings.moduleUrl),
|
|
50
58
|
~queryDbTableName,
|
|
59
|
+
~pgBacked,
|
|
51
60
|
)
|
|
52
61
|
|
|
53
62
|
readModel
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
3
4
|
import * as Util_Bundle$ReventlessAws from "../util/Util_Bundle.res.mjs";
|
|
5
|
+
import * as QueryDbBackend$ReventlessAws from "../adapter/QueryDb/QueryDbBackend.res.mjs";
|
|
6
|
+
import * as QueryDbStorage$ReventlessAws from "../adapter/QueryDb/QueryDbStorage.res.mjs";
|
|
7
|
+
import * as QueryDbResolvers$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers.res.mjs";
|
|
4
8
|
import * as ReadModel_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/ReadModel/ReadModel_Builder.res.mjs";
|
|
5
|
-
import * as QueryDbResolvers_AppSync$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs";
|
|
6
9
|
import * as RuntimeEnvironment_Lambda$ReventlessAws from "../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
|
|
7
|
-
import * as QueryDbStorage_DynamoDbStream$ReventlessAws from "../adapter/QueryDb/QueryDbStorage_DynamoDbStream.res.mjs";
|
|
8
10
|
import * as EventCollectorChannel_DynamoDbStream$ReventlessAws from "../adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res.mjs";
|
|
9
11
|
import * as EventCollectorRuntime_Builder_Single$ReventlessAws from "../adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs";
|
|
10
12
|
|
|
@@ -16,11 +18,7 @@ function Make(Spec) {
|
|
|
16
18
|
extractCorrelationId: RuntimeEnvironment_Lambda$ReventlessAws.extractCorrelationId,
|
|
17
19
|
asEventHandler: prim => prim,
|
|
18
20
|
asEffectHandler: prim => prim
|
|
19
|
-
})({
|
|
20
|
-
make: QueryDbStorage_DynamoDbStream$ReventlessAws.make
|
|
21
|
-
})({
|
|
22
|
-
make: QueryDbResolvers_AppSync$ReventlessAws.make
|
|
23
|
-
})({
|
|
21
|
+
})(QueryDbStorage$ReventlessAws.SelectableStream)(QueryDbResolvers$ReventlessAws.Selectable)({
|
|
24
22
|
make: EventCollectorChannel_DynamoDbStream$ReventlessAws.make,
|
|
25
23
|
connect: EventCollectorChannel_DynamoDbStream$ReventlessAws.connect
|
|
26
24
|
})({
|
|
@@ -33,10 +31,15 @@ function Make(Spec) {
|
|
|
33
31
|
});
|
|
34
32
|
let make = (api, apiRole, allEventTopics, opts) => {
|
|
35
33
|
let readModel = Inner.make(api, apiRole, allEventTopics, opts);
|
|
36
|
-
let
|
|
37
|
-
let
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
let pgBacked = QueryDbBackend$ReventlessAws.isPostgresFor(Inner.Spec.name);
|
|
35
|
+
let queryDbTableName;
|
|
36
|
+
if (pgBacked) {
|
|
37
|
+
queryDbTableName = Pulumi.output(Inner.Spec.name);
|
|
38
|
+
} else {
|
|
39
|
+
let queryDbOutputs = Inner.outputs(readModel).queryDb;
|
|
40
|
+
queryDbTableName = queryDbOutputs.resources[0].name;
|
|
41
|
+
}
|
|
42
|
+
EventCollectorRuntime_Builder_Single$ReventlessAws.registerReadModel(Inner.Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Inner.Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Mappings.moduleUrl), queryDbTableName, pgBacked);
|
|
40
43
|
return readModel;
|
|
41
44
|
};
|
|
42
45
|
let finish = () => EventCollectorRuntime_Builder_Single$ReventlessAws.finish();
|
|
@@ -64,4 +67,4 @@ export {
|
|
|
64
67
|
EventCollectorRuntimeBuilder,
|
|
65
68
|
Make,
|
|
66
69
|
}
|
|
67
|
-
/*
|
|
70
|
+
/* @pulumi/pulumi Not a pure module */
|
|
@@ -11,8 +11,8 @@ module Make = (Api: {
|
|
|
11
11
|
}) => {
|
|
12
12
|
module Inner = ReventlessCore.StateViewSlice_Builder.Make(
|
|
13
13
|
RuntimeEnvironment,
|
|
14
|
-
QueryDbStorage.
|
|
15
|
-
QueryDbResolvers.
|
|
14
|
+
QueryDbStorage.Selectable,
|
|
15
|
+
QueryDbResolvers.Selectable,
|
|
16
16
|
EventCollectorChannel,
|
|
17
17
|
EventCollectorRuntimeBuilder,
|
|
18
18
|
Api,
|
|
@@ -32,12 +32,18 @@ module Make = (Api: {
|
|
|
32
32
|
let make = (~dcbEventLog, ~opts=?): component => {
|
|
33
33
|
let sv = InnerMake.make(~dcbEventLog, ~opts?)
|
|
34
34
|
let queryDbOutputs = (sv->ReventlessCore.Component.outputs).queryDb
|
|
35
|
-
|
|
35
|
+
// On the Postgres backend there is no DynamoDB table (resources is
|
|
36
|
+
// empty) — the slice spec name is the stable `qdb_<name>` discriminator.
|
|
37
|
+
let queryDbTableName = if QueryDbBackend.isPostgresFor(Spec.name) {
|
|
38
|
+
Pulumi.Output.make(Spec.name)
|
|
39
|
+
} else {
|
|
40
|
+
(queryDbOutputs.resources->Array.getUnsafe(0)).name
|
|
41
|
+
}
|
|
36
42
|
EventCollectorRuntimeBuilder.registerStateViewSlice(
|
|
37
43
|
~name=Spec.name,
|
|
38
44
|
~specModulePath=Util_Bundle.getModuleSpecifier(Spec.moduleUrl),
|
|
39
45
|
~projectionModulePath=Util_Bundle.getModuleSpecifier(Projection.moduleUrl),
|
|
40
|
-
~queryDbTableName
|
|
46
|
+
~queryDbTableName,
|
|
41
47
|
~queryDbResources=queryDbOutputs.resources,
|
|
42
48
|
)
|
|
43
49
|
sv
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
3
4
|
import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
|
|
4
5
|
import * as Util_Bundle$ReventlessAws from "../util/Util_Bundle.res.mjs";
|
|
5
|
-
import * as
|
|
6
|
+
import * as QueryDbBackend$ReventlessAws from "../adapter/QueryDb/QueryDbBackend.res.mjs";
|
|
7
|
+
import * as QueryDbStorage$ReventlessAws from "../adapter/QueryDb/QueryDbStorage.res.mjs";
|
|
8
|
+
import * as QueryDbResolvers$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers.res.mjs";
|
|
6
9
|
import * as StateViewSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs";
|
|
7
|
-
import * as QueryDbResolvers_AppSync$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs";
|
|
8
10
|
import * as RuntimeEnvironment_Lambda$ReventlessAws from "../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
|
|
9
11
|
import * as EventCollectorChannel_DynamoDbStream$ReventlessAws from "../adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res.mjs";
|
|
10
12
|
import * as StateViewSliceRuntime_Builder_Single$ReventlessAws from "../adapter/Runtime/StateViewSliceRuntime_Builder_Single.res.mjs";
|
|
@@ -16,11 +18,7 @@ function Make(Api) {
|
|
|
16
18
|
extractCorrelationId: RuntimeEnvironment_Lambda$ReventlessAws.extractCorrelationId,
|
|
17
19
|
asEventHandler: prim => prim,
|
|
18
20
|
asEffectHandler: prim => prim
|
|
19
|
-
})({
|
|
20
|
-
make: QueryDbStorage_DynamoDb$ReventlessAws.make
|
|
21
|
-
})({
|
|
22
|
-
make: QueryDbResolvers_AppSync$ReventlessAws.make
|
|
23
|
-
})({
|
|
21
|
+
})(QueryDbStorage$ReventlessAws.Selectable)(QueryDbResolvers$ReventlessAws.Selectable)({
|
|
24
22
|
make: EventCollectorChannel_DynamoDbStream$ReventlessAws.make,
|
|
25
23
|
connect: EventCollectorChannel_DynamoDbStream$ReventlessAws.connect
|
|
26
24
|
})({
|
|
@@ -36,8 +34,8 @@ function Make(Api) {
|
|
|
36
34
|
let make = (dcbEventLog, opts) => {
|
|
37
35
|
let sv = InnerMake.make(dcbEventLog, opts);
|
|
38
36
|
let queryDbOutputs = Component$ReventlessCore.outputs(sv).queryDb;
|
|
39
|
-
let
|
|
40
|
-
StateViewSliceRuntime_Builder_Single$ReventlessAws.registerStateViewSlice(Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Projection.moduleUrl),
|
|
37
|
+
let queryDbTableName = QueryDbBackend$ReventlessAws.isPostgresFor(Spec.name) ? Pulumi.output(Spec.name) : queryDbOutputs.resources[0].name;
|
|
38
|
+
StateViewSliceRuntime_Builder_Single$ReventlessAws.registerStateViewSlice(Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Projection.moduleUrl), queryDbTableName, queryDbOutputs.resources);
|
|
41
39
|
return sv;
|
|
42
40
|
};
|
|
43
41
|
return {
|
|
@@ -65,4 +63,4 @@ export {
|
|
|
65
63
|
EventCollectorRuntimeBuilder,
|
|
66
64
|
Make,
|
|
67
65
|
}
|
|
68
|
-
/*
|
|
66
|
+
/* @pulumi/pulumi Not a pure module */
|
|
@@ -15,8 +15,8 @@ module Make = (Api: {
|
|
|
15
15
|
}) => {
|
|
16
16
|
module Inner = ReventlessCore.StateViewSlice_Builder.Make(
|
|
17
17
|
RuntimeEnvironment,
|
|
18
|
-
|
|
19
|
-
QueryDbResolvers.
|
|
18
|
+
QueryDbStorage.SelectableStream,
|
|
19
|
+
QueryDbResolvers.Selectable,
|
|
20
20
|
EventCollectorChannel,
|
|
21
21
|
EventCollectorRuntimeBuilder,
|
|
22
22
|
Api,
|
|
@@ -36,12 +36,18 @@ module Make = (Api: {
|
|
|
36
36
|
let make = (~dcbEventLog, ~opts=?): component => {
|
|
37
37
|
let sv = InnerMake.make(~dcbEventLog, ~opts?)
|
|
38
38
|
let queryDbOutputs = (sv->ReventlessCore.Component.outputs).queryDb
|
|
39
|
-
|
|
39
|
+
// On the Postgres backend there is no DynamoDB table (resources is
|
|
40
|
+
// empty) — the slice spec name is the stable `qdb_<name>` discriminator.
|
|
41
|
+
let queryDbTableName = if QueryDbBackend.isPostgresFor(Spec.name) {
|
|
42
|
+
Pulumi.Output.make(Spec.name)
|
|
43
|
+
} else {
|
|
44
|
+
(queryDbOutputs.resources->Array.getUnsafe(0)).name
|
|
45
|
+
}
|
|
40
46
|
EventCollectorRuntimeBuilder.registerStateViewSlice(
|
|
41
47
|
~name=Spec.name,
|
|
42
48
|
~specModulePath=Util_Bundle.getModuleSpecifier(Spec.moduleUrl),
|
|
43
49
|
~projectionModulePath=Util_Bundle.getModuleSpecifier(Projection.moduleUrl),
|
|
44
|
-
~queryDbTableName
|
|
50
|
+
~queryDbTableName,
|
|
45
51
|
~queryDbResources=queryDbOutputs.resources,
|
|
46
52
|
)
|
|
47
53
|
sv
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
3
4
|
import * as Component$ReventlessCore from "@reventlessdev/reventless-core/src/components/Component.res.mjs";
|
|
4
5
|
import * as Util_Bundle$ReventlessAws from "../util/Util_Bundle.res.mjs";
|
|
6
|
+
import * as QueryDbBackend$ReventlessAws from "../adapter/QueryDb/QueryDbBackend.res.mjs";
|
|
7
|
+
import * as QueryDbStorage$ReventlessAws from "../adapter/QueryDb/QueryDbStorage.res.mjs";
|
|
8
|
+
import * as QueryDbResolvers$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers.res.mjs";
|
|
5
9
|
import * as StateViewSlice_Builder$ReventlessCore from "@reventlessdev/reventless-core/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs";
|
|
6
|
-
import * as QueryDbResolvers_AppSync$ReventlessAws from "../adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs";
|
|
7
10
|
import * as RuntimeEnvironment_Lambda$ReventlessAws from "../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
|
|
8
|
-
import * as QueryDbStorage_DynamoDbStream$ReventlessAws from "../adapter/QueryDb/QueryDbStorage_DynamoDbStream.res.mjs";
|
|
9
11
|
import * as EventCollectorChannel_DynamoDbStream$ReventlessAws from "../adapter/EventCollector/EventCollectorChannel_DynamoDbStream.res.mjs";
|
|
10
12
|
import * as StateViewSliceRuntime_Builder_Single$ReventlessAws from "../adapter/Runtime/StateViewSliceRuntime_Builder_Single.res.mjs";
|
|
11
13
|
|
|
@@ -16,11 +18,7 @@ function Make(Api) {
|
|
|
16
18
|
extractCorrelationId: RuntimeEnvironment_Lambda$ReventlessAws.extractCorrelationId,
|
|
17
19
|
asEventHandler: prim => prim,
|
|
18
20
|
asEffectHandler: prim => prim
|
|
19
|
-
})({
|
|
20
|
-
make: QueryDbStorage_DynamoDbStream$ReventlessAws.make
|
|
21
|
-
})({
|
|
22
|
-
make: QueryDbResolvers_AppSync$ReventlessAws.make
|
|
23
|
-
})({
|
|
21
|
+
})(QueryDbStorage$ReventlessAws.SelectableStream)(QueryDbResolvers$ReventlessAws.Selectable)({
|
|
24
22
|
make: EventCollectorChannel_DynamoDbStream$ReventlessAws.make,
|
|
25
23
|
connect: EventCollectorChannel_DynamoDbStream$ReventlessAws.connect
|
|
26
24
|
})({
|
|
@@ -36,8 +34,8 @@ function Make(Api) {
|
|
|
36
34
|
let make = (dcbEventLog, opts) => {
|
|
37
35
|
let sv = InnerMake.make(dcbEventLog, opts);
|
|
38
36
|
let queryDbOutputs = Component$ReventlessCore.outputs(sv).queryDb;
|
|
39
|
-
let
|
|
40
|
-
StateViewSliceRuntime_Builder_Single$ReventlessAws.registerStateViewSlice(Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Projection.moduleUrl),
|
|
37
|
+
let queryDbTableName = QueryDbBackend$ReventlessAws.isPostgresFor(Spec.name) ? Pulumi.output(Spec.name) : queryDbOutputs.resources[0].name;
|
|
38
|
+
StateViewSliceRuntime_Builder_Single$ReventlessAws.registerStateViewSlice(Spec.name, Util_Bundle$ReventlessAws.getModuleSpecifier(Spec.moduleUrl), Util_Bundle$ReventlessAws.getModuleSpecifier(Projection.moduleUrl), queryDbTableName, queryDbOutputs.resources);
|
|
41
39
|
return sv;
|
|
42
40
|
};
|
|
43
41
|
return {
|
|
@@ -65,4 +63,4 @@ export {
|
|
|
65
63
|
EventCollectorRuntimeBuilder,
|
|
66
64
|
Make,
|
|
67
65
|
}
|
|
68
|
-
/*
|
|
66
|
+
/* @pulumi/pulumi Not a pure module */
|
|
@@ -216,6 +216,18 @@ module Make = (
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
// Classic Postgres logs: `~eventTopics` is keyed by aggregate name, so each key
|
|
220
|
+
// attaches this plugin's EventCollector queue to exactly the aggregates whose
|
|
221
|
+
// event-log DynamoDB stream the collector would have subscribed on the DynamoDB
|
|
222
|
+
// path (admin's extension-point filtering included).
|
|
223
|
+
if EventLogBackend.isPostgres() {
|
|
224
|
+
eventTopics
|
|
225
|
+
->Dict.keysToArray
|
|
226
|
+
->Array.forEach(aggregateName =>
|
|
227
|
+
EventLogBackend.attachCollectorQueue(~aggregateName, ~url=queue.id, ~arn=queue.arn)
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
219
231
|
// Pull the per-EventCollector context registered by Plugin_Helpers.connect
|
|
220
232
|
// (plugins) or synthesise an admin one if none registered.
|
|
221
233
|
let context: ReventlessCore.Plugin_Helpers.eventCollectorContext =
|
|
@@ -14,6 +14,7 @@ import * as PluginSpec$ReventlessCore from "@reventlessdev/reventless-core/src/p
|
|
|
14
14
|
import * as Util_Bundle$ReventlessAws from "../../util/Util_Bundle.res.mjs";
|
|
15
15
|
import * as ComponentType$ReventlessCore from "@reventlessdev/reventless-core/src/ComponentType.res.mjs";
|
|
16
16
|
import * as EventCollector$ReventlessCore from "@reventlessdev/reventless-core/src/components/EventCollector/EventCollector.res.mjs";
|
|
17
|
+
import * as EventLogBackend$ReventlessAws from "../../adapter/EventLog/EventLogBackend.res.mjs";
|
|
17
18
|
import * as Plugin_Helpers$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/component/Plugin_Helpers.res.mjs";
|
|
18
19
|
import * as RuntimeEnvironment_Lambda$ReventlessAws from "../../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
|
|
19
20
|
import * as StateChangeSliceRuntime_Builder_Single$ReventlessAws from "../../adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs";
|
|
@@ -174,6 +175,9 @@ function Make(EventCollectorChannel) {
|
|
|
174
175
|
DcbBackend$ReventlessAws.attachCollectorQueue(pluginName + "DcbEventLog", queue.id, queue.arn);
|
|
175
176
|
}
|
|
176
177
|
}
|
|
178
|
+
if (EventLogBackend$ReventlessAws.isPostgres()) {
|
|
179
|
+
Object.keys(eventTopics).forEach(aggregateName => EventLogBackend$ReventlessAws.attachCollectorQueue(aggregateName, queue.id, queue.arn));
|
|
180
|
+
}
|
|
177
181
|
let ctx = Plugin_Helpers$ReventlessCore.eventCollectorContextRef.contents[name];
|
|
178
182
|
let context = ctx !== undefined ? ctx : synthesizeAdminContext();
|
|
179
183
|
let envVars = {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// B3.0: the ReadModel/StateViewSlice record decoder must accept BOTH DynamoDB
|
|
2
|
+
// stream records (DynamoDB backend) and SQS records (Postgres backend — bodies
|
|
3
|
+
// injected by the PgChangeFeedRelay via the projection feed queue), in one batch.
|
|
4
|
+
|
|
5
|
+
open JestGlobals
|
|
6
|
+
|
|
7
|
+
let mkEvent = (records): PulumiAws.Lambda.CallbackFunction.event => Obj.magic({"Records": records})
|
|
8
|
+
|
|
9
|
+
let sqsRecord = body =>
|
|
10
|
+
{
|
|
11
|
+
"eventSource": "aws:sqs",
|
|
12
|
+
"eventSourceARN": "arn:aws:sqs:eu-west-1:1:AllReadModelsFeed",
|
|
13
|
+
"body": body,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let run = event => {
|
|
17
|
+
let seen: array<JSON.t> = []
|
|
18
|
+
let handler: ReventlessCore.EventCollector.jsonEventsHandler = stream =>
|
|
19
|
+
stream
|
|
20
|
+
->Stream.runForEach(json => Effect.succeed(seen->Array.push(json)->ignore))
|
|
21
|
+
->Effect.map(_ => ())
|
|
22
|
+
EventCollectorChannel_DynamoDbStream_Runtime.handleStreamEvent(handler, event, ())
|
|
23
|
+
->Effect.runPromise
|
|
24
|
+
->Promise.thenResolve(_ => seen)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe("handleStreamEvent (ReadModel/SVS record decoder)", () => {
|
|
28
|
+
test("parses SQS feed-queue records into their JSON bodies", async () => {
|
|
29
|
+
let seen = await run(
|
|
30
|
+
mkEvent([
|
|
31
|
+
sqsRecord(`{"id":"agg-1","meta":{"service":"Product"},"event":{"type":"Added","data":{}}}`),
|
|
32
|
+
sqsRecord(`{"id":"agg-2","meta":{"service":"Product"},"event":{"type":"Added","data":{}}}`),
|
|
33
|
+
]),
|
|
34
|
+
)
|
|
35
|
+
expect(seen->Array.length)->toBe(2)
|
|
36
|
+
let id0 =
|
|
37
|
+
seen
|
|
38
|
+
->Array.getUnsafe(0)
|
|
39
|
+
->JSON.Decode.object
|
|
40
|
+
->Option.flatMap(o => o->Dict.get("id"))
|
|
41
|
+
->Option.flatMap(JSON.Decode.string)
|
|
42
|
+
expect(id0)->toEqual(Some("agg-1"))
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test("skips malformed SQS bodies and unknown sources without failing the batch", async () => {
|
|
46
|
+
let seen = await run(
|
|
47
|
+
mkEvent([
|
|
48
|
+
sqsRecord("not-json"),
|
|
49
|
+
{"eventSource": "aws:kinesis", "eventSourceARN": "arn:x", "body": "{}"},
|
|
50
|
+
sqsRecord(`{"ok":true}`),
|
|
51
|
+
]),
|
|
52
|
+
)
|
|
53
|
+
expect(seen->Array.length)->toBe(1)
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
4
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Stream from "effect/Stream";
|
|
7
|
+
import * as EventCollectorChannel_DynamoDbStream_Runtime$ReventlessAws from "../src/adapter/EventCollector/EventCollectorChannel_DynamoDbStream_Runtime.res.mjs";
|
|
8
|
+
|
|
9
|
+
function mkEvent(records) {
|
|
10
|
+
return {
|
|
11
|
+
Records: records
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function sqsRecord(body) {
|
|
16
|
+
return {
|
|
17
|
+
eventSource: "aws:sqs",
|
|
18
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:1:AllReadModelsFeed",
|
|
19
|
+
body: body
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function run(event) {
|
|
24
|
+
let seen = [];
|
|
25
|
+
let handler = stream => Effect.map(Stream.runForEach(stream, json => Effect.succeed((seen.push(json), undefined))), () => {});
|
|
26
|
+
return Effect.runPromise(EventCollectorChannel_DynamoDbStream_Runtime$ReventlessAws.handleStreamEvent(handler, event, undefined)).then(() => seen);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
globalThis.describe("handleStreamEvent (ReadModel/SVS record decoder)", () => {
|
|
30
|
+
globalThis.test("parses SQS feed-queue records into their JSON bodies", async () => {
|
|
31
|
+
let seen = await run({
|
|
32
|
+
Records: [
|
|
33
|
+
{
|
|
34
|
+
eventSource: "aws:sqs",
|
|
35
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:1:AllReadModelsFeed",
|
|
36
|
+
body: `{"id":"agg-1","meta":{"service":"Product"},"event":{"type":"Added","data":{}}}`
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
eventSource: "aws:sqs",
|
|
40
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:1:AllReadModelsFeed",
|
|
41
|
+
body: `{"id":"agg-2","meta":{"service":"Product"},"event":{"type":"Added","data":{}}}`
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
});
|
|
45
|
+
globalThis.expect(seen.length).toBe(2);
|
|
46
|
+
let id0 = Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(seen[0]), o => o["id"]), Stdlib_JSON.Decode.string);
|
|
47
|
+
globalThis.expect(id0).toEqual("agg-1");
|
|
48
|
+
});
|
|
49
|
+
globalThis.test("skips malformed SQS bodies and unknown sources without failing the batch", async () => {
|
|
50
|
+
let seen = await run({
|
|
51
|
+
Records: [
|
|
52
|
+
{
|
|
53
|
+
eventSource: "aws:sqs",
|
|
54
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:1:AllReadModelsFeed",
|
|
55
|
+
body: "not-json"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
eventSource: "aws:kinesis",
|
|
59
|
+
eventSourceARN: "arn:x",
|
|
60
|
+
body: "{}"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
eventSource: "aws:sqs",
|
|
64
|
+
eventSourceARN: "arn:aws:sqs:eu-west-1:1:AllReadModelsFeed",
|
|
65
|
+
body: `{"ok":true}`
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
});
|
|
69
|
+
globalThis.expect(seen.length).toBe(1);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
mkEvent,
|
|
75
|
+
sqsRecord,
|
|
76
|
+
run,
|
|
77
|
+
}
|
|
78
|
+
/* Not a pure module */
|