@reventlessdev/reventless-core 3.0.0-alpha.174 → 3.0.0-alpha.175
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 +11 -0
- package/package.json +4 -4
- package/src/ComponentType.res +8 -1
- package/src/ComponentType.res.mjs +6 -0
- package/src/RequestContext.res +45 -1
- package/src/RequestContext.res.mjs +12 -2
- package/src/ResourceAttribution.res +133 -0
- package/src/ResourceAttribution.res.mjs +96 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +24 -5
- package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res.mjs +9 -3
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +6 -0
- package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res.mjs +3 -3
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +6 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res.mjs +3 -1
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +25 -7
- package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +11 -8
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +2 -0
- package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res.mjs +1 -1
- package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +4 -0
- package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res.mjs +2 -2
- package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +4 -0
- package/src/adapter/Runtime/PluginRuntime_Builder_Single.res.mjs +2 -2
- package/src/adapter/Runtime/Runtime.res +49 -10
- package/src/adapter/Runtime/Runtime.res.mjs +22 -8
- package/src/admin/Platform_Admin.res +1 -1
- package/src/admin/Platform_Admin.res.mjs +8 -2
- package/src/components/Aggregate/Aggregate_Builder.res +10 -2
- package/src/components/Aggregate/Aggregate_Builder.res.mjs +8 -2
- package/src/components/AutomationSlice/AutomationSlice_Builder.res +12 -2
- package/src/components/AutomationSlice/AutomationSlice_Builder.res.mjs +8 -2
- package/src/components/CommandTopic/CommandTopic.res +5 -1
- package/src/components/CommandTopic/CommandTopic_Adapter.res +1 -0
- package/src/components/CommandTopic/CommandTopic_Builder.res +4 -4
- package/src/components/CommandTopic/CommandTopic_Builder.res.mjs +29 -30
- package/src/components/Counter/Counter_Builder.res +7 -1
- package/src/components/Counter/Counter_Builder.res.mjs +5 -2
- package/src/components/Dcb/Dcb_Builder.res +2 -2
- package/src/components/Dcb/Dcb_Builder.res.mjs +8 -2
- package/src/components/DcbEventLog/DcbEventLog_Builder.res +3 -0
- package/src/components/DcbEventLog/DcbEventLog_Builder.res.mjs +4 -1
- package/src/components/EventCollector/EventCollector.res +1 -0
- package/src/components/EventCollector/EventCollector_Adapter.res +1 -0
- package/src/components/EventCollector/EventCollector_Builder.res +4 -4
- package/src/components/EventCollector/EventCollector_Builder.res.mjs +2 -2
- package/src/components/EventLog/EventLog.res +5 -1
- package/src/components/EventLog/EventLog_Adapter.res +5 -1
- package/src/components/EventLog/EventLog_Builder.res +9 -4
- package/src/components/EventLog/EventLog_Builder.res.mjs +7 -8
- package/src/components/EventMapper/EventMapper_Builder.res +6 -1
- package/src/components/EventMapper/EventMapper_Builder.res.mjs +4 -1
- package/src/components/EventTopic/EventTopic.res +1 -0
- package/src/components/EventTopic/EventTopic_Adapter.res +1 -0
- package/src/components/EventTopic/EventTopic_Builder.res +4 -3
- package/src/components/EventTopic/EventTopic_Builder.res.mjs +2 -2
- package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +11 -2
- package/src/components/ExtensionPoint/ExtensionPoint_Builder.res.mjs +8 -2
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +6 -1
- package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs +4 -1
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +12 -2
- package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs +8 -2
- package/src/components/QueryDb/QueryDb.res +1 -0
- package/src/components/QueryDb/QueryDb_Adapter.res +1 -0
- package/src/components/QueryDb/QueryDb_Builder.res +4 -3
- package/src/components/QueryDb/QueryDb_Builder.res.mjs +2 -2
- package/src/components/ReadModel/ReadModel_Builder.res +12 -2
- package/src/components/ReadModel/ReadModel_Builder.res.mjs +8 -2
- package/src/components/SideEffectHandler/SideEffectHandler_Builder.res +6 -1
- package/src/components/SideEffectHandler/SideEffectHandler_Builder.res.mjs +4 -1
- package/src/components/StateViewSlice/StateViewSlice_Builder.res +12 -2
- package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +8 -2
- package/src/plugin/component/Plugin_Builder.res +6 -0
- package/src/plugin/component/Plugin_Builder.res.mjs +3 -0
- package/src/plugin/component/Plugin_Helpers.res +1 -1
- package/src/plugin/component/Plugin_Helpers.res.mjs +4 -1
- package/tests/ResourceAttributionTest.res +70 -0
- package/tests/aggregate/AggregateCacheTest.res +1 -1
- package/tests/aggregate/AggregateConflictTest.res +1 -1
- package/tests/aggregate/AggregateFixtures.res +1 -1
- package/tests/aggregate/AggregateSnapshotTest.res +1 -1
- package/tests/eventlog/EventLogFixtures.res +1 -1
- package/tests/logger/LogFormatTest.res +43 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
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.175 (2026-07-22)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **aws:** give deployed resources a complete attribution tag schema ([f931a44](https://github.com/ReventlessDev/reventless-core/commit/f931a44ab311a4aff1cd73939b42e7e5221621c9))
|
|
11
|
+
* **aws:** unify the deployed entry-point dispatch boundary; add latency fields ([ad7b3f6](https://github.com/ReventlessDev/reventless-core/commit/ad7b3f60e7b2b2213677732bbf13f486043075ef))
|
|
12
|
+
* **core:** annotate event-collector logs with the element's comp ([eda413a](https://github.com/ReventlessDev/reventless-core/commit/eda413ab00eb8bb02b30e029af2d6221e3e9ba75)), closes [#1](https://github.com/ReventlessDev/reventless-core/issues/1)
|
|
13
|
+
* **core:** attribute piece resources to the component that owns them ([2ddd91a](https://github.com/ReventlessDev/reventless-core/commit/2ddd91ae1a5394257dec4b9b6e5021d5aa6e7f63))
|
|
14
|
+
* **core:** attribute shared substrate to the plugin that owns it ([a440d4f](https://github.com/ReventlessDev/reventless-core/commit/a440d4f827dfab9e2e9a763ffd9fc40240852e09))
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# 3.0.0-alpha.174 (2026-07-21)
|
|
7
18
|
|
|
8
19
|
### Features
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-core",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.175",
|
|
4
4
|
"description": "Core package for Reventless framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"jest": {
|
|
@@ -28,17 +28,17 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"sury": "11.0.0-alpha.4",
|
|
30
30
|
"uuid": "^13.0.0",
|
|
31
|
+
"@reventlessdev/rescript-effect": "0.1.0-alpha.30",
|
|
31
32
|
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.13",
|
|
32
33
|
"@reventlessdev/rescript-fast-csv": "1.2.0-alpha.14",
|
|
33
34
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.9",
|
|
34
35
|
"@reventlessdev/rescript-node-streams": "1.1.0-alpha.13",
|
|
35
|
-
"@reventlessdev/rescript-effect": "0.1.0-alpha.29",
|
|
36
36
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.17",
|
|
37
37
|
"@reventlessdev/rescript-ssh2": "1.1.0-alpha.14",
|
|
38
38
|
"@reventlessdev/rescript-uuid": "1.1.0-alpha.17",
|
|
39
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.
|
|
39
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.103",
|
|
40
40
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.28",
|
|
41
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.
|
|
41
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.80"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"rescript": "12.3.0",
|
package/src/ComponentType.res
CHANGED
|
@@ -2,6 +2,7 @@ type t =
|
|
|
2
2
|
| Aggregate
|
|
3
3
|
| Counter
|
|
4
4
|
| Plugin
|
|
5
|
+
| Platform
|
|
5
6
|
| CommandGenerator
|
|
6
7
|
| CommandTopic
|
|
7
8
|
| EventCollector
|
|
@@ -17,7 +18,10 @@ type t =
|
|
|
17
18
|
| SideEffectHandler
|
|
18
19
|
| Task
|
|
19
20
|
| Vpc
|
|
20
|
-
|
|
|
21
|
+
| /** Vestigial: predates the platform/plugin split and names nothing the
|
|
22
|
+
framework builds. Do not reach for it — platform-level things are
|
|
23
|
+
`Platform`, and the built-in core PLUGIN is a `Plugin`. */
|
|
24
|
+
Core
|
|
21
25
|
| Heartbeat
|
|
22
26
|
| Cloner
|
|
23
27
|
| DcbEventLog
|
|
@@ -32,6 +36,7 @@ let toString = componentType =>
|
|
|
32
36
|
| Aggregate => "Aggregate"
|
|
33
37
|
| Counter => "Counter"
|
|
34
38
|
| Plugin => "Plugin"
|
|
39
|
+
| Platform => "Platform"
|
|
35
40
|
| CommandGenerator => "CommandGenerator"
|
|
36
41
|
| CommandTopic => "CommandTopic"
|
|
37
42
|
| EventCollector => "EventCollector"
|
|
@@ -63,6 +68,7 @@ let ofString = str =>
|
|
|
63
68
|
| "Aggregate" => Aggregate->Some
|
|
64
69
|
| "Counter" => Counter->Some
|
|
65
70
|
| "Plugin" => Plugin->Some
|
|
71
|
+
| "Platform" => Platform->Some
|
|
66
72
|
| "CommandGenerator" => CommandGenerator->Some
|
|
67
73
|
| "CommandTopic" => CommandTopic->Some
|
|
68
74
|
| "EventCollector" => EventCollector->Some
|
|
@@ -95,6 +101,7 @@ let toName = componentType =>
|
|
|
95
101
|
| Aggregate => "Aggr"
|
|
96
102
|
| Counter => "Counter"
|
|
97
103
|
| Plugin => "Plugin"
|
|
104
|
+
| Platform => "Platform"
|
|
98
105
|
| CommandGenerator => "CmdGen"
|
|
99
106
|
| CommandTopic => "CmdTopic"
|
|
100
107
|
| EventCollector => "EventColl"
|
|
@@ -10,6 +10,8 @@ function toString(componentType) {
|
|
|
10
10
|
return "Counter";
|
|
11
11
|
case "Plugin" :
|
|
12
12
|
return "Plugin";
|
|
13
|
+
case "Platform" :
|
|
14
|
+
return "Platform";
|
|
13
15
|
case "CommandGenerator" :
|
|
14
16
|
return "CommandGenerator";
|
|
15
17
|
case "CommandTopic" :
|
|
@@ -97,6 +99,8 @@ function ofString(str) {
|
|
|
97
99
|
return "InboundTranslationSlice";
|
|
98
100
|
case "OutboundTranslationSlice" :
|
|
99
101
|
return "OutboundTranslationSlice";
|
|
102
|
+
case "Platform" :
|
|
103
|
+
return "Platform";
|
|
100
104
|
case "Plugin" :
|
|
101
105
|
return "Plugin";
|
|
102
106
|
case "QueryDB" :
|
|
@@ -130,6 +134,8 @@ function toName(componentType) {
|
|
|
130
134
|
return "Counter";
|
|
131
135
|
case "Plugin" :
|
|
132
136
|
return "Plugin";
|
|
137
|
+
case "Platform" :
|
|
138
|
+
return "Platform";
|
|
133
139
|
case "CommandGenerator" :
|
|
134
140
|
return "CmdGen";
|
|
135
141
|
case "CommandTopic" :
|
package/src/RequestContext.res
CHANGED
|
@@ -19,13 +19,24 @@
|
|
|
19
19
|
// causal chain within one `correlationId`. `component` / `pluginName` identify the
|
|
20
20
|
// component and plugin handling the invocation — mirror the `comp` / `plugin` log
|
|
21
21
|
// fields so a consumer of this service sees the same attribution the logs carry.
|
|
22
|
-
//
|
|
22
|
+
//
|
|
23
|
+
// `timestamp` = when the triggering message was *sent* (ms since epoch), not when
|
|
24
|
+
// this handler started: SQS `SentTimestamp`, a DynamoDB stream record's
|
|
25
|
+
// `ApproximateCreationDateTime`, or dispatch time in-process. A handler computes
|
|
26
|
+
// end-to-end latency from it without calling `Date.now()` itself, and the value
|
|
27
|
+
// includes queue dwell — which a handler-local clock cannot see.
|
|
28
|
+
// `retryCount` = delivery attempt, 1 on first delivery (SQS
|
|
29
|
+
// `ApproximateReceiveCount`; always 1 where the transport has no redelivery).
|
|
30
|
+
//
|
|
31
|
+
// All optional fields are absent in `.test()` and wherever the dispatch site has
|
|
23
32
|
// no value to supply.
|
|
24
33
|
type t = {
|
|
25
34
|
correlationId: string,
|
|
26
35
|
causationId?: string,
|
|
27
36
|
component?: string,
|
|
28
37
|
pluginName?: string,
|
|
38
|
+
timestamp?: float,
|
|
39
|
+
retryCount?: int,
|
|
29
40
|
identity: Reventless.Identity.t,
|
|
30
41
|
claims: dict<string>,
|
|
31
42
|
}
|
|
@@ -39,6 +50,8 @@ let make = (
|
|
|
39
50
|
~causationId=?,
|
|
40
51
|
~component=?,
|
|
41
52
|
~pluginName=?,
|
|
53
|
+
~timestamp=?,
|
|
54
|
+
~retryCount=?,
|
|
42
55
|
~identity=Reventless.Identity.anonymous,
|
|
43
56
|
~claims=Dict.make(),
|
|
44
57
|
): t => {
|
|
@@ -46,10 +59,37 @@ let make = (
|
|
|
46
59
|
causationId: ?causationId,
|
|
47
60
|
component: ?component,
|
|
48
61
|
pluginName: ?pluginName,
|
|
62
|
+
timestamp: ?timestamp,
|
|
63
|
+
retryCount: ?retryCount,
|
|
49
64
|
identity,
|
|
50
65
|
claims,
|
|
51
66
|
}
|
|
52
67
|
|
|
68
|
+
// JS-facing constructor for the hand-written Lambda entry-point shells
|
|
69
|
+
// (HandlerFactoryHelpers.mjs). `make`'s labelled arguments compile to *positional*
|
|
70
|
+
// ones, so a JS caller breaks silently the moment an argument is inserted; this
|
|
71
|
+
// takes a single options object whose field names survive compilation and stay
|
|
72
|
+
// compiler-checked here. Every field is optional so a shell can supply only what
|
|
73
|
+
// its transport actually carries.
|
|
74
|
+
type options = {
|
|
75
|
+
correlationId?: string,
|
|
76
|
+
causationId?: string,
|
|
77
|
+
component?: string,
|
|
78
|
+
pluginName?: string,
|
|
79
|
+
timestamp?: float,
|
|
80
|
+
retryCount?: int,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let fromOptions = (o: options): t =>
|
|
84
|
+
make(
|
|
85
|
+
~correlationId=o.correlationId->Option.getOr("unknown"),
|
|
86
|
+
~causationId=?o.causationId,
|
|
87
|
+
~component=?o.component,
|
|
88
|
+
~pluginName=?o.pluginName,
|
|
89
|
+
~timestamp=?o.timestamp,
|
|
90
|
+
~retryCount=?o.retryCount,
|
|
91
|
+
)
|
|
92
|
+
|
|
53
93
|
let getClaim = (ctx: t, key: string): option<string> =>
|
|
54
94
|
ctx.claims->Dict.get(key)
|
|
55
95
|
|
|
@@ -61,10 +101,14 @@ let withClaim = (ctx: t, key: string, value: string): t => {
|
|
|
61
101
|
|
|
62
102
|
let test = (
|
|
63
103
|
~correlationId="test-correlation-id",
|
|
104
|
+
~timestamp=?,
|
|
105
|
+
~retryCount=?,
|
|
64
106
|
~identity=Reventless.Identity.anonymous,
|
|
65
107
|
~claims=Dict.make(),
|
|
66
108
|
): t => {
|
|
67
109
|
correlationId,
|
|
110
|
+
timestamp: ?timestamp,
|
|
111
|
+
retryCount: ?retryCount,
|
|
68
112
|
identity,
|
|
69
113
|
claims,
|
|
70
114
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
3
4
|
import * as Context from "effect/Context";
|
|
4
5
|
import * as Identity$Reventless from "@reventlessdev/reventless-spec/src/types/Identity.res.mjs";
|
|
5
6
|
|
|
6
7
|
let tag = Context.GenericTag("reventless/RequestContext");
|
|
7
8
|
|
|
8
|
-
function make(correlationId, causationId, component, pluginName, identityOpt, claimsOpt) {
|
|
9
|
+
function make(correlationId, causationId, component, pluginName, timestamp, retryCount, identityOpt, claimsOpt) {
|
|
9
10
|
let identity = identityOpt !== undefined ? identityOpt : Identity$Reventless.anonymous;
|
|
10
11
|
let claims = claimsOpt !== undefined ? claimsOpt : ({});
|
|
11
12
|
return {
|
|
@@ -13,11 +14,17 @@ function make(correlationId, causationId, component, pluginName, identityOpt, cl
|
|
|
13
14
|
causationId: causationId,
|
|
14
15
|
component: component,
|
|
15
16
|
pluginName: pluginName,
|
|
17
|
+
timestamp: timestamp,
|
|
18
|
+
retryCount: retryCount,
|
|
16
19
|
identity: identity,
|
|
17
20
|
claims: claims
|
|
18
21
|
};
|
|
19
22
|
}
|
|
20
23
|
|
|
24
|
+
function fromOptions(o) {
|
|
25
|
+
return make(Stdlib_Option.getOr(o.correlationId, "unknown"), o.causationId, o.component, o.pluginName, o.timestamp, o.retryCount, undefined, undefined);
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
function getClaim(ctx, key) {
|
|
22
29
|
return ctx.claims[key];
|
|
23
30
|
}
|
|
@@ -30,12 +37,14 @@ function withClaim(ctx, key, value) {
|
|
|
30
37
|
return newrecord;
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
function test(correlationIdOpt, identityOpt, claimsOpt) {
|
|
40
|
+
function test(correlationIdOpt, timestamp, retryCount, identityOpt, claimsOpt) {
|
|
34
41
|
let correlationId = correlationIdOpt !== undefined ? correlationIdOpt : "test-correlation-id";
|
|
35
42
|
let identity = identityOpt !== undefined ? identityOpt : Identity$Reventless.anonymous;
|
|
36
43
|
let claims = claimsOpt !== undefined ? claimsOpt : ({});
|
|
37
44
|
return {
|
|
38
45
|
correlationId: correlationId,
|
|
46
|
+
timestamp: timestamp,
|
|
47
|
+
retryCount: retryCount,
|
|
39
48
|
identity: identity,
|
|
40
49
|
claims: claims
|
|
41
50
|
};
|
|
@@ -44,6 +53,7 @@ function test(correlationIdOpt, identityOpt, claimsOpt) {
|
|
|
44
53
|
export {
|
|
45
54
|
tag,
|
|
46
55
|
make,
|
|
56
|
+
fromOptions,
|
|
47
57
|
getClaim,
|
|
48
58
|
withClaim,
|
|
49
59
|
test,
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/***
|
|
2
|
+
The vocabulary a deployed resource is attributed with: which model element owns
|
|
3
|
+
it, in what role, at what level. Provider-agnostic on purpose — AWS renders these
|
|
4
|
+
as namespaced `reventless:` tags, Kubernetes as `reventless.io` labels. Defining
|
|
5
|
+
them once here is what keeps the two backends (and the monitoring registry) from
|
|
6
|
+
drifting into private spellings of the same fact.
|
|
7
|
+
|
|
8
|
+
The three facts are deliberately independent:
|
|
9
|
+
|
|
10
|
+
- `ComponentType.t` — the *modelling* kind (Aggregate, StateViewSlice, …): what
|
|
11
|
+
the element IS in the domain model.
|
|
12
|
+
- `Role.t` — the *deployment piece* (EventLog, QueryDb, Runtime, …): what job
|
|
13
|
+
this particular resource does for that element. One component owns several
|
|
14
|
+
pieces, so kind alone can't identify a resource.
|
|
15
|
+
- `Scope.t` — the level the resource is attributed to: an individual component,
|
|
16
|
+
a plugin's shared substrate, or platform substrate.
|
|
17
|
+
|
|
18
|
+
Note this is NOT the same axis as `Monitoring.unitKind`, which classifies an
|
|
19
|
+
execution unit by what its *failure* means (CommandHandler / Projection /
|
|
20
|
+
Reactor). A `Runtime` role can be any of those; both facts are worth carrying and
|
|
21
|
+
neither derives from the other.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** The level a resource is attributed to. */
|
|
25
|
+
module Scope = {
|
|
26
|
+
type t =
|
|
27
|
+
| /** owned by one model component */ Component
|
|
28
|
+
| /** shared substrate within a plugin (DcbEventLog, plugin DLQ, …) */ Plugin
|
|
29
|
+
| /** shared substrate across the platform (API, auth, hosting, …) */ Platform
|
|
30
|
+
|
|
31
|
+
let toString = scope =>
|
|
32
|
+
switch scope {
|
|
33
|
+
| Component => "component"
|
|
34
|
+
| Plugin => "plugin"
|
|
35
|
+
| Platform => "platform"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
The deployment piece a resource implements. `Other(string)` is the escape hatch
|
|
41
|
+
for support pieces and future roles (same pattern as `Monitoring.unitKind`).
|
|
42
|
+
*/
|
|
43
|
+
module Role = {
|
|
44
|
+
type t =
|
|
45
|
+
| CommandTopic
|
|
46
|
+
| EventTopic
|
|
47
|
+
| StateTopic
|
|
48
|
+
| EventLog
|
|
49
|
+
| DcbEventLog
|
|
50
|
+
| EventLogSubscription
|
|
51
|
+
| EventCollector
|
|
52
|
+
| QueryDb
|
|
53
|
+
| /** the execution unit that runs a component's handler */ Runtime
|
|
54
|
+
| /** queue/topic receiving messages that exhausted processing */ DeadLetter
|
|
55
|
+
| /** scheduled invocation (heartbeat, task scheduler) */ Scheduler
|
|
56
|
+
| /** log storage and log-derived metrics */ Logs
|
|
57
|
+
| /** execution identity and its policies */ Identity
|
|
58
|
+
| /** the GraphQL API surface and its resolvers */ Api
|
|
59
|
+
| /** identity provider / user pools */ Auth
|
|
60
|
+
| /** static-site hosting, CDN, certificates, DNS */ Hosting
|
|
61
|
+
| /** VPC and its network plumbing */ Network
|
|
62
|
+
| /** transport wiring between a source and a runtime */ EventSourceMapping
|
|
63
|
+
| /** bulk data movement (cloner, migrations) */ DataTransfer
|
|
64
|
+
| Other(string)
|
|
65
|
+
|
|
66
|
+
let toString = role =>
|
|
67
|
+
switch role {
|
|
68
|
+
| CommandTopic => "CommandTopic"
|
|
69
|
+
| EventTopic => "EventTopic"
|
|
70
|
+
| StateTopic => "StateTopic"
|
|
71
|
+
| EventLog => "EventLog"
|
|
72
|
+
| DcbEventLog => "DcbEventLog"
|
|
73
|
+
| EventLogSubscription => "EventLogSubscription"
|
|
74
|
+
| EventCollector => "EventCollector"
|
|
75
|
+
| QueryDb => "QueryDb"
|
|
76
|
+
| Runtime => "Runtime"
|
|
77
|
+
| DeadLetter => "DeadLetter"
|
|
78
|
+
| Scheduler => "Scheduler"
|
|
79
|
+
| Logs => "Logs"
|
|
80
|
+
| Identity => "Identity"
|
|
81
|
+
| Api => "Api"
|
|
82
|
+
| Auth => "Auth"
|
|
83
|
+
| Hosting => "Hosting"
|
|
84
|
+
| Network => "Network"
|
|
85
|
+
| EventSourceMapping => "EventSourceMapping"
|
|
86
|
+
| DataTransfer => "DataTransfer"
|
|
87
|
+
| Other(name) => name
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
The model component a provisioned resource belongs to.
|
|
93
|
+
|
|
94
|
+
Piece builders (EventLog, QueryDb, CommandTopic, EventTopic, EventCollector) are
|
|
95
|
+
shared building blocks applied as functors by many different component kinds — a
|
|
96
|
+
QueryDb is instantiated by ReadModel, StateViewSlice, AutomationSlice, both
|
|
97
|
+
translation slices and Counter. The adapter that provisions the physical resource
|
|
98
|
+
sits at the bottom of that chain and would otherwise only know its own piece, so
|
|
99
|
+
`kind` would collapse onto `role` and the owning component would be unrecoverable.
|
|
100
|
+
The owning builder passes this record down instead.
|
|
101
|
+
|
|
102
|
+
`name` is the owner's spec name (the component stem, `Products`), not the
|
|
103
|
+
suffixed resource name (`ProductsQueryDb`).
|
|
104
|
+
*/
|
|
105
|
+
type owner = {kind: ComponentType.t, name: string}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
Ambient deploy-time context: which plugin (and platform) is currently being
|
|
109
|
+
constructed. Adapters that create resources sit far below the builder that knows
|
|
110
|
+
these names, and threading two strings through every adapter signature would be a
|
|
111
|
+
large, purely mechanical churn — so the plugin builder publishes them here for
|
|
112
|
+
the duration of its construct, exactly as it already does for
|
|
113
|
+
`Logger.currentPluginName`.
|
|
114
|
+
|
|
115
|
+
Safe because deploy-time resource construction is synchronous (the framework
|
|
116
|
+
forbids creating resources inside `Pulumi.Output.apply`), so everything built
|
|
117
|
+
between `enter` and `restore` genuinely belongs to that plugin. Outside any
|
|
118
|
+
plugin construct both are `None` — which is the correct answer for
|
|
119
|
+
platform-scope substrate.
|
|
120
|
+
*/
|
|
121
|
+
type context = {platform: option<string>, plugin: option<string>}
|
|
122
|
+
|
|
123
|
+
let current: ref<context> = ref({platform: None, plugin: None})
|
|
124
|
+
|
|
125
|
+
/** Publish the plugin being constructed; returns the previous context to restore. */
|
|
126
|
+
let enter = (~platform: string, ~plugin: string) => {
|
|
127
|
+
let previous = current.contents
|
|
128
|
+
current := {platform: Some(platform), plugin: Some(plugin)}
|
|
129
|
+
previous
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Restore the context captured by `enter`. */
|
|
133
|
+
let restore = (previous: context) => current := previous
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function toString(scope) {
|
|
5
|
+
switch (scope) {
|
|
6
|
+
case "Component" :
|
|
7
|
+
return "component";
|
|
8
|
+
case "Plugin" :
|
|
9
|
+
return "plugin";
|
|
10
|
+
case "Platform" :
|
|
11
|
+
return "platform";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let Scope = {
|
|
16
|
+
toString: toString
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function toString$1(role) {
|
|
20
|
+
if (typeof role === "object") {
|
|
21
|
+
return role._0;
|
|
22
|
+
}
|
|
23
|
+
switch (role) {
|
|
24
|
+
case "CommandTopic" :
|
|
25
|
+
return "CommandTopic";
|
|
26
|
+
case "EventTopic" :
|
|
27
|
+
return "EventTopic";
|
|
28
|
+
case "StateTopic" :
|
|
29
|
+
return "StateTopic";
|
|
30
|
+
case "EventLog" :
|
|
31
|
+
return "EventLog";
|
|
32
|
+
case "DcbEventLog" :
|
|
33
|
+
return "DcbEventLog";
|
|
34
|
+
case "EventLogSubscription" :
|
|
35
|
+
return "EventLogSubscription";
|
|
36
|
+
case "EventCollector" :
|
|
37
|
+
return "EventCollector";
|
|
38
|
+
case "QueryDb" :
|
|
39
|
+
return "QueryDb";
|
|
40
|
+
case "Runtime" :
|
|
41
|
+
return "Runtime";
|
|
42
|
+
case "DeadLetter" :
|
|
43
|
+
return "DeadLetter";
|
|
44
|
+
case "Scheduler" :
|
|
45
|
+
return "Scheduler";
|
|
46
|
+
case "Logs" :
|
|
47
|
+
return "Logs";
|
|
48
|
+
case "Identity" :
|
|
49
|
+
return "Identity";
|
|
50
|
+
case "Api" :
|
|
51
|
+
return "Api";
|
|
52
|
+
case "Auth" :
|
|
53
|
+
return "Auth";
|
|
54
|
+
case "Hosting" :
|
|
55
|
+
return "Hosting";
|
|
56
|
+
case "Network" :
|
|
57
|
+
return "Network";
|
|
58
|
+
case "EventSourceMapping" :
|
|
59
|
+
return "EventSourceMapping";
|
|
60
|
+
case "DataTransfer" :
|
|
61
|
+
return "DataTransfer";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let Role = {
|
|
66
|
+
toString: toString$1
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
let current = {
|
|
70
|
+
contents: {
|
|
71
|
+
platform: undefined,
|
|
72
|
+
plugin: undefined
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
function enter(platform, plugin) {
|
|
77
|
+
let previous = current.contents;
|
|
78
|
+
current.contents = {
|
|
79
|
+
platform: platform,
|
|
80
|
+
plugin: plugin
|
|
81
|
+
};
|
|
82
|
+
return previous;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function restore(previous) {
|
|
86
|
+
current.contents = previous;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
Scope,
|
|
91
|
+
Role,
|
|
92
|
+
current,
|
|
93
|
+
enter,
|
|
94
|
+
restore,
|
|
95
|
+
}
|
|
96
|
+
/* No side effect */
|
|
@@ -26,20 +26,29 @@ module Make = (
|
|
|
26
26
|
}
|
|
27
27
|
type effectHandler = Runtime.effectHandler<RuntimeEnvironment.event, context, unit, string>
|
|
28
28
|
|
|
29
|
+
// Event collectors nested under this aggregate belong to their own element (a
|
|
30
|
+
// ReadModel, an EventMapper, …), so they carry the comp resolved at registration
|
|
31
|
+
// time rather than the hosting aggregate's.
|
|
32
|
+
type registeredHandler = {comp: string, handler: effectHandler}
|
|
33
|
+
|
|
29
34
|
let runtimeSpecs: dict<runtimeSpec> = Dict.make()
|
|
30
35
|
let commandGeneratorHandlers: dict<CommandGenerator.effectEventHandler<context>> = Dict.make()
|
|
31
36
|
let commandTopicHandlers: dict<effectHandler> = Dict.make()
|
|
32
|
-
let eventCollectorHandlers: dict<array<
|
|
37
|
+
let eventCollectorHandlers: dict<array<registeredHandler>> = Dict.make()
|
|
33
38
|
|
|
34
39
|
let aggregateHandler = aggregateName =>
|
|
35
40
|
async (event: RuntimeEnvironment.event, context) => {
|
|
36
41
|
let correlationId = event->RuntimeEnvironment.extractCorrelationId
|
|
37
42
|
let causationId = event->RuntimeEnvironment.extractCausationId
|
|
43
|
+
let timestamp = event->RuntimeEnvironment.extractSentTimestamp
|
|
44
|
+
let retryCount = event->RuntimeEnvironment.extractRetryCount
|
|
38
45
|
let comp = `AggregateRuntime(${aggregateName})`
|
|
39
46
|
// Shared dispatch helper (Runtime.runEffect) annotates correlationId / comp /
|
|
40
47
|
// causationId onto the invocation so the application handler's own log lines
|
|
41
|
-
// carry them without re-logging by hand
|
|
42
|
-
|
|
48
|
+
// carry them without re-logging by hand, and carries the transport's send
|
|
49
|
+
// time / delivery attempt into RequestContext.
|
|
50
|
+
let runEffect = effect =>
|
|
51
|
+
Runtime.runEffect(~correlationId?, ~causationId?, ~comp, ~timestamp?, ~retryCount?, effect)
|
|
43
52
|
switch event->CommandGenerator.metaInfo {
|
|
44
53
|
| Some(info) =>
|
|
45
54
|
switch commandGeneratorHandlers->Dict.get(info) {
|
|
@@ -71,7 +80,16 @@ module Make = (
|
|
|
71
80
|
`found ${count} EventCollector handler(s) for ${urn}`,
|
|
72
81
|
)->Effect.runSync
|
|
73
82
|
let _ = await handlers
|
|
74
|
-
->Array.map(
|
|
83
|
+
->Array.map(({comp, handler}) =>
|
|
84
|
+
Runtime.runEffect(
|
|
85
|
+
~correlationId?,
|
|
86
|
+
~causationId?,
|
|
87
|
+
~comp,
|
|
88
|
+
~timestamp?,
|
|
89
|
+
~retryCount?,
|
|
90
|
+
handler(event, context),
|
|
91
|
+
)
|
|
92
|
+
)
|
|
75
93
|
->Promise.all
|
|
76
94
|
| None =>
|
|
77
95
|
let available =
|
|
@@ -237,11 +255,12 @@ module Make = (
|
|
|
237
255
|
~comp="AggregateRuntime",
|
|
238
256
|
`forEventCollector ${eventCollectorName}: set handler for ${urns->Array.join(", ")}`,
|
|
239
257
|
)
|
|
258
|
+
let comp = `EventCollector(${eventCollectorName})`
|
|
240
259
|
urns->Array.map(urn => {
|
|
241
260
|
let handlers = eventCollectorHandlers->Dict.get(urn)->Option.getOr([])
|
|
242
261
|
eventCollectorHandlers->Dict.set(
|
|
243
262
|
urn,
|
|
244
|
-
handlers->Array.concat([handler->RuntimeEnvironment.asEffectHandler]),
|
|
263
|
+
handlers->Array.concat([{comp, handler: handler->RuntimeEnvironment.asEffectHandler}]),
|
|
245
264
|
)
|
|
246
265
|
})
|
|
247
266
|
})
|
|
@@ -21,8 +21,10 @@ function Make(RuntimeEnvironment) {
|
|
|
21
21
|
let aggregateHandler = aggregateName => (async (event, context) => {
|
|
22
22
|
let correlationId = RuntimeEnvironment.extractCorrelationId(event);
|
|
23
23
|
let causationId = RuntimeEnvironment.extractCausationId(event);
|
|
24
|
+
let timestamp = RuntimeEnvironment.extractSentTimestamp(event);
|
|
25
|
+
let retryCount = RuntimeEnvironment.extractRetryCount(event);
|
|
24
26
|
let comp = `AggregateRuntime(` + aggregateName + `)`;
|
|
25
|
-
let runEffect = effect => Runtime$ReventlessCore.runEffect(correlationId, causationId, comp, undefined, undefined, undefined, effect);
|
|
27
|
+
let runEffect = effect => Runtime$ReventlessCore.runEffect(correlationId, causationId, comp, undefined, timestamp, retryCount, undefined, undefined, effect);
|
|
26
28
|
let info = CommandGenerator$ReventlessCore.metaInfo(event);
|
|
27
29
|
if (info !== undefined) {
|
|
28
30
|
let handler = commandGeneratorHandlers[info];
|
|
@@ -46,7 +48,7 @@ function Make(RuntimeEnvironment) {
|
|
|
46
48
|
if (handlers !== undefined) {
|
|
47
49
|
let count = handlers.length.toString();
|
|
48
50
|
Effect.runSync(EffectLogger$ReventlessCore.logDebug(comp, undefined, `found ` + count + ` EventCollector handler(s) for ` + urn));
|
|
49
|
-
await Promise.all(handlers.map(
|
|
51
|
+
await Promise.all(handlers.map(param => Runtime$ReventlessCore.runEffect(correlationId, causationId, param.comp, undefined, timestamp, retryCount, undefined, undefined, param.handler(event, context))));
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
let available = Object.keys(commandTopicHandlers).concat(Object.keys(eventCollectorHandlers)).join(",");
|
|
@@ -155,9 +157,13 @@ function Make(RuntimeEnvironment) {
|
|
|
155
157
|
let handler = param[1];
|
|
156
158
|
let urns = param[0];
|
|
157
159
|
log.debug("AggregateRuntime", undefined, `forEventCollector ` + eventCollectorName + `: set handler for ` + urns.join(", "));
|
|
160
|
+
let comp = `EventCollector(` + eventCollectorName + `)`;
|
|
158
161
|
return urns.map(urn => {
|
|
159
162
|
let handlers = Stdlib_Option.getOr(eventCollectorHandlers[urn], []);
|
|
160
|
-
eventCollectorHandlers[urn] = handlers.concat([
|
|
163
|
+
eventCollectorHandlers[urn] = handlers.concat([{
|
|
164
|
+
comp: comp,
|
|
165
|
+
handler: RuntimeEnvironment.asEffectHandler(handler)
|
|
166
|
+
}]);
|
|
161
167
|
});
|
|
162
168
|
});
|
|
163
169
|
};
|
|
@@ -32,6 +32,8 @@ module Make = (
|
|
|
32
32
|
->Runtime.runEffectHandler(
|
|
33
33
|
~extractCorrelationId=RuntimeEnvironment.extractCorrelationId,
|
|
34
34
|
~extractCausationId=RuntimeEnvironment.extractCausationId,
|
|
35
|
+
~extractSentTimestamp=RuntimeEnvironment.extractSentTimestamp,
|
|
36
|
+
~extractRetryCount=RuntimeEnvironment.extractRetryCount,
|
|
35
37
|
~comp=name,
|
|
36
38
|
)
|
|
37
39
|
),
|
|
@@ -60,6 +62,8 @@ module Make = (
|
|
|
60
62
|
->Runtime.runEffectHandler(
|
|
61
63
|
~extractCorrelationId=RuntimeEnvironment.extractCorrelationId,
|
|
62
64
|
~extractCausationId=RuntimeEnvironment.extractCausationId,
|
|
65
|
+
~extractSentTimestamp=RuntimeEnvironment.extractSentTimestamp,
|
|
66
|
+
~extractRetryCount=RuntimeEnvironment.extractRetryCount,
|
|
63
67
|
~comp=name,
|
|
64
68
|
)
|
|
65
69
|
),
|
|
@@ -91,6 +95,8 @@ module Make = (
|
|
|
91
95
|
->Runtime.runEffectHandler(
|
|
92
96
|
~extractCorrelationId=RuntimeEnvironment.extractCorrelationId,
|
|
93
97
|
~extractCausationId=RuntimeEnvironment.extractCausationId,
|
|
98
|
+
~extractSentTimestamp=RuntimeEnvironment.extractSentTimestamp,
|
|
99
|
+
~extractRetryCount=RuntimeEnvironment.extractRetryCount,
|
|
94
100
|
~comp=name,
|
|
95
101
|
)
|
|
96
102
|
),
|
|
@@ -14,7 +14,7 @@ function Make(RuntimeEnvironment) {
|
|
|
14
14
|
let timeout = timeoutOpt !== undefined ? timeoutOpt : 30;
|
|
15
15
|
let resource = Component$ReventlessCore.toPulumiResource(commandGenerator);
|
|
16
16
|
let name = ComponentType$ReventlessCore.nameOpt(resource.__name, CommandGenerator$ReventlessCore.componentType);
|
|
17
|
-
return connect(RuntimeEnvironment.make(name, handler.apply(handler => Runtime$ReventlessCore.runEffectHandler(RuntimeEnvironment.extractCorrelationId, RuntimeEnvironment.extractCausationId, name, undefined, RuntimeEnvironment.asEffectHandler(handler))), memorySize, timeout, {
|
|
17
|
+
return connect(RuntimeEnvironment.make(name, handler.apply(handler => Runtime$ReventlessCore.runEffectHandler(RuntimeEnvironment.extractCorrelationId, RuntimeEnvironment.extractCausationId, RuntimeEnvironment.extractSentTimestamp, RuntimeEnvironment.extractRetryCount, name, undefined, RuntimeEnvironment.asEffectHandler(handler))), memorySize, timeout, {
|
|
18
18
|
parent: resource
|
|
19
19
|
}));
|
|
20
20
|
};
|
|
@@ -23,7 +23,7 @@ function Make(RuntimeEnvironment) {
|
|
|
23
23
|
let timeout = timeoutOpt !== undefined ? timeoutOpt : 30;
|
|
24
24
|
let resource = Component$ReventlessCore.toPulumiResource(commandTopic);
|
|
25
25
|
let name = ComponentType$ReventlessCore.nameOpt(resource.__name, CommandTopic$ReventlessCore.componentType);
|
|
26
|
-
return connect(RuntimeEnvironment.make(name, handler.apply(handler => Runtime$ReventlessCore.runEffectHandler(RuntimeEnvironment.extractCorrelationId, RuntimeEnvironment.extractCausationId, name, undefined, RuntimeEnvironment.asEffectHandler(handler))), memorySize, timeout, {
|
|
26
|
+
return connect(RuntimeEnvironment.make(name, handler.apply(handler => Runtime$ReventlessCore.runEffectHandler(RuntimeEnvironment.extractCorrelationId, RuntimeEnvironment.extractCausationId, RuntimeEnvironment.extractSentTimestamp, RuntimeEnvironment.extractRetryCount, name, undefined, RuntimeEnvironment.asEffectHandler(handler))), memorySize, timeout, {
|
|
27
27
|
parent: resource
|
|
28
28
|
}));
|
|
29
29
|
};
|
|
@@ -36,7 +36,7 @@ function Make(RuntimeEnvironment) {
|
|
|
36
36
|
let opts = {
|
|
37
37
|
parent: opts_parent
|
|
38
38
|
};
|
|
39
|
-
let runtime = RuntimeEnvironment.make(name, handler.apply(handler => Runtime$ReventlessCore.runEffectHandler(RuntimeEnvironment.extractCorrelationId, RuntimeEnvironment.extractCausationId, name, undefined, RuntimeEnvironment.asEffectHandler(handler))), memorySize, timeout, opts);
|
|
39
|
+
let runtime = RuntimeEnvironment.make(name, handler.apply(handler => Runtime$ReventlessCore.runEffectHandler(RuntimeEnvironment.extractCorrelationId, RuntimeEnvironment.extractCausationId, RuntimeEnvironment.extractSentTimestamp, RuntimeEnvironment.extractRetryCount, name, undefined, RuntimeEnvironment.asEffectHandler(handler))), memorySize, timeout, opts);
|
|
40
40
|
EventCollectorChannel.connect(name, [{
|
|
41
41
|
channel: eventCollector.channel,
|
|
42
42
|
eventTopics: eventTopics,
|
|
@@ -22,6 +22,9 @@ module Make = (
|
|
|
22
22
|
) => {
|
|
23
23
|
let resource = eventCollector->Component.toPulumiResource
|
|
24
24
|
let name = resource.name->ComponentType.nameOpt(EventCollector.componentType)
|
|
25
|
+
// Same `comp` shape as the shared-runtime dispatchers, so a log filter reads the
|
|
26
|
+
// same whichever deployment strategy hosts the collector.
|
|
27
|
+
let comp = `EventCollector(${resource.name->Option.getOr("Unnamed")})`
|
|
25
28
|
let opts = {Pulumi.ComponentResource.parent: resource}
|
|
26
29
|
let runtime = RuntimeEnvironment.make(
|
|
27
30
|
~name,
|
|
@@ -31,7 +34,9 @@ module Make = (
|
|
|
31
34
|
->Runtime.runEffectHandler(
|
|
32
35
|
~extractCorrelationId=RuntimeEnvironment.extractCorrelationId,
|
|
33
36
|
~extractCausationId=RuntimeEnvironment.extractCausationId,
|
|
34
|
-
~
|
|
37
|
+
~extractSentTimestamp=RuntimeEnvironment.extractSentTimestamp,
|
|
38
|
+
~extractRetryCount=RuntimeEnvironment.extractRetryCount,
|
|
39
|
+
~comp,
|
|
35
40
|
)
|
|
36
41
|
),
|
|
37
42
|
~memorySize,
|