@reventlessdev/reventless-aws 3.0.0-alpha.304 → 3.0.0-alpha.306
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 +16 -0
- package/package.json +9 -9
- package/src/Platform.res +1 -1
- package/src/adapter/Api/AppSync_Resolver_Native.res +1 -1
- package/src/adapter/Api/AppSync_Resolver_Retrying.res +2 -2
- package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res +69 -11
- package/src/adapter/Auth/Auth_ActiveRolePoolAttachment.res.mjs +19 -1
- package/src/adapter/DcbEventLog/DcbEventLogStorage_DynamoDb_Runtime.res +2 -2
- package/src/adapter/DcbEventLog/DcbEventLogStorage_Postgres.res +1 -1
- package/src/adapter/EventLog/EventLogStorage_DynamoDb_Runtime.res +1 -1
- package/src/adapter/Postgres/PgChangeFeedRelay_Runtime.res +1 -1
- package/src/adapter/Postgres/PgProjectionFeed.res +1 -1
- package/src/adapter/QueryDb/QueryDbBackend.res +1 -1
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res +29 -15
- package/src/adapter/QueryDb/QueryDbResolvers_AppSync.res.mjs +6 -5
- package/src/adapter/QueryEngine/QueryEngine_DynamoDb.res +1 -1
- package/src/adapter/Runtime/AggregateEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/AggregateEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/AutomationSliceEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/AutomationSliceEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/CounterEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/CounterEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint.mjs +44 -6
- package/src/adapter/Runtime/DcbCommandTopicEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/EventCollectorEntryPoint.mjs +8 -9
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +36 -8
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res.mjs +18 -7
- package/src/adapter/Runtime/EventMapperEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/EventMapperEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/ExtensionPointEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/ExtensionPointEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/PgQueryResolverEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/PgQueryResolverEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/PluginExtensionPointEntryPoint.res +1 -1
- package/src/adapter/Runtime/ProjectionEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/QueryDbEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/ReadModelEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/ReadModelEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/RuntimeEnvironment_Lambda.res +1 -1
- package/src/adapter/Runtime/SideEffectEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/SideEffectEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res +3 -1
- package/src/adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs +4 -1
- package/src/adapter/Runtime/StateViewSliceEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/StateViewSliceEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/StreamRoutedEntryPoint_Ops.res +1 -1
- package/src/adapter/Runtime/TaskBucketEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/TaskBucketEntryPoint_Ops.res +1 -1
- package/src/plugin/runtime/PluginRuntime_Builder.res +46 -22
- package/src/plugin/runtime/PluginRuntime_Builder.res.mjs +16 -11
- package/src/util/Util_Bundle.res +1 -1
- package/src/util/Util_DynamoDbStream_Runtime.res +1 -1
- package/src/util/Util_LambdaEnvBudget.res +74 -0
- package/src/util/Util_LambdaEnvBudget.res.mjs +37 -0
- package/tests/AWS_TagsTest.res +2 -2
- package/tests/Auth_ActiveRolePoolAttachmentTest.res +140 -1
- package/tests/Auth_ActiveRolePoolAttachmentTest.res.mjs +117 -2
- package/tests/DcbEventLogStorage_DynamoDb_RuntimeTest.res +2 -2
- package/tests/EventCollectorEntryPoint_OpsTest.res +13 -4
- package/tests/EventCollectorEntryPoint_OpsTest.res.mjs +19 -13
- package/tests/EventLogStorage_DynamoDb_RuntimeTest.res +1 -1
- package/tests/QueryDbResolvers_AppSyncTest.res +2 -2
- package/tests/Util_BundleEsmLoaderTest.res +1 -1
- package/tests/Util_BundleRuntimeExtensionTest.res +1 -1
- package/tests/Util_LambdaEnvBudgetTest.res +78 -0
- package/tests/Util_LambdaEnvBudgetTest.res.mjs +55 -0
- package/tests/integration/AggregateEntryPoint_IntegrationTest.res +1 -1
- package/tests/integration/DcbCommandTopicEntryPoint_IntegrationTest.res +1 -1
- package/tests/integration/DcbEventLogStorage_DynamoDb_IntegrationTest.res +2 -2
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// driven entirely by HANDLER_CONFIG.
|
|
4
4
|
//
|
|
5
5
|
// Thin untyped shell ("typed core, thin shell" —
|
|
6
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
6
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
7
|
// seams that are inherently untyped — the dynamic `import()` of EP/extension/spec
|
|
8
8
|
// modules named in HANDLER_CONFIG and the functor applications consuming those
|
|
9
9
|
// runtime-loaded modules. Everything else (config parse/validation, the Plugin-RM
|
|
@@ -46,12 +46,9 @@
|
|
|
46
46
|
// "readModelNames": string[] // RMs this extension may enqueue events into (filter into readModelQueueUrls)
|
|
47
47
|
// }
|
|
48
48
|
// ],
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
// "readModelQueueUrls": { // rmName → env-var name holding the RM's EventCollector SQS URL
|
|
53
|
-
// "ProductDemands": "PRM_ProductDemands_QUEUE_URL"
|
|
54
|
-
// },
|
|
49
|
+
// (publishToAggregates / readModelQueueUrls moved to the queueUrls.json asset —
|
|
50
|
+
// one entry per target, so they outgrew the 4KB environment. Each still maps a
|
|
51
|
+
// target name to the PTA_/PRM_ env var holding its SQS URL.)
|
|
55
52
|
// "readModelNamesForSourceName": { // deploy-side inversion of RM.sourceNames; sourceServiceName → [rmName]
|
|
56
53
|
// "Ordering.Orders": ["ProductDemands"]
|
|
57
54
|
// }
|
|
@@ -100,6 +97,8 @@ async function buildHandler() {
|
|
|
100
97
|
await runtimeExtensionsReady;
|
|
101
98
|
const config = Ops.parseHandlerConfig(process.env["HANDLER_CONFIG"] || "");
|
|
102
99
|
const pluginDefinition = Ops.loadPluginDefinition();
|
|
100
|
+
// target → env-var name; the URLs themselves stay in the environment.
|
|
101
|
+
const queueUrlNames = Ops.loadQueueUrlNames();
|
|
103
102
|
|
|
104
103
|
const queryEngine = Ops.makeQueryEngine(config.pluginReadModelTableName);
|
|
105
104
|
const scheduler = Ops.makeScheduler(config.schedulerRoleArn);
|
|
@@ -165,7 +164,7 @@ async function buildHandler() {
|
|
|
165
164
|
return { aggregateNames: ep.aggregateNames, outgoingHandler: ops.outgoingJsonEventsHandler };
|
|
166
165
|
}));
|
|
167
166
|
|
|
168
|
-
const publishToAggregates = Ops.buildPublishToAggregates(
|
|
167
|
+
const publishToAggregates = Ops.buildPublishToAggregates(queueUrlNames.publishToAggregates);
|
|
169
168
|
const publishToPluginExtensionPoint = Ops.makePublishJsons(config.pluginExtensionPointCmdTopicUrl);
|
|
170
169
|
|
|
171
170
|
// Connect extension — exactly one entry per plugin Lambda; null for admin.
|
|
@@ -230,7 +229,7 @@ async function buildHandler() {
|
|
|
230
229
|
mappings: [transformedMapping],
|
|
231
230
|
};
|
|
232
231
|
|
|
233
|
-
const dicts = Ops.extensionPublishDicts(config, ext);
|
|
232
|
+
const dicts = Ops.extensionPublishDicts(config, queueUrlNames, ext);
|
|
234
233
|
const ops = extensionOperationsMake(epSpec)(mappingsModule)({
|
|
235
234
|
publishToAggregates: dicts.publishToAggregates,
|
|
236
235
|
publishToPluginExtensionPoint,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Typed cold-start core for the Plugin EventCollector Lambda entry point.
|
|
2
2
|
//
|
|
3
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
3
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
4
|
// EventCollectorEntryPoint.mjs owns ONLY the untyped seams — the dynamic
|
|
5
5
|
// `import()` of EP/extension/spec modules named in HANDLER_CONFIG and the
|
|
6
6
|
// functor applications consuming those runtime-loaded modules
|
|
@@ -109,9 +109,16 @@ type handlerConfig = {
|
|
|
109
109
|
extensionPoints: array<extensionPointConfig>,
|
|
110
110
|
connectExtension: option<connectExtensionConfig>,
|
|
111
111
|
extensions: array<extensionConfig>,
|
|
112
|
+
readModelNamesForSourceName: dict<array<string>>,
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// The target→env-var maps that used to ride HANDLER_CONFIG, now read from
|
|
116
|
+
// queueUrls.json (PluginRuntime_Builder). Values are env var NAMES, not URLs —
|
|
117
|
+
// the URLs stay in the environment because the builder cannot resolve those
|
|
118
|
+
// Outputs in bulk.
|
|
119
|
+
type queueUrlNames = {
|
|
112
120
|
publishToAggregates: dict<string>,
|
|
113
121
|
readModelQueueUrls: dict<string>,
|
|
114
|
-
readModelNamesForSourceName: dict<array<string>>,
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
let strOf = (obj: dict<JSON.t>, key: string): option<string> =>
|
|
@@ -149,7 +156,6 @@ let parseHandlerConfig = (rawJson: string): handlerConfig => {
|
|
|
149
156
|
"schedulerQueueName",
|
|
150
157
|
"extensionPoints",
|
|
151
158
|
"extensions",
|
|
152
|
-
"publishToAggregates",
|
|
153
159
|
]->Array.forEach(k =>
|
|
154
160
|
if obj->Dict.get(k)->Option.isNone {
|
|
155
161
|
JsError.throwWithMessage("HANDLER_CONFIG missing required field: " ++ k)
|
|
@@ -225,8 +231,6 @@ let parseHandlerConfig = (rawJson: string): handlerConfig => {
|
|
|
225
231
|
extensionPoints,
|
|
226
232
|
connectExtension,
|
|
227
233
|
extensions,
|
|
228
|
-
publishToAggregates: obj->strDictOf("publishToAggregates"),
|
|
229
|
-
readModelQueueUrls: obj->strDictOf("readModelQueueUrls"),
|
|
230
234
|
readModelNamesForSourceName,
|
|
231
235
|
}
|
|
232
236
|
}
|
|
@@ -625,7 +629,11 @@ type extensionDicts = {
|
|
|
625
629
|
readModelNamesForSourceName: dict<array<string>>,
|
|
626
630
|
}
|
|
627
631
|
|
|
628
|
-
let extensionPublishDicts = (
|
|
632
|
+
let extensionPublishDicts = (
|
|
633
|
+
config: handlerConfig,
|
|
634
|
+
names: queueUrlNames,
|
|
635
|
+
ext: extensionConfig,
|
|
636
|
+
): extensionDicts => {
|
|
629
637
|
let resolve = (names: array<string>, envVarNames: dict<string>) =>
|
|
630
638
|
names
|
|
631
639
|
->Array.filterMap(name =>
|
|
@@ -637,8 +645,8 @@ let extensionPublishDicts = (config: handlerConfig, ext: extensionConfig): exten
|
|
|
637
645
|
)
|
|
638
646
|
->Dict.fromArray
|
|
639
647
|
{
|
|
640
|
-
publishToAggregates: resolve(ext.aggregateNames,
|
|
641
|
-
publishToReadModels: resolve(ext.readModelNames,
|
|
648
|
+
publishToAggregates: resolve(ext.aggregateNames, names.publishToAggregates),
|
|
649
|
+
publishToReadModels: resolve(ext.readModelNames, names.readModelQueueUrls),
|
|
642
650
|
// Scoped to this extension's EP — Extension_Operations uses this dict to
|
|
643
651
|
// decide which RMs receive each incoming event.
|
|
644
652
|
readModelNamesForSourceName: Dict.fromArray([
|
|
@@ -680,6 +688,26 @@ let loadPluginDefinition = (): Reventless.Plugin.pluginDefinition =>
|
|
|
680
688
|
)
|
|
681
689
|
}
|
|
682
690
|
|
|
691
|
+
// The target→env-var maps, read once at cold start. A plugin that publishes
|
|
692
|
+
// nowhere writes empty maps rather than omitting the file, so a read failure is
|
|
693
|
+
// a genuinely broken archive and not an empty-map case worth guessing at.
|
|
694
|
+
let loadQueueUrlNames = (): queueUrlNames =>
|
|
695
|
+
try {
|
|
696
|
+
let obj =
|
|
697
|
+
assetPath("queueUrls.json")
|
|
698
|
+
->NodeFs.readFileSync
|
|
699
|
+
->JSON.parseOrThrow
|
|
700
|
+
->JSON.Decode.object
|
|
701
|
+
->Option.getOr(Dict.make())
|
|
702
|
+
{
|
|
703
|
+
publishToAggregates: obj->strDictOf("publishToAggregates"),
|
|
704
|
+
readModelQueueUrls: obj->strDictOf("readModelQueueUrls"),
|
|
705
|
+
}
|
|
706
|
+
} catch {
|
|
707
|
+
| exn =>
|
|
708
|
+
JsError.throwWithMessage("Failed to load queueUrls.json from asset zip: " ++ exnMessage(exn))
|
|
709
|
+
}
|
|
710
|
+
|
|
683
711
|
// The plugin's UI-fragment manifest — its own asset since the manifest no
|
|
684
712
|
// longer rides pluginDefinition (the UiFragmentRegistry slice owns fragment
|
|
685
713
|
// state). JSON null (plugins without a UI) and a missing file (older archives)
|
|
@@ -111,8 +111,7 @@ function parseHandlerConfig(rawJson) {
|
|
|
111
111
|
"schedulerQueueArn",
|
|
112
112
|
"schedulerQueueName",
|
|
113
113
|
"extensionPoints",
|
|
114
|
-
"extensions"
|
|
115
|
-
"publishToAggregates"
|
|
114
|
+
"extensions"
|
|
116
115
|
].forEach(k => {
|
|
117
116
|
if (Stdlib_Option.isNone(obj[k])) {
|
|
118
117
|
return Stdlib_JsError.throwWithMessage("HANDLER_CONFIG missing required field: " + k);
|
|
@@ -159,8 +158,6 @@ function parseHandlerConfig(rawJson) {
|
|
|
159
158
|
extensionPoints: extensionPoints,
|
|
160
159
|
connectExtension: connectExtension,
|
|
161
160
|
extensions: extensions,
|
|
162
|
-
publishToAggregates: strDictOf(obj, "publishToAggregates"),
|
|
163
|
-
readModelQueueUrls: strDictOf(obj, "readModelQueueUrls"),
|
|
164
161
|
readModelNamesForSourceName: readModelNamesForSourceName
|
|
165
162
|
};
|
|
166
163
|
}
|
|
@@ -495,14 +492,14 @@ function buildPublishToAggregates(map) {
|
|
|
495
492
|
]));
|
|
496
493
|
}
|
|
497
494
|
|
|
498
|
-
function extensionPublishDicts(config, ext) {
|
|
495
|
+
function extensionPublishDicts(config, names, ext) {
|
|
499
496
|
let resolve = (names, envVarNames) => Object.fromEntries(Stdlib_Array.filterMap(names, name => Stdlib_Option.map(Stdlib_Option.filter(Stdlib_Option.flatMap(envVarNames[name], envVarName => process.env[envVarName]), queueUrl => queueUrl !== ""), queueUrl => [
|
|
500
497
|
name,
|
|
501
498
|
makePublishJsons(queueUrl)
|
|
502
499
|
])));
|
|
503
500
|
return {
|
|
504
|
-
publishToAggregates: resolve(ext.aggregateNames,
|
|
505
|
-
publishToReadModels: resolve(ext.readModelNames,
|
|
501
|
+
publishToAggregates: resolve(ext.aggregateNames, names.publishToAggregates),
|
|
502
|
+
publishToReadModels: resolve(ext.readModelNames, names.readModelQueueUrls),
|
|
506
503
|
readModelNamesForSourceName: Object.fromEntries([[
|
|
507
504
|
ext.extensionPointName,
|
|
508
505
|
Stdlib_Option.getOr(config.readModelNamesForSourceName[ext.extensionPointName], [])
|
|
@@ -529,6 +526,19 @@ function loadPluginDefinition() {
|
|
|
529
526
|
}
|
|
530
527
|
}
|
|
531
528
|
|
|
529
|
+
function loadQueueUrlNames() {
|
|
530
|
+
try {
|
|
531
|
+
let obj = Stdlib_Option.getOr(Stdlib_JSON.Decode.object(JSON.parse(Nodefs.readFileSync(assetPath("queueUrls.json"), "utf8"))), {});
|
|
532
|
+
return {
|
|
533
|
+
publishToAggregates: strDictOf(obj, "publishToAggregates"),
|
|
534
|
+
readModelQueueUrls: strDictOf(obj, "readModelQueueUrls")
|
|
535
|
+
};
|
|
536
|
+
} catch (raw_exn) {
|
|
537
|
+
let exn = Primitive_exceptions.internalToException(raw_exn);
|
|
538
|
+
return Stdlib_JsError.throwWithMessage("Failed to load queueUrls.json from asset zip: " + exnMessage(exn));
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
532
542
|
function loadUiFragments() {
|
|
533
543
|
try {
|
|
534
544
|
let json = JSON.parse(Nodefs.readFileSync(assetPath("uiFragments.json"), "utf8"));
|
|
@@ -649,6 +659,7 @@ export {
|
|
|
649
659
|
warnSkippedExtension,
|
|
650
660
|
assetPath,
|
|
651
661
|
loadPluginDefinition,
|
|
662
|
+
loadQueueUrlNames,
|
|
652
663
|
loadUiFragments,
|
|
653
664
|
pushHandler,
|
|
654
665
|
makeSqsHandlerBundle,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// wires EventMapper_Callback.MakeCounterHandler + MakeEventCollectorHandler.
|
|
4
4
|
//
|
|
5
5
|
// Thin untyped shell ("typed core, thin shell" —
|
|
6
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
6
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
7
|
// seams that are inherently untyped — the dynamic `import()` of the
|
|
8
8
|
// target-spec/mappings modules named in HANDLER_CONFIG, the shape fix-ups on
|
|
9
9
|
// those runtime-loaded modules (patchSpecId / patchMappingsSourceIds), and the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Typed cold-start core for the EventMapper Lambda entry point (Micro mode).
|
|
2
2
|
//
|
|
3
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
3
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
4
|
// EventMapperEntryPoint.mjs keeps only the untyped seam — the dynamic
|
|
5
5
|
// `import()` of the target-spec/mappings modules named in HANDLER_CONFIG, the
|
|
6
6
|
// `patchSpecId` / mapping-Source-Id fix-ups, and the
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// routes SQS events through handleQueueEvent.
|
|
5
5
|
//
|
|
6
6
|
// Thin untyped shell ("typed core, thin shell" —
|
|
7
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
8
8
|
// seams that are inherently untyped — the dynamic `import()` of the
|
|
9
9
|
// spec/mappings modules named in HANDLER_CONFIG, the `patchSpecId` fix-up, and
|
|
10
10
|
// the two functor applications consuming them. The callback config,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Typed cold-start core for the (per-extension-point) ExtensionPoint Lambda
|
|
2
2
|
// entry point.
|
|
3
3
|
//
|
|
4
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
5
5
|
// ExtensionPointEntryPoint.mjs keeps only the untyped seam — the dynamic
|
|
6
6
|
// `import()` of the spec/mappings modules named in HANDLER_CONFIG, the
|
|
7
7
|
// `patchSpecId` fix-up, and the ExtensionPoint_Callback.Make /
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// PgQueryResolver_Lambda.dispatch routes.
|
|
10
10
|
//
|
|
11
11
|
// Thin untyped shell ("typed core, thin shell" —
|
|
12
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
12
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
13
13
|
// seams that are inherently untyped — the dynamic `import()` of the spec
|
|
14
14
|
// packages named in QUERY_RESOLVER_CONFIG, the `patchSpecId` fix-up, and the
|
|
15
15
|
// reads of the runtime-loaded modules' exports. QUERY_RESOLVER_CONFIG parsing,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Typed cold-start core for the shared PgQueryResolver Lambda entry point
|
|
2
2
|
// (B3.2b).
|
|
3
3
|
//
|
|
4
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
5
5
|
// PgQueryResolverEntryPoint.mjs keeps only the untyped seam — the dynamic
|
|
6
6
|
// `import()` of each spec package named in QUERY_RESOLVER_CONFIG, the
|
|
7
7
|
// `patchSpecId` fix-up, and the reads of the runtime-loaded module's exports
|
|
@@ -95,7 +95,7 @@ module Mappings = {
|
|
|
95
95
|
// Parity with the former shell: only the Plugin lifecycle mapping. The
|
|
96
96
|
// in-process wiring (PluginExtensionPoint_Builder) additionally registers
|
|
97
97
|
// PluginExtensionPoint_UiFragment.Mapping — divergence tracked in
|
|
98
|
-
// docs/plans/entry-point-rescript-conversion.md.
|
|
98
|
+
// docs/plans/done/entry-point-rescript-conversion.md.
|
|
99
99
|
let mappings: array<module(Mapping)> = [module(PluginMappingInstance.Mapping)]
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Typed QueryDb-assembly core shared by the two projection Lambda entry points
|
|
2
2
|
// (ReadModelEntryPoint.mjs, StateViewSliceEntryPoint.mjs).
|
|
3
3
|
//
|
|
4
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
5
5
|
// both shells build the QueryDb operation set (DynamoDB or Postgres, live-update
|
|
6
6
|
// wrapped) for each projection from spec-module reads; that machinery lives
|
|
7
7
|
// here, fully type-checked. The routed dispatch boundary they share (with the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Typed cold-start core shared by the QueryDb-backed entry-point shells
|
|
2
2
|
// (ReadModelEntryPoint.mjs, StateViewSliceEntryPoint.mjs).
|
|
3
3
|
//
|
|
4
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md).
|
|
4
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md).
|
|
5
5
|
// The DynamoDB QueryDb operations were built in each shell with seven positional
|
|
6
6
|
// `load(table)` / `save(table)` / … calls into the compiled runtime, assembled
|
|
7
7
|
// into an object the shell then passes to the ReadModel/StateViewSlice callback
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// wires ReadModel_Callback.Make, builds handler map keyed by source URN.
|
|
4
4
|
//
|
|
5
5
|
// Thin untyped shell ("typed core, thin shell" —
|
|
6
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
6
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
7
|
// seams that are inherently untyped — the dynamic `import()` of spec/mappings
|
|
8
8
|
// modules named in HANDLER_CONFIG, the shape fix-ups on those runtime-loaded
|
|
9
9
|
// modules (patchSpecId / fixMappingsModule), and the ReadModel_Callback.Make
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Typed cold-start core for the ReadModel Lambda entry point.
|
|
2
2
|
//
|
|
3
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
3
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
4
|
// ReadModelEntryPoint.mjs keeps only the untyped seams — the dynamic `import()`
|
|
5
5
|
// of spec/mappings modules named in HANDLER_CONFIG, the `patchSpecId` /
|
|
6
6
|
// `fixMappingsModule` shape fix-ups on those runtime-loaded modules, and the
|
|
@@ -354,7 +354,7 @@ let makeFromCodeAsset: (
|
|
|
354
354
|
|
|
355
355
|
// Announce the provisioned execution unit to the Monitoring registry. No-op
|
|
356
356
|
// unless a deploy program registered a backend via Monitoring.use — see
|
|
357
|
-
// docs/plans/monitoring-hook-seam.md.
|
|
357
|
+
// docs/plans/done/monitoring-hook-seam.md.
|
|
358
358
|
ReventlessCore.Monitoring.notify(~kind=unitKind, ~name, ~component=lambdaResource)
|
|
359
359
|
|
|
360
360
|
{
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// wires SideEffectHandler_Callback.Make, builds handler map keyed by source URN.
|
|
4
4
|
//
|
|
5
5
|
// Thin untyped shell ("typed core, thin shell" —
|
|
6
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
6
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
7
|
// seams that are inherently untyped — the dynamic `import()` of the side-effect
|
|
8
8
|
// modules named in HANDLER_CONFIG and the SideEffectHandler_Callback.Make
|
|
9
9
|
// functor application consuming them. HANDLER_CONFIG parsing and handler
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Typed cold-start core for the SideEffectHandler Lambda entry point.
|
|
2
2
|
//
|
|
3
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
3
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
4
|
// SideEffectEntryPoint.mjs keeps only the untyped seam — the dynamic `import()`
|
|
5
5
|
// of the side-effect modules named in HANDLER_CONFIG and the
|
|
6
6
|
// SideEffectHandler_Callback.Make functor application consuming them.
|
|
@@ -179,7 +179,9 @@ let forDcbCommandTopic = (
|
|
|
179
179
|
Pulumi.Output.all4((dcbTableName, queue.id, pgConnectionFragment, inboundFragment))
|
|
180
180
|
->Pulumi.Output.apply(((table, queueUrl, pgFragment, inbFragment)) => {
|
|
181
181
|
let pluginNameJson = pluginName->JSON.stringifyAny->Option.getOr(`""`)
|
|
182
|
-
`{"dcbEventLogTableName":"${table}","queueUrl":"${queueUrl}","pluginName":${pluginNameJson}${pgFragment}${inbFragment}}`
|
|
182
|
+
let json = `{"dcbEventLogTableName":"${table}","queueUrl":"${queueUrl}","pluginName":${pluginNameJson}${pgFragment}${inbFragment}}`
|
|
183
|
+
Util_LambdaEnvBudget.check(~lambdaName=name, ~handlerConfigJson=json)
|
|
184
|
+
json
|
|
183
185
|
})
|
|
184
186
|
envVars->Dict.set("HANDLER_CONFIG", handlerConfigJson->Pulumi.Output.asInput)
|
|
185
187
|
|
|
@@ -11,6 +11,7 @@ import * as DcbBackend$ReventlessAws from "../DcbEventLog/DcbBackend.res.mjs";
|
|
|
11
11
|
import * as PolicyDocument$PulumiAws from "@reventlessdev/rescript-pulumi-aws/src/IAM/PolicyDocument.res.mjs";
|
|
12
12
|
import * as Util_Bundle$ReventlessAws from "../../util/Util_Bundle.res.mjs";
|
|
13
13
|
import * as PgConnection$ReventlessAws from "../Postgres/PgConnection.res.mjs";
|
|
14
|
+
import * as Util_LambdaEnvBudget$ReventlessAws from "../../util/Util_LambdaEnvBudget.res.mjs";
|
|
14
15
|
import * as CommandTopicChannel_SQS$ReventlessAws from "../CommandTopic/CommandTopicChannel_SQS.res.mjs";
|
|
15
16
|
import * as RuntimeEnvironment_Lambda$ReventlessAws from "./RuntimeEnvironment_Lambda.res.mjs";
|
|
16
17
|
|
|
@@ -79,7 +80,9 @@ function forDcbCommandTopic(slicePaths, inboundSlicesOpt, dcbTableName, pluginNa
|
|
|
79
80
|
inboundFragment
|
|
80
81
|
]).apply(param => {
|
|
81
82
|
let pluginNameJson = Stdlib_Option.getOr(JSON.stringify(pluginName), `""`);
|
|
82
|
-
|
|
83
|
+
let json = `{"dcbEventLogTableName":"` + param[0] + `","queueUrl":"` + param[1] + `","pluginName":` + pluginNameJson + param[2] + param[3] + `}`;
|
|
84
|
+
Util_LambdaEnvBudget$ReventlessAws.check(name, json, undefined);
|
|
85
|
+
return json;
|
|
83
86
|
});
|
|
84
87
|
envVars["HANDLER_CONFIG"] = handlerConfigJson;
|
|
85
88
|
let packageDirs = {};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// source URN.
|
|
5
5
|
//
|
|
6
6
|
// Thin untyped shell ("typed core, thin shell" —
|
|
7
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
8
8
|
// inherently-untyped seam — the dynamic `import()` of spec/projection modules
|
|
9
9
|
// named in HANDLER_CONFIG and the reads of their exports. Everything else
|
|
10
10
|
// (HANDLER_CONFIG parsing incl. the compact-v2 expansion, the QueryDb operation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Typed cold-start core for the StateViewSlice Lambda entry point.
|
|
2
2
|
//
|
|
3
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
3
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
4
|
// StateViewSliceEntryPoint.mjs keeps only the inherently-untyped seam — the
|
|
5
5
|
// dynamic `import()` of spec/projection modules named in HANDLER_CONFIG and the
|
|
6
6
|
// reads of their exports. HANDLER_CONFIG parsing (including the compact-v2
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// points (ReadModelEntryPoint.mjs, StateViewSliceEntryPoint.mjs,
|
|
3
3
|
// AutomationSliceEntryPoint.mjs).
|
|
4
4
|
//
|
|
5
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
5
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
6
6
|
// all three shells route DynamoDB-stream / SQS-feed records to per-source-URN
|
|
7
7
|
// handler lists with per-handler log attribution — machinery the `.mjs` files
|
|
8
8
|
// previously duplicated verbatim. It lives here so every co-hosted component
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// Events schedules).
|
|
5
5
|
//
|
|
6
6
|
// Thin untyped shell ("typed core, thin shell" —
|
|
7
|
-
// docs/plans/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
7
|
+
// docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md): this file owns ONLY the
|
|
8
8
|
// inherently-untyped seam — the dynamic `import()` of the callback module named
|
|
9
9
|
// in HANDLER_CONFIG and the read of its `callback` export. Everything else
|
|
10
10
|
// (HANDLER_CONFIG parsing, S3-event handling via TaskBucket_S3_Runtime, the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Typed cold-start core for the TaskBucket Lambda entry point.
|
|
2
2
|
//
|
|
3
|
-
// The "typed core, thin shell" split (docs/plans/minimize-lambda-entrypoint-mjs-shell.md):
|
|
3
|
+
// The "typed core, thin shell" split (docs/plans/done/minimize-lambda-entrypoint-mjs-shell.md):
|
|
4
4
|
// TaskBucketEntryPoint.mjs keeps only the inherently-untyped seam — the
|
|
5
5
|
// dynamic `import()` of the task callback module named in HANDLER_CONFIG and
|
|
6
6
|
// the read of its `callback` export. HANDLER_CONFIG parsing, the S3-event →
|
|
@@ -503,27 +503,13 @@ module Make = (
|
|
|
503
503
|
})
|
|
504
504
|
dict->Dict.set("extensions", JSON.Encode.array(extensionsArr))
|
|
505
505
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
)
|
|
514
|
-
)
|
|
515
|
-
dict->Dict.set("publishToAggregates", JSON.Encode.object(publishToAggregatesDict))
|
|
516
|
-
|
|
517
|
-
let readModelQueueUrlsDict = Dict.make()
|
|
518
|
-
context.readModelQueueUrls
|
|
519
|
-
->Dict.keysToArray
|
|
520
|
-
->Array.forEach(rmName =>
|
|
521
|
-
readModelQueueUrlsDict->Dict.set(
|
|
522
|
-
rmName,
|
|
523
|
-
JSON.Encode.string(`PRM_${rmName}_QUEUE_URL`),
|
|
524
|
-
)
|
|
525
|
-
)
|
|
526
|
-
dict->Dict.set("readModelQueueUrls", JSON.Encode.object(readModelQueueUrlsDict))
|
|
506
|
+
// publishToAggregates / readModelQueueUrls live in queueUrls.json (see the
|
|
507
|
+
// asset bundle below). Both are one entry per target, so they grow with the
|
|
508
|
+
// plugin, and together with the PTA_/PRM_ vars they name they carried the
|
|
509
|
+
// catalog EventCollector past Lambda's 4KB environment ceiling. Only the
|
|
510
|
+
// maps move: they are built from Dict.keysToArray, so they hold no Pulumi
|
|
511
|
+
// Output and can be serialized here. The URLs themselves cannot follow —
|
|
512
|
+
// see the note on the aggregate walk further down.
|
|
527
513
|
|
|
528
514
|
let rmNamesForSourceDict = Dict.make()
|
|
529
515
|
context.readModelNamesForSourceName
|
|
@@ -536,7 +522,22 @@ module Make = (
|
|
|
536
522
|
)
|
|
537
523
|
dict->Dict.set("readModelNamesForSourceName", JSON.Encode.object(rmNamesForSourceDict))
|
|
538
524
|
|
|
539
|
-
JSON.Encode.object(dict)->JSON.stringify
|
|
525
|
+
let json = JSON.Encode.object(dict)->JSON.stringify
|
|
526
|
+
// The PTA_/PRM_ vars are the rest of this Lambda's environment and the
|
|
527
|
+
// half that grows with the plugin. Their names are known here; their
|
|
528
|
+
// values are still Outputs, so the budget check estimates those.
|
|
529
|
+
let queueUrlKeys = Array.concat(
|
|
530
|
+
context.publishToAggregates
|
|
531
|
+
->Dict.keysToArray
|
|
532
|
+
->Array.map(n => `PTA_${n}_QUEUE_URL`),
|
|
533
|
+
context.readModelQueueUrls->Dict.keysToArray->Array.map(n => `PRM_${n}_QUEUE_URL`),
|
|
534
|
+
)
|
|
535
|
+
Util_LambdaEnvBudget.check(
|
|
536
|
+
~lambdaName=name,
|
|
537
|
+
~handlerConfigJson=json,
|
|
538
|
+
~outputValuedKeys=queueUrlKeys,
|
|
539
|
+
)
|
|
540
|
+
json
|
|
540
541
|
})
|
|
541
542
|
envVars->Dict.set("HANDLER_CONFIG", handlerConfigJson->Pulumi.Output.asInput)
|
|
542
543
|
|
|
@@ -599,6 +600,29 @@ module Make = (
|
|
|
599
600
|
->Pulumi.Output.apply(((pluginDefinitionJson, uiFragmentsJson)) => {
|
|
600
601
|
let extraStringAssets = Dict.make()
|
|
601
602
|
extraStringAssets->Dict.set("pluginDefinition.json", pluginDefinitionJson)
|
|
603
|
+
// target name → the env var holding that target's queue URL. The
|
|
604
|
+
// indirection stays (the URLs are Outputs this builder must not resolve
|
|
605
|
+
// in bulk); only the naming map moves out of HANDLER_CONFIG.
|
|
606
|
+
let nameMap = (names: array<string>, prefix: string) => {
|
|
607
|
+
let d = Dict.make()
|
|
608
|
+
names
|
|
609
|
+
->Array.toSorted(String.compare)
|
|
610
|
+
->Array.forEach(n => d->Dict.set(n, JSON.Encode.string(`${prefix}_${n}_QUEUE_URL`)))
|
|
611
|
+
JSON.Encode.object(d)
|
|
612
|
+
}
|
|
613
|
+
let queueUrlsDict = Dict.make()
|
|
614
|
+
queueUrlsDict->Dict.set(
|
|
615
|
+
"publishToAggregates",
|
|
616
|
+
nameMap(context.publishToAggregates->Dict.keysToArray, "PTA"),
|
|
617
|
+
)
|
|
618
|
+
queueUrlsDict->Dict.set(
|
|
619
|
+
"readModelQueueUrls",
|
|
620
|
+
nameMap(context.readModelQueueUrls->Dict.keysToArray, "PRM"),
|
|
621
|
+
)
|
|
622
|
+
extraStringAssets->Dict.set(
|
|
623
|
+
"queueUrls.json",
|
|
624
|
+
JSON.Encode.object(queueUrlsDict)->JSON.stringify,
|
|
625
|
+
)
|
|
602
626
|
// The UI-fragment manifest no longer rides pluginDefinition — ship it as
|
|
603
627
|
// its own asset ("null" for plugins without a UI) so the bundled Connect
|
|
604
628
|
// extension can emit RegisterUiFragment in the handshake answer.
|
|
@@ -16,6 +16,7 @@ import * as ComponentType$ReventlessCore from "@reventlessdev/reventless-core/sr
|
|
|
16
16
|
import * as EventCollector$ReventlessCore from "@reventlessdev/reventless-core/src/components/EventCollector/EventCollector.res.mjs";
|
|
17
17
|
import * as EventLogBackend$ReventlessAws from "../../adapter/EventLog/EventLogBackend.res.mjs";
|
|
18
18
|
import * as Plugin_Helpers$ReventlessCore from "@reventlessdev/reventless-core/src/plugin/component/Plugin_Helpers.res.mjs";
|
|
19
|
+
import * as Util_LambdaEnvBudget$ReventlessAws from "../../util/Util_LambdaEnvBudget.res.mjs";
|
|
19
20
|
import * as Platform_Admin_Structure$ReventlessCore from "@reventlessdev/reventless-core/src/admin/Platform_Admin_Structure.res.mjs";
|
|
20
21
|
import * as RuntimeEnvironment_Lambda$ReventlessAws from "../../adapter/Runtime/RuntimeEnvironment_Lambda.res.mjs";
|
|
21
22
|
import * as StateChangeSliceRuntime_Builder_Single$ReventlessAws from "../../adapter/Runtime/StateChangeSliceRuntime_Builder_Single.res.mjs";
|
|
@@ -323,22 +324,15 @@ function Make(EventCollectorChannel) {
|
|
|
323
324
|
return entryDict;
|
|
324
325
|
});
|
|
325
326
|
dict["extensions"] = extensionsArr;
|
|
326
|
-
let publishToAggregatesDict = {};
|
|
327
|
-
Object.keys(context.publishToAggregates).forEach(aggName => {
|
|
328
|
-
publishToAggregatesDict[aggName] = `PTA_` + aggName + `_QUEUE_URL`;
|
|
329
|
-
});
|
|
330
|
-
dict["publishToAggregates"] = publishToAggregatesDict;
|
|
331
|
-
let readModelQueueUrlsDict = {};
|
|
332
|
-
Object.keys(context.readModelQueueUrls).forEach(rmName => {
|
|
333
|
-
readModelQueueUrlsDict[rmName] = `PRM_` + rmName + `_QUEUE_URL`;
|
|
334
|
-
});
|
|
335
|
-
dict["readModelQueueUrls"] = readModelQueueUrlsDict;
|
|
336
327
|
let rmNamesForSourceDict = {};
|
|
337
328
|
Object.entries(context.readModelNamesForSourceName).forEach(param => {
|
|
338
329
|
rmNamesForSourceDict[param[0]] = param[1].map(prim => prim);
|
|
339
330
|
});
|
|
340
331
|
dict["readModelNamesForSourceName"] = rmNamesForSourceDict;
|
|
341
|
-
|
|
332
|
+
let json = JSON.stringify(dict);
|
|
333
|
+
let queueUrlKeys = Object.keys(context.publishToAggregates).map(n => `PTA_` + n + `_QUEUE_URL`).concat(Object.keys(context.readModelQueueUrls).map(n => `PRM_` + n + `_QUEUE_URL`));
|
|
334
|
+
Util_LambdaEnvBudget$ReventlessAws.check(name, json, queueUrlKeys);
|
|
335
|
+
return json;
|
|
342
336
|
});
|
|
343
337
|
envVars["HANDLER_CONFIG"] = handlerConfigJson;
|
|
344
338
|
let packageDirs = {};
|
|
@@ -374,6 +368,17 @@ function Make(EventCollectorChannel) {
|
|
|
374
368
|
]).apply(param => {
|
|
375
369
|
let extraStringAssets = {};
|
|
376
370
|
extraStringAssets["pluginDefinition.json"] = param[0];
|
|
371
|
+
let nameMap = (names, prefix) => {
|
|
372
|
+
let d = {};
|
|
373
|
+
names.toSorted(Primitive_string.compare).forEach(n => {
|
|
374
|
+
d[n] = prefix + `_` + n + `_QUEUE_URL`;
|
|
375
|
+
});
|
|
376
|
+
return d;
|
|
377
|
+
};
|
|
378
|
+
let queueUrlsDict = {};
|
|
379
|
+
queueUrlsDict["publishToAggregates"] = nameMap(Object.keys(context.publishToAggregates), "PTA");
|
|
380
|
+
queueUrlsDict["readModelQueueUrls"] = nameMap(Object.keys(context.readModelQueueUrls), "PRM");
|
|
381
|
+
extraStringAssets["queueUrls.json"] = JSON.stringify(queueUrlsDict);
|
|
377
382
|
extraStringAssets["uiFragments.json"] = param[1];
|
|
378
383
|
return Util_Bundle$ReventlessAws.buildCodeArchive("@reventlessdev/reventless-aws/src/adapter/Runtime/EventCollectorEntryPoint.mjs", packageDirs, extraStringAssets, undefined);
|
|
379
384
|
});
|
package/src/util/Util_Bundle.res
CHANGED
|
@@ -122,7 +122,7 @@ let hashString = (str: string): string =>
|
|
|
122
122
|
// (set on the Lambda env by RuntimeEnvironment_Lambda.makeFromCodeAsset). Shipped
|
|
123
123
|
// at the root of every code archive; NODE_OPTIONS=--import points Node at
|
|
124
124
|
// register-hook.mjs. Validated on a Node 22.17.1 rig; see
|
|
125
|
-
// docs/plans/deployed-lambda-esm-self-containment.md.
|
|
125
|
+
// docs/plans/done/deployed-lambda-esm-self-containment.md.
|
|
126
126
|
let registerHookFileName = "register-hook.mjs"
|
|
127
127
|
let layerResolverFileName = "layer-resolver.mjs"
|
|
128
128
|
|
|
@@ -5,7 +5,7 @@ type result =
|
|
|
5
5
|
| Invalid
|
|
6
6
|
|
|
7
7
|
// Returns None for rows that aren't events — e.g. DCB FENCE rows and aggregate
|
|
8
|
-
// snapshot rows (position = "SNAPSHOT"; docs/plans/aggregate-snapshotting.md),
|
|
8
|
+
// snapshot rows (position = "SNAPSHOT"; docs/plans/done/aggregate-snapshotting.md),
|
|
9
9
|
// neither of which has an `event` column. The caller filters these out via
|
|
10
10
|
// `Invalid` rather than synthesising a bogus event that sury would later reject.
|
|
11
11
|
let buildJsonEvent' = dict => {
|