@reventlessdev/reventless-aws 3.0.0-alpha.171 → 3.0.0-alpha.173
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 +23 -0
- package/package.json +6 -5
- package/rescript.json +2 -1
- package/src/Platform.res.mjs +5 -5
- package/src/adapter/Counter/CounterHandler_DynamoDbStream.res.mjs +1 -1
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +12 -6
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs +17 -5
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Postgres_Runtime.res +26 -0
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Postgres_Runtime.res.mjs +15 -0
- package/src/adapter/EventLog/EventLogStorage_Postgres_Runtime.res +23 -0
- package/src/adapter/EventLog/EventLogStorage_Postgres_Runtime.res.mjs +14 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res +181 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Builder.res.mjs +135 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +64 -0
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res.mjs +36 -0
- package/src/adapter/Postgres/PgConnection.res +169 -0
- package/src/adapter/Postgres/PgConnection.res.mjs +112 -0
- package/src/adapter/Postgres/PgRuntime.res +71 -0
- package/src/adapter/Postgres/PgRuntime.res.mjs +71 -0
- package/src/adapter/Runtime/AggregateEntryPoint.mjs +27 -9
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res.mjs +3 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro_Async.res.mjs +3 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_PerAggregate_Async.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/AggregateRuntime_Builder_Single_Async.res.mjs +1 -1
- package/src/adapter/Runtime/AutomationSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +20 -6
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res.mjs +1 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res.mjs +1 -1
- package/src/adapter/Runtime/PgChangeFeedRelayEntryPoint.mjs +52 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +38 -0
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs +20 -2
- package/src/adapter/Runtime/SideEffectHandlerRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/StateViewSliceRuntime_Builder_Single.res.mjs +1 -1
- package/src/adapter/Runtime/TaskRuntime_Builder_PerBucket.res.mjs +1 -1
- package/src/components/Api/AppSync_Adapter.res +72 -8
- package/src/components/Api/AppSync_Adapter.res.mjs +45 -6
- package/src/plugin/runtime/PluginExtensionPointRuntime_Builder.res.mjs +1 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +2 -2
- package/src/util/Util_AppSync_Caller.res +24 -4
- package/src/util/Util_AppSync_Caller.res.mjs +7 -4
- package/tests/AppSync_AdapterTest.res +140 -0
- package/tests/AppSync_AdapterTest.res.mjs +182 -6
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +7 -3
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res.mjs +18 -3
- package/tests/PgChangeFeedRelay_RuntimeTest.res +44 -0
- package/tests/PgChangeFeedRelay_RuntimeTest.res.mjs +70 -0
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +2 -1
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res.mjs +2 -2
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Postgres change-feed relay runtime (B2.2).
|
|
2
|
+
//
|
|
3
|
+
// Drains a Postgres DCB log via `PgChangeFeed` and pushes each event — transformed
|
|
4
|
+
// into the `{id, meta, event}` shape the plugin EventCollector SQS handler
|
|
5
|
+
// consumes — onto that queue. The plugin EventCollector (`AdminEventCollectorEntryPoint`)
|
|
6
|
+
// then drives the full fan-out: read-model projections, aggregate command topics,
|
|
7
|
+
// and the cross-plugin SNS EventTopic. See
|
|
8
|
+
// docs/plans/aws-postgres-change-feed-bridge.md.
|
|
9
|
+
//
|
|
10
|
+
// The transform reuses the canonical DynamoDB shape producers
|
|
11
|
+
// (`derivePartitionKey` + `buildJsonEvent'`) so the emitted body is byte-identical
|
|
12
|
+
// to the DynamoDB-stream path — the SQS handler cannot tell the difference.
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Transform one feed event into the EventCollector JSON body. Rebuilds the same
|
|
16
|
+
* unmarshalled-item dict the DCB DynamoDB-stream decoder would see (id from the
|
|
17
|
+
* partition tag, position, event type, data, decomposed meta) and runs it through
|
|
18
|
+
* `buildJsonEvent'` — the exact decoder the SQS handler expects. Returns `None`
|
|
19
|
+
* for a malformed event (mirrors `buildJsonEvent'`).
|
|
20
|
+
*/
|
|
21
|
+
let toEventCollectorJson = (
|
|
22
|
+
event: ReventlessCore.DcbEventLog_Adapter.rawSequencedEvent,
|
|
23
|
+
~partitionTag: option<Reventless.DcbTag.derivedPartitionTag>=?,
|
|
24
|
+
): option<JSON.t> => {
|
|
25
|
+
let item = Dict.make()
|
|
26
|
+
item->Dict.set(
|
|
27
|
+
"id",
|
|
28
|
+
DcbEventLogStorage_DynamoDb_Runtime.derivePartitionKey(~partitionTag?, event.tags)
|
|
29
|
+
->JSON.Encode.string,
|
|
30
|
+
)
|
|
31
|
+
item->Dict.set("position", event.position->JSON.Encode.string)
|
|
32
|
+
item->Dict.set("event", event.eventType->JSON.Encode.string)
|
|
33
|
+
item->Dict.set("data", event.data)
|
|
34
|
+
ReventlessCore.Message.decomposeMeta(event.meta)->Array.forEach(((key, value)) =>
|
|
35
|
+
item->Dict.set(key, value)
|
|
36
|
+
)
|
|
37
|
+
Util_DynamoDbStream_Runtime.buildJsonEvent'(item)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Drain a Postgres DCB log from its checkpoint and relay its events to the
|
|
42
|
+
* EventCollector via the injected `sendBatch`. `sendBatch` is injected (rather than
|
|
43
|
+
* hardcoding SQS) so the drain/transform is unit-testable; the relay entry point
|
|
44
|
+
* wires it to the actual `SendMessage`. Returns the number of events processed.
|
|
45
|
+
*
|
|
46
|
+
* At-least-once by construction: `PgChangeFeed.drain` replays the last page on a
|
|
47
|
+
* crash before checkpoint, and EventCollector projections are idempotent
|
|
48
|
+
* (event-sourced), so re-delivery is safe.
|
|
49
|
+
*/
|
|
50
|
+
let relay = async (
|
|
51
|
+
~config: PgConnection.connectionConfig,
|
|
52
|
+
~logName: string,
|
|
53
|
+
~subscriber: string,
|
|
54
|
+
~partitionTag: option<Reventless.DcbTag.derivedPartitionTag>=?,
|
|
55
|
+
~sendBatch: array<JSON.t> => promise<unit>,
|
|
56
|
+
): int => {
|
|
57
|
+
let pool = PgRuntime.poolFor(config)
|
|
58
|
+
await ReventlessPostgres.PgChangeFeed.drain(pool, ~logName, ~subscriber, ~handle=async events => {
|
|
59
|
+
let jsons = events->Array.filterMap(event => toEventCollectorJson(event, ~partitionTag?))
|
|
60
|
+
if jsons->Array.length > 0 {
|
|
61
|
+
await sendBatch(jsons)
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
4
|
+
import * as Message$ReventlessCore from "@reventlessdev/reventless-core/src/Message.res.mjs";
|
|
5
|
+
import * as PgRuntime$ReventlessAws from "./PgRuntime.res.mjs";
|
|
6
|
+
import * as PgChangeFeed$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/PgChangeFeed.res.mjs";
|
|
7
|
+
import * as Util_DynamoDbStream_Runtime$ReventlessAws from "../../util/Util_DynamoDbStream_Runtime.res.mjs";
|
|
8
|
+
import * as DcbEventLogStorage_DynamoDb_Runtime$ReventlessAws from "../DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res.mjs";
|
|
9
|
+
|
|
10
|
+
function toEventCollectorJson(event, partitionTag) {
|
|
11
|
+
let item = {};
|
|
12
|
+
item["id"] = DcbEventLogStorage_DynamoDb_Runtime$ReventlessAws.derivePartitionKey(partitionTag, event.tags);
|
|
13
|
+
item["position"] = event.position;
|
|
14
|
+
item["event"] = event.eventType;
|
|
15
|
+
item["data"] = event.data;
|
|
16
|
+
Message$ReventlessCore.decomposeMeta(event.meta).forEach(param => {
|
|
17
|
+
item[param[0]] = param[1];
|
|
18
|
+
});
|
|
19
|
+
return Util_DynamoDbStream_Runtime$ReventlessAws.buildJsonEvent$p(item);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function relay(config, logName, subscriber, partitionTag, sendBatch) {
|
|
23
|
+
let pool = PgRuntime$ReventlessAws.poolFor(config);
|
|
24
|
+
return await PgChangeFeed$ReventlessPostgres.drain(pool, logName, subscriber, undefined, async events => {
|
|
25
|
+
let jsons = Stdlib_Array.filterMap(events, event => toEventCollectorJson(event, partitionTag));
|
|
26
|
+
if (jsons.length !== 0) {
|
|
27
|
+
return await sendBatch(jsons);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
toEventCollectorJson,
|
|
34
|
+
relay,
|
|
35
|
+
}
|
|
36
|
+
/* Message-ReventlessCore Not a pure module */
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/** Deploy-time component that provisions a managed Postgres instance (RDS) and
|
|
2
|
+
resolves the connection details the `reventless-postgres` runtime needs inside
|
|
3
|
+
a Lambda.
|
|
4
|
+
|
|
5
|
+
One `PgConnection` hosts **all three** storage surfaces (classic `event_log`,
|
|
6
|
+
DCB `dcb_event`, and the QueryDb `qdb_*` tables) in a single database — the
|
|
7
|
+
per-surface adapters take a reference to it, they do not each provision a DB.
|
|
8
|
+
|
|
9
|
+
Networking is supplied by the platform (an existing VPC + private subnets); a
|
|
10
|
+
`PgConnection` does not provision a VPC. It creates:
|
|
11
|
+
- a **shared security group** with a self-referencing `5432` ingress rule, so
|
|
12
|
+
every Lambda that attaches this same SG (see C1 / `securityGroupId`) can
|
|
13
|
+
reach the DB without a separate client SG;
|
|
14
|
+
- a **DB subnet group** over the given private subnets;
|
|
15
|
+
- the **RDS instance** with `manageMasterUserPassword` — RDS mints and rotates
|
|
16
|
+
the master credentials in Secrets Manager, so no plaintext password ever
|
|
17
|
+
lands in Pulumi state. The resulting secret ARN surfaces on
|
|
18
|
+
`connectionConfig.secretArn`; the runtime resolves it at cold start.
|
|
19
|
+
|
|
20
|
+
Aurora / Aurora Serverless v2 is a planned second engine behind the same
|
|
21
|
+
`connectionConfig` output shape (tracked in the AWS-Postgres plan). */
|
|
22
|
+
|
|
23
|
+
/** Resolved at deploy time, serialized into the handler Lambda env, and consumed
|
|
24
|
+
at cold start to build a `PgDriver` pool. `secretArn` points at the
|
|
25
|
+
RDS-managed `{username, password}` secret; `host`/`port`/`database` come from
|
|
26
|
+
the instance itself. */
|
|
27
|
+
@schema
|
|
28
|
+
type connectionConfig = {
|
|
29
|
+
host: string,
|
|
30
|
+
port: int,
|
|
31
|
+
database: string,
|
|
32
|
+
/** RDS master username — set at deploy time, not secret. The pool's `user`;
|
|
33
|
+
the Secrets Manager secret supplies only the matching password. */
|
|
34
|
+
username: string,
|
|
35
|
+
secretArn: string,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type t = {
|
|
39
|
+
/** Deploy-time resources (currently the RDS instance) for dependency wiring —
|
|
40
|
+
e.g. the A3 migration Lambda and the B-phase adapters order after these. */
|
|
41
|
+
resources: array<ReventlessInfra.Adapter.resource>,
|
|
42
|
+
connectionConfig: Pulumi.Output.t<connectionConfig>,
|
|
43
|
+
/** Attach to every Lambda that talks to Postgres: the SG's self-referencing
|
|
44
|
+
rule is what lets those Lambdas reach the DB on 5432. */
|
|
45
|
+
securityGroupId: Pulumi.Output.t<string>,
|
|
46
|
+
/** The DB's private subnets, echoed back for the Lambda `vpcConfig` so
|
|
47
|
+
handlers land in the same subnets as the database. */
|
|
48
|
+
subnetIds: array<Pulumi.Input.t<string>>,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Postgres wire port. */
|
|
52
|
+
let port = 5432
|
|
53
|
+
|
|
54
|
+
let make = (
|
|
55
|
+
~name,
|
|
56
|
+
~vpcId: Pulumi.Input.t<string>,
|
|
57
|
+
~subnetIds: array<Pulumi.Input.t<string>>,
|
|
58
|
+
~databaseName="reventless",
|
|
59
|
+
~username="reventless_admin",
|
|
60
|
+
~engineVersion="16",
|
|
61
|
+
~instanceClass="db.t3.micro",
|
|
62
|
+
~allocatedStorage=20,
|
|
63
|
+
~multiAz=false,
|
|
64
|
+
~storageEncrypted=true,
|
|
65
|
+
~backupRetentionPeriod=7,
|
|
66
|
+
~deletionProtection=true,
|
|
67
|
+
~skipFinalSnapshot=false,
|
|
68
|
+
~opts: option<Pulumi.ComponentResource.options>=?,
|
|
69
|
+
): t => {
|
|
70
|
+
let opts =
|
|
71
|
+
opts->Option.map(ReventlessCore.Util.Pulumi.ComponentResourceOptions.toCustomResourceOptions)
|
|
72
|
+
|
|
73
|
+
let tags =
|
|
74
|
+
[
|
|
75
|
+
("Name", name),
|
|
76
|
+
("Environment", Pulumi.Pulumi.getStackName()),
|
|
77
|
+
("reventless:role", "postgres-connection"),
|
|
78
|
+
]->Dict.fromArray
|
|
79
|
+
|
|
80
|
+
// Shared DB-access security group. Self-referencing 5432 ingress lets member
|
|
81
|
+
// Lambdas reach the DB; open egress so both the DB and those Lambdas can make
|
|
82
|
+
// outbound calls (e.g. Secrets Manager, other AWS APIs).
|
|
83
|
+
let sg = PulumiAws.EC2.SecurityGroup.make(
|
|
84
|
+
~name=`${name}-pg-sg`,
|
|
85
|
+
~args={
|
|
86
|
+
name: `${name}-pg-sg`,
|
|
87
|
+
vpcId,
|
|
88
|
+
ingress: [
|
|
89
|
+
{
|
|
90
|
+
fromPort: port,
|
|
91
|
+
protocol: "tcp",
|
|
92
|
+
toPort: port,
|
|
93
|
+
cidrBlocks: [],
|
|
94
|
+
self: true,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
egress: [PulumiAws.EC2.SecurityGroup.Egress.allowAll],
|
|
98
|
+
tags,
|
|
99
|
+
},
|
|
100
|
+
~opts?,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
let subnetGroup = PulumiAws.Rds.SubnetGroup.make(
|
|
104
|
+
~name=`${name}-pg-subnets`,
|
|
105
|
+
~args={
|
|
106
|
+
name: `${name}-pg-subnets`->Pulumi.Input.make,
|
|
107
|
+
subnetIds: subnetIds->Pulumi.Input.make,
|
|
108
|
+
tags: tags->Pulumi.Input.make,
|
|
109
|
+
},
|
|
110
|
+
~opts?,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
let instance = PulumiAws.Rds.Instance.make(
|
|
114
|
+
~name=`${name}-pg`,
|
|
115
|
+
~args={
|
|
116
|
+
engine: "postgres"->Pulumi.Input.make,
|
|
117
|
+
engineVersion: engineVersion->Pulumi.Input.make,
|
|
118
|
+
instanceClass: instanceClass->Pulumi.Input.make,
|
|
119
|
+
allocatedStorage: allocatedStorage->Pulumi.Input.make,
|
|
120
|
+
dbName: databaseName->Pulumi.Input.make,
|
|
121
|
+
username: username->Pulumi.Input.make,
|
|
122
|
+
manageMasterUserPassword: true->Pulumi.Input.make,
|
|
123
|
+
dbSubnetGroupName: subnetGroup.name->Pulumi.Output.asInput,
|
|
124
|
+
vpcSecurityGroupIds: [sg.id->Pulumi.Output.asInput]->Pulumi.Input.make,
|
|
125
|
+
port: port->Pulumi.Input.make,
|
|
126
|
+
multiAz: multiAz->Pulumi.Input.make,
|
|
127
|
+
publiclyAccessible: false->Pulumi.Input.make,
|
|
128
|
+
storageEncrypted: storageEncrypted->Pulumi.Input.make,
|
|
129
|
+
backupRetentionPeriod: backupRetentionPeriod->Pulumi.Input.make,
|
|
130
|
+
deletionProtection: deletionProtection->Pulumi.Input.make,
|
|
131
|
+
skipFinalSnapshot: skipFinalSnapshot->Pulumi.Input.make,
|
|
132
|
+
tags: tags->Pulumi.Input.make,
|
|
133
|
+
},
|
|
134
|
+
~opts?,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
let connectionConfig =
|
|
138
|
+
(instance.address, instance.masterUserSecrets)
|
|
139
|
+
->Pulumi.Output.all2
|
|
140
|
+
->Pulumi.Output.apply(((host, secrets)) => {
|
|
141
|
+
host,
|
|
142
|
+
port,
|
|
143
|
+
database: databaseName,
|
|
144
|
+
username,
|
|
145
|
+
secretArn: switch secrets->Array.get(0) {
|
|
146
|
+
| Some(secret) => secret.secretArn
|
|
147
|
+
| None =>
|
|
148
|
+
JsError.throwWithMessage(
|
|
149
|
+
"RDS instance exposes no master user secret — manageMasterUserPassword must be enabled",
|
|
150
|
+
)
|
|
151
|
+
},
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
{
|
|
155
|
+
resources: [
|
|
156
|
+
ReventlessInfra.Adapter.make(
|
|
157
|
+
~name=name->Pulumi.Output.make,
|
|
158
|
+
~id=instance.id,
|
|
159
|
+
~urn=instance.arn,
|
|
160
|
+
~service="aws:rds"->Pulumi.Output.make,
|
|
161
|
+
~role="postgres"->Pulumi.Output.make,
|
|
162
|
+
~resourceType="aws:rds:Instance"->Pulumi.Output.make,
|
|
163
|
+
),
|
|
164
|
+
],
|
|
165
|
+
connectionConfig,
|
|
166
|
+
securityGroupId: sg.id,
|
|
167
|
+
subnetIds,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Aws from "@pulumi/aws";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Pulumi from "@pulumi/pulumi";
|
|
7
|
+
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
8
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
9
|
+
import * as Adapter$ReventlessInfra from "@reventlessdev/reventless-infra/src/adapter/Adapter.res.mjs";
|
|
10
|
+
import * as Util_Pulumi$ReventlessCore from "@reventlessdev/reventless-core/src/util/Util_Pulumi.res.mjs";
|
|
11
|
+
import * as EC2_SecurityGroup$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/EC2/EC2_SecurityGroup.res.mjs";
|
|
12
|
+
|
|
13
|
+
let connectionConfigSchema = S.schema(s => ({
|
|
14
|
+
host: s.m(S.string),
|
|
15
|
+
port: s.m(S.int),
|
|
16
|
+
database: s.m(S.string),
|
|
17
|
+
username: s.m(S.string),
|
|
18
|
+
secretArn: s.m(S.string)
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
function make(name, vpcId, subnetIds, databaseNameOpt, usernameOpt, engineVersionOpt, instanceClassOpt, allocatedStorageOpt, multiAzOpt, storageEncryptedOpt, backupRetentionPeriodOpt, deletionProtectionOpt, skipFinalSnapshotOpt, opts) {
|
|
22
|
+
let databaseName = databaseNameOpt !== undefined ? databaseNameOpt : "reventless";
|
|
23
|
+
let username = usernameOpt !== undefined ? usernameOpt : "reventless_admin";
|
|
24
|
+
let engineVersion = engineVersionOpt !== undefined ? engineVersionOpt : "16";
|
|
25
|
+
let instanceClass = instanceClassOpt !== undefined ? instanceClassOpt : "db.t3.micro";
|
|
26
|
+
let allocatedStorage = allocatedStorageOpt !== undefined ? allocatedStorageOpt : 20;
|
|
27
|
+
let multiAz = multiAzOpt !== undefined ? multiAzOpt : false;
|
|
28
|
+
let storageEncrypted = storageEncryptedOpt !== undefined ? storageEncryptedOpt : true;
|
|
29
|
+
let backupRetentionPeriod = backupRetentionPeriodOpt !== undefined ? backupRetentionPeriodOpt : 7;
|
|
30
|
+
let deletionProtection = deletionProtectionOpt !== undefined ? deletionProtectionOpt : true;
|
|
31
|
+
let skipFinalSnapshot = skipFinalSnapshotOpt !== undefined ? skipFinalSnapshotOpt : false;
|
|
32
|
+
let opts$1 = Stdlib_Option.map(opts, Util_Pulumi$ReventlessCore.ComponentResourceOptions.toCustomResourceOptions);
|
|
33
|
+
let tags = Object.fromEntries([
|
|
34
|
+
[
|
|
35
|
+
"Name",
|
|
36
|
+
name
|
|
37
|
+
],
|
|
38
|
+
[
|
|
39
|
+
"Environment",
|
|
40
|
+
Pulumi.getStack()
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
"reventless:role",
|
|
44
|
+
"postgres-connection"
|
|
45
|
+
]
|
|
46
|
+
]);
|
|
47
|
+
let sg = EC2_SecurityGroup$PulumiAws.make(name + `-pg-sg`, {
|
|
48
|
+
name: name + `-pg-sg`,
|
|
49
|
+
vpcId: vpcId,
|
|
50
|
+
ingress: [{
|
|
51
|
+
fromPort: 5432,
|
|
52
|
+
protocol: "tcp",
|
|
53
|
+
toPort: 5432,
|
|
54
|
+
cidrBlocks: [],
|
|
55
|
+
self: true
|
|
56
|
+
}],
|
|
57
|
+
egress: [EC2_SecurityGroup$PulumiAws.Egress.allowAll],
|
|
58
|
+
tags: tags
|
|
59
|
+
}, opts$1);
|
|
60
|
+
let subnetGroup = new (Aws.rds.SubnetGroup)(name + `-pg-subnets`, {
|
|
61
|
+
name: name + `-pg-subnets`,
|
|
62
|
+
subnetIds: subnetIds,
|
|
63
|
+
tags: tags
|
|
64
|
+
}, opts$1 !== undefined ? Primitive_option.valFromOption(opts$1) : undefined);
|
|
65
|
+
let instance = new (Aws.rds.Instance)(name + `-pg`, {
|
|
66
|
+
allocatedStorage: allocatedStorage,
|
|
67
|
+
engine: "postgres",
|
|
68
|
+
engineVersion: engineVersion,
|
|
69
|
+
instanceClass: instanceClass,
|
|
70
|
+
dbName: databaseName,
|
|
71
|
+
username: username,
|
|
72
|
+
manageMasterUserPassword: true,
|
|
73
|
+
dbSubnetGroupName: subnetGroup.name,
|
|
74
|
+
vpcSecurityGroupIds: [sg.id],
|
|
75
|
+
port: 5432,
|
|
76
|
+
multiAz: multiAz,
|
|
77
|
+
publiclyAccessible: false,
|
|
78
|
+
storageEncrypted: storageEncrypted,
|
|
79
|
+
backupRetentionPeriod: backupRetentionPeriod,
|
|
80
|
+
deletionProtection: deletionProtection,
|
|
81
|
+
skipFinalSnapshot: skipFinalSnapshot,
|
|
82
|
+
tags: tags
|
|
83
|
+
}, opts$1 !== undefined ? Primitive_option.valFromOption(opts$1) : undefined);
|
|
84
|
+
let connectionConfig = Pulumi.all([
|
|
85
|
+
instance.address,
|
|
86
|
+
instance.masterUserSecrets
|
|
87
|
+
]).apply(param => {
|
|
88
|
+
let secret = param[1][0];
|
|
89
|
+
return {
|
|
90
|
+
host: param[0],
|
|
91
|
+
port: 5432,
|
|
92
|
+
database: databaseName,
|
|
93
|
+
username: username,
|
|
94
|
+
secretArn: secret !== undefined ? secret.secretArn : Stdlib_JsError.throwWithMessage("RDS instance exposes no master user secret — manageMasterUserPassword must be enabled")
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
return {
|
|
98
|
+
resources: [Adapter$ReventlessInfra.make(Pulumi.output(name), instance.id, instance.arn, Pulumi.output("aws:rds"), undefined, Pulumi.output("postgres"), undefined, Pulumi.output("aws:rds:Instance"), undefined, undefined)],
|
|
99
|
+
connectionConfig: connectionConfig,
|
|
100
|
+
securityGroupId: sg.id,
|
|
101
|
+
subnetIds: subnetIds
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let port = 5432;
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
connectionConfigSchema,
|
|
109
|
+
port,
|
|
110
|
+
make,
|
|
111
|
+
}
|
|
112
|
+
/* connectionConfigSchema Not a pure module */
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** Cold-start Postgres connectivity for deployed Lambdas.
|
|
2
|
+
|
|
3
|
+
Given a resolved `PgConnection.connectionConfig` (injected into the handler env
|
|
4
|
+
at deploy time), this resolves the RDS-managed master password from Secrets
|
|
5
|
+
Manager and builds **one pg pool per container**, memoized by secret ARN.
|
|
6
|
+
|
|
7
|
+
Rotation-safe by construction: the pool is created with a *password provider*,
|
|
8
|
+
which pg invokes each time it opens a physical connection — so a rotated secret
|
|
9
|
+
is picked up on the next new connection. The fetched secret is cached per ARN
|
|
10
|
+
(as a promise) to avoid a Secrets Manager round trip on every connection; a
|
|
11
|
+
password rotation surfaces as auth failures that recycle the container, after
|
|
12
|
+
which the next cold start re-fetches. */
|
|
13
|
+
|
|
14
|
+
/** RDS-managed master secret payload (`{username, password}` JSON). We only need
|
|
15
|
+
the password here — the username is carried on `connectionConfig` (deploy-time
|
|
16
|
+
known) so the pool can be constructed without first awaiting the secret. */
|
|
17
|
+
let passwordFromSecret = async (secretArn: string): string => {
|
|
18
|
+
let out =
|
|
19
|
+
await {AwsSdk.SecretsManager.GetSecretValueCommand.secretId: secretArn}
|
|
20
|
+
->AwsSdk.SecretsManager.GetSecretValueCommand.make
|
|
21
|
+
->AwsSdk.SecretsManager.GetSecretValueCommand.send
|
|
22
|
+
switch out.secretString {
|
|
23
|
+
| Some(str) =>
|
|
24
|
+
switch str->JSON.parseOrThrow->JSON.Decode.object {
|
|
25
|
+
| Some(obj) =>
|
|
26
|
+
switch obj->Dict.get("password")->Option.flatMap(JSON.Decode.string) {
|
|
27
|
+
| Some(password) => password
|
|
28
|
+
| None => JsError.throwWithMessage("Secrets Manager secret has no `password` field")
|
|
29
|
+
}
|
|
30
|
+
| None => JsError.throwWithMessage("Secrets Manager secret is not a JSON object")
|
|
31
|
+
}
|
|
32
|
+
| None =>
|
|
33
|
+
JsError.throwWithMessage(`Secrets Manager secret ${secretArn} has no SecretString`)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Cache the in-flight/settled password fetch per ARN so pg's per-connection
|
|
38
|
+
// provider doesn't hit Secrets Manager on every physical connection.
|
|
39
|
+
let passwordCache: dict<promise<string>> = Dict.make()
|
|
40
|
+
|
|
41
|
+
let cachedPassword = (secretArn: string): promise<string> =>
|
|
42
|
+
switch passwordCache->Dict.get(secretArn) {
|
|
43
|
+
| Some(p) => p
|
|
44
|
+
| None =>
|
|
45
|
+
let p = passwordFromSecret(secretArn)
|
|
46
|
+
passwordCache->Dict.set(secretArn, p)
|
|
47
|
+
p
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// One pool per secret ARN for the life of the container.
|
|
51
|
+
let poolCache: dict<ReventlessPostgres.PgDriver.pool> = Dict.make()
|
|
52
|
+
|
|
53
|
+
/** The container-lifetime pool for the given connection config, built on first
|
|
54
|
+
use. pg pools connect lazily, so this is cheap until the first query. */
|
|
55
|
+
let poolFor = (config: PgConnection.connectionConfig): ReventlessPostgres.PgDriver.pool =>
|
|
56
|
+
switch poolCache->Dict.get(config.secretArn) {
|
|
57
|
+
| Some(pool) => pool
|
|
58
|
+
| None =>
|
|
59
|
+
let pool = ReventlessPostgres.PgDriver.makePool({
|
|
60
|
+
host: config.host,
|
|
61
|
+
port: config.port,
|
|
62
|
+
database: config.database,
|
|
63
|
+
user: config.username,
|
|
64
|
+
password: () => cachedPassword(config.secretArn),
|
|
65
|
+
// RDS PG15+ defaults to rds.force_ssl=1. Encrypt without CA verification
|
|
66
|
+
// for v1; pin the RDS CA bundle as a hardening follow-up.
|
|
67
|
+
ssl: {rejectUnauthorized: false},
|
|
68
|
+
})
|
|
69
|
+
poolCache->Dict.set(config.secretArn, pool)
|
|
70
|
+
pool
|
|
71
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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 Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
6
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
7
|
+
import * as SecretsManager$AwsSdk from "@reventlessdev/rescript-aws-sdk/src/SecretsManager.res.mjs";
|
|
8
|
+
import * as PgDriver$ReventlessPostgres from "@reventlessdev/reventless-postgres/src/PgDriver.res.mjs";
|
|
9
|
+
import * as ClientSecretsManager from "@aws-sdk/client-secrets-manager";
|
|
10
|
+
|
|
11
|
+
async function passwordFromSecret(secretArn) {
|
|
12
|
+
let out = await SecretsManager$AwsSdk.GetSecretValueCommand.send(new ClientSecretsManager.GetSecretValueCommand({
|
|
13
|
+
SecretId: secretArn
|
|
14
|
+
}));
|
|
15
|
+
let str = out.SecretString;
|
|
16
|
+
if (str === undefined) {
|
|
17
|
+
return Stdlib_JsError.throwWithMessage(`Secrets Manager secret ` + secretArn + ` has no SecretString`);
|
|
18
|
+
}
|
|
19
|
+
let obj = Stdlib_JSON.Decode.object(JSON.parse(str));
|
|
20
|
+
if (obj === undefined) {
|
|
21
|
+
return Stdlib_JsError.throwWithMessage("Secrets Manager secret is not a JSON object");
|
|
22
|
+
}
|
|
23
|
+
let password = Stdlib_Option.flatMap(obj["password"], Stdlib_JSON.Decode.string);
|
|
24
|
+
if (password !== undefined) {
|
|
25
|
+
return password;
|
|
26
|
+
} else {
|
|
27
|
+
return Stdlib_JsError.throwWithMessage("Secrets Manager secret has no `password` field");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let passwordCache = {};
|
|
32
|
+
|
|
33
|
+
function cachedPassword(secretArn) {
|
|
34
|
+
let p = passwordCache[secretArn];
|
|
35
|
+
if (p !== undefined) {
|
|
36
|
+
return p;
|
|
37
|
+
}
|
|
38
|
+
let p$1 = passwordFromSecret(secretArn);
|
|
39
|
+
passwordCache[secretArn] = p$1;
|
|
40
|
+
return p$1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let poolCache = {};
|
|
44
|
+
|
|
45
|
+
function poolFor(config) {
|
|
46
|
+
let pool = poolCache[config.secretArn];
|
|
47
|
+
if (pool !== undefined) {
|
|
48
|
+
return Primitive_option.valFromOption(pool);
|
|
49
|
+
}
|
|
50
|
+
let pool$1 = PgDriver$ReventlessPostgres.makePool({
|
|
51
|
+
host: config.host,
|
|
52
|
+
port: config.port,
|
|
53
|
+
database: config.database,
|
|
54
|
+
user: config.username,
|
|
55
|
+
password: () => cachedPassword(config.secretArn),
|
|
56
|
+
ssl: {
|
|
57
|
+
rejectUnauthorized: false
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
poolCache[config.secretArn] = pool$1;
|
|
61
|
+
return pool$1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export {
|
|
65
|
+
passwordFromSecret,
|
|
66
|
+
passwordCache,
|
|
67
|
+
cachedPassword,
|
|
68
|
+
poolCache,
|
|
69
|
+
poolFor,
|
|
70
|
+
}
|
|
71
|
+
/* SecretsManager-AwsSdk Not a pure module */
|
|
@@ -12,6 +12,7 @@ import { Make as commandTopicCallbackMake } from "@reventlessdev/reventless-core
|
|
|
12
12
|
import { makeGenerateCommand } from "@reventlessdev/reventless-core/src/components/CommandGenerator/CommandGenerator_Callback.res.mjs";
|
|
13
13
|
import { commandOutcomeToJson, runInlineAndCollect } from "@reventlessdev/reventless-core/src/components/CommandTopic/CommandTopic_Helpers.res.mjs";
|
|
14
14
|
import { append, replay, replayStream, appendStream } from "@reventlessdev/reventless-aws/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res.mjs";
|
|
15
|
+
import { opsFor as pgEventLogOpsFor } from "@reventlessdev/reventless-aws/src/adapter/EventLog/EventLogStorage_Postgres_Runtime.res.mjs";
|
|
15
16
|
import { handleQueueEvent, publishJsons as sqsPublishJsons } from "@reventlessdev/reventless-aws/src/adapter/CommandTopic/CommandTopicChannel_SQS_Runtime.res.mjs";
|
|
16
17
|
import { DynamoDBClient, ScanCommand } from "@aws-sdk/client-dynamodb";
|
|
17
18
|
import { unmarshall } from "@aws-sdk/util-dynamodb";
|
|
@@ -118,15 +119,32 @@ async function checkPluginStatus(event) {
|
|
|
118
119
|
// Route 2 (SQS event source): the in-process command handler (used both as the
|
|
119
120
|
// inline dispatch target and as the SQS message handler) plus the resolved
|
|
120
121
|
// queue ref for the fire-and-forget async path.
|
|
121
|
-
|
|
122
|
+
// `pgConnection`, when present, is the resolved PgConnection.connectionConfig
|
|
123
|
+
// ({host,port,database,username,secretArn}) serialized into HANDLER_CONFIG by the
|
|
124
|
+
// runtime builder for a Postgres-backed aggregate. Its presence selects the
|
|
125
|
+
// Postgres EventLog runtime; absence keeps the DynamoDB path byte-identical.
|
|
126
|
+
// `eventLogTableName` doubles as the Postgres `event_log.log_name` discriminator
|
|
127
|
+
// (all aggregates share one Postgres table, unlike DynamoDB's table-per-aggregate).
|
|
128
|
+
function buildAggregateParts(specModule, behaviorModule, eventLogTableName, queueUrl, pgConnection) {
|
|
122
129
|
const patchedSpec = patchSpecId(specModule);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
let rawStorageOps;
|
|
131
|
+
if (pgConnection) {
|
|
132
|
+
const pgOps = pgEventLogOpsFor(pgConnection, eventLogTableName);
|
|
133
|
+
rawStorageOps = {
|
|
134
|
+
append: pgOps.append,
|
|
135
|
+
replay: pgOps.replay,
|
|
136
|
+
replayStream: pgOps.replayStream,
|
|
137
|
+
appendStream: pgOps.appendStream,
|
|
138
|
+
};
|
|
139
|
+
} else {
|
|
140
|
+
const resolvedTable = { name: eventLogTableName };
|
|
141
|
+
rawStorageOps = {
|
|
142
|
+
append: append(resolvedTable),
|
|
143
|
+
replay: replay(resolvedTable),
|
|
144
|
+
replayStream: replayStream(resolvedTable),
|
|
145
|
+
appendStream: appendStream(resolvedTable),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
130
148
|
const eventLogOps = eventLogOperationsMake(patchedSpec)({
|
|
131
149
|
Spec: patchedSpec,
|
|
132
150
|
EventTopic: { Spec: patchedSpec },
|
|
@@ -246,7 +264,7 @@ async function buildAllHandlers() {
|
|
|
246
264
|
await Promise.all(config.handlers.map(async h => {
|
|
247
265
|
const specModule = await dynamicImport(h.specModule);
|
|
248
266
|
const behaviorModule = await dynamicImport(h.behaviorModule);
|
|
249
|
-
const parts = buildAggregateParts(specModule, behaviorModule, h.eventLogTable, h.queueUrl);
|
|
267
|
+
const parts = buildAggregateParts(specModule, behaviorModule, h.eventLogTable, h.queueUrl, h.pgConnection);
|
|
250
268
|
cmdTopicHandlers[h.queueArn] = parts.sqsHandler;
|
|
251
269
|
cmdGenHandlers[specModule.name] = buildCommandGeneratorHandler(parts, DISPATCH_MODE);
|
|
252
270
|
}));
|
|
@@ -173,7 +173,7 @@ function finish() {
|
|
|
173
173
|
cmdTopicEnvVars["HANDLER_CONFIG"] = cmdTopicHandlerConfigOutput;
|
|
174
174
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/AggregateEntryPoint.mjs", packageDirs, undefined);
|
|
175
175
|
let cmdTopicName = baseName + "CmdHandler";
|
|
176
|
-
let cmdTopicRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdTopicName, match.code, match.sourceCodeHash, cmdTopicEnvVars, Math.max(spec.commandTopicMemorySize, 1024), Math.max(spec.commandTopicTimeout, 30), undefined, undefined, undefined, undefined, aggregateOpts);
|
|
176
|
+
let cmdTopicRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdTopicName, match.code, match.sourceCodeHash, cmdTopicEnvVars, Math.max(spec.commandTopicMemorySize, 1024), Math.max(spec.commandTopicTimeout, 30), undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
177
177
|
spec.commandTopicConnects.forEach(connect => connect(cmdTopicRuntime));
|
|
178
178
|
if (spec.commandGeneratorConnects.length !== 0) {
|
|
179
179
|
let cmdGenHandlerConfigOutput = Pulumi.all([
|
|
@@ -185,7 +185,7 @@ function finish() {
|
|
|
185
185
|
cmdGenEnvVars["HANDLER_CONFIG"] = cmdGenHandlerConfigOutput;
|
|
186
186
|
let match$1 = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/AggregateEntryPoint.mjs", packageDirs, undefined);
|
|
187
187
|
let cmdGenName = baseName + "CmdGen";
|
|
188
|
-
let cmdGenRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdGenName, match$1.code, match$1.sourceCodeHash, cmdGenEnvVars, Math.max(spec.commandGeneratorMemorySize, 1024), Math.max(spec.commandGeneratorTimeout, 30), undefined, undefined, undefined, undefined, aggregateOpts);
|
|
188
|
+
let cmdGenRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdGenName, match$1.code, match$1.sourceCodeHash, cmdGenEnvVars, Math.max(spec.commandGeneratorMemorySize, 1024), Math.max(spec.commandGeneratorTimeout, 30), undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
189
189
|
spec.commandGeneratorConnects.forEach(connect => connect(cmdGenRuntime));
|
|
190
190
|
}
|
|
191
191
|
let match$2 = spec.eventCollectorChannelSpec;
|
|
@@ -208,7 +208,7 @@ function finish() {
|
|
|
208
208
|
evtMapperPackageDirs[mappingsPkg] = Util_Bundle$ReventlessAws.resolvePackageRoot(mappingsPkg);
|
|
209
209
|
let match$4 = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/EventMapperEntryPoint.mjs", evtMapperPackageDirs, undefined);
|
|
210
210
|
let evtMapperName = baseName + "EventMapper";
|
|
211
|
-
let evtMapperRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(evtMapperName, match$4.code, match$4.sourceCodeHash, evtMapperEnvVars, Math.max(spec.eventCollectorMemorySize, 2048), Math.max(spec.eventCollectorTimeout, 180), undefined, undefined, undefined, undefined, aggregateOpts);
|
|
211
|
+
let evtMapperRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(evtMapperName, match$4.code, match$4.sourceCodeHash, evtMapperEnvVars, Math.max(spec.eventCollectorMemorySize, 2048), Math.max(spec.eventCollectorTimeout, 180), undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
212
212
|
EventCollectorChannel_DynamoDbStream$ReventlessAws.connect(evtMapperName, [match$2], evtMapperRuntime, aggregateOpts);
|
|
213
213
|
});
|
|
214
214
|
}
|
|
@@ -173,7 +173,7 @@ function finish() {
|
|
|
173
173
|
cmdTopicEnvVars["HANDLER_CONFIG"] = cmdTopicHandlerConfigOutput;
|
|
174
174
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/AggregateEntryPoint.mjs", packageDirs, undefined);
|
|
175
175
|
let cmdTopicName = baseName + "CmdHandler";
|
|
176
|
-
let cmdTopicRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdTopicName, match.code, match.sourceCodeHash, cmdTopicEnvVars, Math.max(spec.commandTopicMemorySize, 1024), Math.max(spec.commandTopicTimeout, 30), undefined, undefined, undefined, undefined, aggregateOpts);
|
|
176
|
+
let cmdTopicRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdTopicName, match.code, match.sourceCodeHash, cmdTopicEnvVars, Math.max(spec.commandTopicMemorySize, 1024), Math.max(spec.commandTopicTimeout, 30), undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
177
177
|
spec.commandTopicConnects.forEach(connect => connect(cmdTopicRuntime));
|
|
178
178
|
if (spec.commandGeneratorConnects.length !== 0) {
|
|
179
179
|
let cmdGenHandlerConfigOutput = Pulumi.all([
|
|
@@ -186,7 +186,7 @@ function finish() {
|
|
|
186
186
|
cmdGenEnvVars["DISPATCH_MODE"] = "async";
|
|
187
187
|
let match$1 = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/AggregateEntryPoint.mjs", packageDirs, undefined);
|
|
188
188
|
let cmdGenName = baseName + "CmdGen";
|
|
189
|
-
let cmdGenRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdGenName, match$1.code, match$1.sourceCodeHash, cmdGenEnvVars, Math.max(spec.commandGeneratorMemorySize, 1024), Math.max(spec.commandGeneratorTimeout, 30), undefined, undefined, undefined, undefined, aggregateOpts);
|
|
189
|
+
let cmdGenRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(cmdGenName, match$1.code, match$1.sourceCodeHash, cmdGenEnvVars, Math.max(spec.commandGeneratorMemorySize, 1024), Math.max(spec.commandGeneratorTimeout, 30), undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
190
190
|
spec.commandGeneratorConnects.forEach(connect => connect(cmdGenRuntime));
|
|
191
191
|
}
|
|
192
192
|
let match$2 = spec.eventCollectorChannelSpec;
|
|
@@ -209,7 +209,7 @@ function finish() {
|
|
|
209
209
|
evtMapperPackageDirs[mappingsPkg] = Util_Bundle$ReventlessAws.resolvePackageRoot(mappingsPkg);
|
|
210
210
|
let match$4 = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/EventMapperEntryPoint.mjs", evtMapperPackageDirs, undefined);
|
|
211
211
|
let evtMapperName = baseName + "EventMapper";
|
|
212
|
-
let evtMapperRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(evtMapperName, match$4.code, match$4.sourceCodeHash, evtMapperEnvVars, Math.max(spec.eventCollectorMemorySize, 2048), Math.max(spec.eventCollectorTimeout, 180), undefined, undefined, undefined, undefined, aggregateOpts);
|
|
212
|
+
let evtMapperRuntime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(evtMapperName, match$4.code, match$4.sourceCodeHash, evtMapperEnvVars, Math.max(spec.eventCollectorMemorySize, 2048), Math.max(spec.eventCollectorTimeout, 180), undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
213
213
|
EventCollectorChannel_DynamoDbStream$ReventlessAws.connect(evtMapperName, [match$2], evtMapperRuntime, aggregateOpts);
|
|
214
214
|
});
|
|
215
215
|
}
|
|
@@ -152,7 +152,7 @@ function finish() {
|
|
|
152
152
|
packageDirs[specPkg] = Util_Bundle$ReventlessAws.resolvePackageRoot(specPkg);
|
|
153
153
|
packageDirs[behaviorPkg] = Util_Bundle$ReventlessAws.resolvePackageRoot(behaviorPkg);
|
|
154
154
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/AggregateEntryPoint.mjs", packageDirs, undefined);
|
|
155
|
-
let runtime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(lambdaName, match.code, match.sourceCodeHash, envVars, spec.memorySize, spec.timeout, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
155
|
+
let runtime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(lambdaName, match.code, match.sourceCodeHash, envVars, spec.memorySize, spec.timeout, undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
156
156
|
spec.connects.forEach(connect => connect(runtime));
|
|
157
157
|
let channelSpecs = Stdlib_Option.mapOr(spec.eventCollectorChannelSpec, [], cs => [cs]);
|
|
158
158
|
EventCollectorChannel_DynamoDbStream$ReventlessAws.connect(name, channelSpecs, runtime, aggregateOpts);
|
|
@@ -152,7 +152,7 @@ function finish() {
|
|
|
152
152
|
packageDirs[specPkg] = Util_Bundle$ReventlessAws.resolvePackageRoot(specPkg);
|
|
153
153
|
packageDirs[behaviorPkg] = Util_Bundle$ReventlessAws.resolvePackageRoot(behaviorPkg);
|
|
154
154
|
let match = Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/AggregateEntryPoint.mjs", packageDirs, undefined);
|
|
155
|
-
let runtime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(name, match.code, match.sourceCodeHash, envVars, spec.memorySize, spec.timeout, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
155
|
+
let runtime = RuntimeEnvironment_Lambda$ReventlessAws.makeFromCodeAsset(name, match.code, match.sourceCodeHash, envVars, spec.memorySize, spec.timeout, undefined, undefined, undefined, undefined, undefined, aggregateOpts);
|
|
156
156
|
spec.connects.forEach(connect => connect(runtime));
|
|
157
157
|
let channelSpecs = Stdlib_Option.mapOr(spec.eventCollectorChannelSpec, [], cs => [cs]);
|
|
158
158
|
EventCollectorChannel_DynamoDbStream$ReventlessAws.connect(name, channelSpecs, runtime, aggregateOpts);
|