@reventlessdev/reventless-aws 3.0.0-alpha.422 → 3.0.0-alpha.423
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/package.json +6 -6
- package/src/adapter/Runtime/EventCollectorEntryPoint.mjs +1 -1
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res +10 -0
- package/src/adapter/Runtime/EventCollectorEntryPoint_Ops.res.mjs +10 -0
- package/src/adapter/Runtime/HandlerFactoryHelpers.mjs +14 -0
- package/tests/EventCollectorEntryPoint_OpsTest.res +20 -0
- package/tests/EventCollectorEntryPoint_OpsTest.res.mjs +23 -0
- package/tests/HandlerFactoryDispatchTest.res +17 -0
- package/tests/HandlerFactoryDispatchTest.res.mjs +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 3.0.0-alpha.423 (2026-11-05)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **aws:** a line logged outside its invocation's fiber still names the plugin ([8e6f553](https://github.com/ReventlessDev/reventless-core/commit/8e6f553cc8ac2e439862bf1f3636ac86a4a22137))
|
|
11
|
+
* **aws:** an extension's lines name its extension point once ([b448c59](https://github.com/ReventlessDev/reventless-core/commit/b448c5976feafd7d49ae8c04a67dcfbb72e973b5))
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
# 3.0.0-alpha.422 (2026-11-05)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @reventlessdev/reventless-aws
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-aws",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.423",
|
|
4
4
|
"description": "AWS adapters for Reventless",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -24,17 +24,17 @@
|
|
|
24
24
|
"yaml": "^2.8.3",
|
|
25
25
|
"@reventlessdev/rescript-aws-sdk": "3.0.0-alpha.39",
|
|
26
26
|
"@reventlessdev/rescript-effect": "1.0.0-alpha.1",
|
|
27
|
-
"@reventlessdev/rescript-node": "2.0.0-alpha.26",
|
|
28
|
-
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.39",
|
|
29
27
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.13",
|
|
30
|
-
"@reventlessdev/rescript-pulumi-
|
|
28
|
+
"@reventlessdev/rescript-pulumi-aws": "3.0.0-alpha.39",
|
|
29
|
+
"@reventlessdev/rescript-node": "2.0.0-alpha.26",
|
|
31
30
|
"@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
|
|
31
|
+
"@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
|
|
32
32
|
"@reventlessdev/rescript-web": "1.0.0-alpha.8",
|
|
33
|
+
"@reventlessdev/reventless-core": "3.0.0-alpha.330",
|
|
33
34
|
"@reventlessdev/reventless-infra": "3.0.0-alpha.223",
|
|
34
35
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.42",
|
|
35
36
|
"@reventlessdev/reventless-spec": "3.0.0-alpha.194",
|
|
36
|
-
"@reventlessdev/reventless-postgres": "3.0.0-alpha.
|
|
37
|
-
"@reventlessdev/reventless-core": "3.0.0-alpha.329"
|
|
37
|
+
"@reventlessdev/reventless-postgres": "3.0.0-alpha.194"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"rescript": "12.3.1",
|
|
@@ -218,7 +218,7 @@ async function buildHandler() {
|
|
|
218
218
|
};
|
|
219
219
|
const transformedMapping = extensionMappingMake(fullMapping);
|
|
220
220
|
const mappingsModule = {
|
|
221
|
-
name: ext
|
|
221
|
+
name: Ops.mappingsName(ext),
|
|
222
222
|
moduleUrl: ext.mappingsModule,
|
|
223
223
|
mappings: [transformedMapping],
|
|
224
224
|
};
|
|
@@ -561,6 +561,16 @@ let extensionPublishDicts = (names: queueUrlNames, ext: extensionConfig): extens
|
|
|
561
561
|
{publishToAggregates: resolve(ext.aggregateNames, names.publishToAggregates)}
|
|
562
562
|
}
|
|
563
563
|
|
|
564
|
+
/** The name an extension's mappings carry, as at deploy: its plugin's. The config names the
|
|
565
|
+
extension component, `<extension point>.<plugin>`, and `Extension_Operations` prefixes the
|
|
566
|
+
extension point itself. */
|
|
567
|
+
let mappingsName = (ext: extensionConfig): string => {
|
|
568
|
+
let prefix = ext.extensionPointName ++ "."
|
|
569
|
+
ext.name->String.startsWith(prefix)
|
|
570
|
+
? ext.name->String.slice(~start=prefix->String.length, ~end=ext.name->String.length)
|
|
571
|
+
: ext.name
|
|
572
|
+
}
|
|
573
|
+
|
|
564
574
|
let warnSkippedExtension = (ext: extensionConfig) =>
|
|
565
575
|
logWarn(
|
|
566
576
|
`extension '${ext.name}' missing module specifier(s); skipping. specModule=${ext.specModule}, mappingsModule=${ext.mappingsModule}, delegateModule=${ext.delegateModule}`,
|
|
@@ -445,6 +445,15 @@ function extensionPublishDicts(names, ext) {
|
|
|
445
445
|
};
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
+
function mappingsName(ext) {
|
|
449
|
+
let prefix = ext.extensionPointName + ".";
|
|
450
|
+
if (ext.name.startsWith(prefix)) {
|
|
451
|
+
return ext.name.slice(prefix.length, ext.name.length);
|
|
452
|
+
} else {
|
|
453
|
+
return ext.name;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
448
457
|
function warnSkippedExtension(ext) {
|
|
449
458
|
HandlerFactoryHelpersMjs.log.warn(`extension '` + ext.name + `' missing module specifier(s); skipping. specModule=` + ext.specModule + `, mappingsModule=` + ext.mappingsModule + `, delegateModule=` + ext.delegateModule, {
|
|
450
459
|
comp: "EventCollectorEntryPoint"
|
|
@@ -592,6 +601,7 @@ export {
|
|
|
592
601
|
makePublishJsons,
|
|
593
602
|
buildPublishToAggregates,
|
|
594
603
|
extensionPublishDicts,
|
|
604
|
+
mappingsName,
|
|
595
605
|
warnSkippedExtension,
|
|
596
606
|
assetPath,
|
|
597
607
|
loadPluginDefinition,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
tag as requestContextTag,
|
|
7
7
|
fromOptions as makeRequestContext,
|
|
8
8
|
} from "@reventlessdev/reventless-core/src/RequestContext.res.mjs";
|
|
9
|
+
import { currentPluginName } from "@reventlessdev/reventless-spec/src/LogPrefix.res.mjs";
|
|
9
10
|
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
10
11
|
import { DynamoDBDocumentClient, ScanCommand } from "@aws-sdk/lib-dynamodb";
|
|
11
12
|
|
|
@@ -120,6 +121,19 @@ export function runEffect(effect, opts = {}) {
|
|
|
120
121
|
// Only annotate a redelivery. A constant "1" on every line is noise, and its
|
|
121
122
|
// absence is what makes `filter retryCount > 1` a usable query.
|
|
122
123
|
if (retryCount > 1) e = e.pipe(Effect.annotateLogs("retryCount", String(retryCount)));
|
|
124
|
+
// A line run on a fiber of its own (`->Effect.runSync`) misses these annotations, and the
|
|
125
|
+
// component→plugin registry is empty in a Lambda: it names its plugin from the ambient one,
|
|
126
|
+
// set for the invocation and restored after it.
|
|
127
|
+
if (resolvedPlugin) {
|
|
128
|
+
const inner = e;
|
|
129
|
+
e = Effect.suspend(() => {
|
|
130
|
+
const before = currentPluginName.contents;
|
|
131
|
+
currentPluginName.contents = resolvedPlugin;
|
|
132
|
+
return inner.pipe(
|
|
133
|
+
Effect.ensuring(Effect.sync(() => { currentPluginName.contents = before; })),
|
|
134
|
+
);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
123
137
|
return e
|
|
124
138
|
.pipe(
|
|
125
139
|
Effect.provideService(
|
|
@@ -226,3 +226,23 @@ describe("EventCollectorEntryPoint_Ops.parseHandlerConfig", () => {
|
|
|
226
226
|
expect((c.extensions->Array.getUnsafe(0)).extensionPointName)->toBe("Ordering.Orders")
|
|
227
227
|
})
|
|
228
228
|
})
|
|
229
|
+
|
|
230
|
+
describe("EventCollectorEntryPoint_Ops.mappingsName", () => {
|
|
231
|
+
let ext = (~name): EventCollectorEntryPoint_Ops.extensionConfig => {
|
|
232
|
+
name,
|
|
233
|
+
specModule: "",
|
|
234
|
+
mappingsModule: "",
|
|
235
|
+
delegateModule: "",
|
|
236
|
+
extensionPointName: "Ordering.Orders",
|
|
237
|
+
aggregateNames: [],
|
|
238
|
+
}
|
|
239
|
+
// The component is `Extension(<point>.<name>)`: the point is not named twice.
|
|
240
|
+
testSync("is the plugin's name, as at deploy", () =>
|
|
241
|
+
expect(EventCollectorEntryPoint_Ops.mappingsName(ext(~name="Ordering.Orders.Catalog")))->toBe(
|
|
242
|
+
"Catalog",
|
|
243
|
+
)
|
|
244
|
+
)
|
|
245
|
+
testSync("keeps a name that does not start with its extension point", () =>
|
|
246
|
+
expect(EventCollectorEntryPoint_Ops.mappingsName(ext(~name="Catalog")))->toBe("Catalog")
|
|
247
|
+
)
|
|
248
|
+
})
|
|
@@ -315,6 +315,29 @@ globalThis.describe("EventCollectorEntryPoint_Ops.parseHandlerConfig", () => {
|
|
|
315
315
|
});
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
+
globalThis.describe("EventCollectorEntryPoint_Ops.mappingsName", () => {
|
|
319
|
+
globalThis.test("is the plugin's name, as at deploy", () => {
|
|
320
|
+
globalThis.expect(EventCollectorEntryPoint_Ops$ReventlessAws.mappingsName({
|
|
321
|
+
name: "Ordering.Orders.Catalog",
|
|
322
|
+
specModule: "",
|
|
323
|
+
mappingsModule: "",
|
|
324
|
+
delegateModule: "",
|
|
325
|
+
extensionPointName: "Ordering.Orders",
|
|
326
|
+
aggregateNames: []
|
|
327
|
+
})).toBe("Catalog");
|
|
328
|
+
});
|
|
329
|
+
globalThis.test("keeps a name that does not start with its extension point", () => {
|
|
330
|
+
globalThis.expect(EventCollectorEntryPoint_Ops$ReventlessAws.mappingsName({
|
|
331
|
+
name: "Catalog",
|
|
332
|
+
specModule: "",
|
|
333
|
+
mappingsModule: "",
|
|
334
|
+
delegateModule: "",
|
|
335
|
+
extensionPointName: "Ordering.Orders",
|
|
336
|
+
aggregateNames: []
|
|
337
|
+
})).toBe("Catalog");
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
318
341
|
let project = EventCollectorEntryPoint_Ops$ReventlessAws.projectPluginRow;
|
|
319
342
|
|
|
320
343
|
export {
|
|
@@ -200,6 +200,23 @@ describe("entry-point dispatch boundary", () => {
|
|
|
200
200
|
},
|
|
201
201
|
)
|
|
202
202
|
|
|
203
|
+
// A line run on a fiber of its own (`->Effect.runSync`) misses the invocation's annotations,
|
|
204
|
+
// and a Lambda's component→plugin registry is empty: the ambient plugin names it.
|
|
205
|
+
test(
|
|
206
|
+
"a line logged on a fiber of its own names the invocation's plugin",
|
|
207
|
+
async () => {
|
|
208
|
+
let before = Reventless.LogPrefix.currentPluginName.contents
|
|
209
|
+
let seen = await runEffect(
|
|
210
|
+
Effect.sync(
|
|
211
|
+
() => Reventless.LogPrefix.resolvePlugin(~comp="StateChangeSlice(PlaceOrder)", ()),
|
|
212
|
+
),
|
|
213
|
+
{correlationId: "c", comp: "StateChangeSlice(PlaceOrder)", plugin: "Ordering"},
|
|
214
|
+
)
|
|
215
|
+
expect(seen)->Expect.toEqual(Some("Ordering"))
|
|
216
|
+
expect(Reventless.LogPrefix.currentPluginName.contents)->Expect.toEqual(before)
|
|
217
|
+
},
|
|
218
|
+
)
|
|
219
|
+
|
|
203
220
|
// A constant "1" on every line is noise; its absence is what makes
|
|
204
221
|
// `filter retryCount > 1` a usable CloudWatch query.
|
|
205
222
|
test(
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as Effect from "@reventlessdev/rescript-effect/src/Effect.res.mjs";
|
|
4
4
|
import * as Effect$1 from "effect/Effect";
|
|
5
5
|
import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
|
|
6
|
+
import * as LogPrefix$Reventless from "@reventlessdev/reventless-spec/src/LogPrefix.res.mjs";
|
|
6
7
|
import * as RequestContext$ReventlessCore from "@reventlessdev/reventless-core/src/RequestContext.res.mjs";
|
|
7
8
|
import * as HandlerFactoryHelpersMjs from "@reventlessdev/reventless-aws/src/adapter/Runtime/HandlerFactoryHelpers.mjs";
|
|
8
9
|
|
|
@@ -112,6 +113,16 @@ globalThis.describe("entry-point dispatch boundary", () => {
|
|
|
112
113
|
globalThis.expect(annotated$1["correlationId"]).toEqual("corr-1");
|
|
113
114
|
globalThis.expect(annotated$1["requestId"]).toEqual("req-abc");
|
|
114
115
|
});
|
|
116
|
+
globalThis.test("a line logged on a fiber of its own names the invocation's plugin", async () => {
|
|
117
|
+
let before = LogPrefix$Reventless.currentPluginName.contents;
|
|
118
|
+
let seen = await HandlerFactoryHelpersMjs.runEffect(Effect$1.sync(() => LogPrefix$Reventless.resolvePlugin("StateChangeSlice(PlaceOrder)", undefined)), {
|
|
119
|
+
correlationId: "c",
|
|
120
|
+
comp: "StateChangeSlice(PlaceOrder)",
|
|
121
|
+
plugin: "Ordering"
|
|
122
|
+
});
|
|
123
|
+
globalThis.expect(seen).toEqual("Ordering");
|
|
124
|
+
globalThis.expect(LogPrefix$Reventless.currentPluginName.contents).toEqual(before);
|
|
125
|
+
});
|
|
115
126
|
globalThis.test("annotates retryCount only on a redelivery", async () => {
|
|
116
127
|
let first = await HandlerFactoryHelpersMjs.runEffect(Effect$1.logAnnotations, {
|
|
117
128
|
correlationId: "c",
|