@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.
Files changed (81) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/package.json +4 -4
  3. package/src/ComponentType.res +8 -1
  4. package/src/ComponentType.res.mjs +6 -0
  5. package/src/RequestContext.res +45 -1
  6. package/src/RequestContext.res.mjs +12 -2
  7. package/src/ResourceAttribution.res +133 -0
  8. package/src/ResourceAttribution.res.mjs +96 -0
  9. package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res +24 -5
  10. package/src/adapter/Runtime/AggregateRuntime_Builder_Common.res.mjs +9 -3
  11. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res +6 -0
  12. package/src/adapter/Runtime/AggregateRuntime_Builder_Micro.res.mjs +3 -3
  13. package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res +6 -1
  14. package/src/adapter/Runtime/EventCollectorRuntime_Builder_PerEventCollector.res.mjs +3 -1
  15. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res +25 -7
  16. package/src/adapter/Runtime/EventCollectorRuntime_Builder_Single.res.mjs +11 -8
  17. package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res +2 -0
  18. package/src/adapter/Runtime/ExtensionPointRuntime_Builder_PerExtensionPoint.res.mjs +1 -1
  19. package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res +4 -0
  20. package/src/adapter/Runtime/PluginRuntime_Builder_Micro.res.mjs +2 -2
  21. package/src/adapter/Runtime/PluginRuntime_Builder_Single.res +4 -0
  22. package/src/adapter/Runtime/PluginRuntime_Builder_Single.res.mjs +2 -2
  23. package/src/adapter/Runtime/Runtime.res +49 -10
  24. package/src/adapter/Runtime/Runtime.res.mjs +22 -8
  25. package/src/admin/Platform_Admin.res +1 -1
  26. package/src/admin/Platform_Admin.res.mjs +8 -2
  27. package/src/components/Aggregate/Aggregate_Builder.res +10 -2
  28. package/src/components/Aggregate/Aggregate_Builder.res.mjs +8 -2
  29. package/src/components/AutomationSlice/AutomationSlice_Builder.res +12 -2
  30. package/src/components/AutomationSlice/AutomationSlice_Builder.res.mjs +8 -2
  31. package/src/components/CommandTopic/CommandTopic.res +5 -1
  32. package/src/components/CommandTopic/CommandTopic_Adapter.res +1 -0
  33. package/src/components/CommandTopic/CommandTopic_Builder.res +4 -4
  34. package/src/components/CommandTopic/CommandTopic_Builder.res.mjs +29 -30
  35. package/src/components/Counter/Counter_Builder.res +7 -1
  36. package/src/components/Counter/Counter_Builder.res.mjs +5 -2
  37. package/src/components/Dcb/Dcb_Builder.res +2 -2
  38. package/src/components/Dcb/Dcb_Builder.res.mjs +8 -2
  39. package/src/components/DcbEventLog/DcbEventLog_Builder.res +3 -0
  40. package/src/components/DcbEventLog/DcbEventLog_Builder.res.mjs +4 -1
  41. package/src/components/EventCollector/EventCollector.res +1 -0
  42. package/src/components/EventCollector/EventCollector_Adapter.res +1 -0
  43. package/src/components/EventCollector/EventCollector_Builder.res +4 -4
  44. package/src/components/EventCollector/EventCollector_Builder.res.mjs +2 -2
  45. package/src/components/EventLog/EventLog.res +5 -1
  46. package/src/components/EventLog/EventLog_Adapter.res +5 -1
  47. package/src/components/EventLog/EventLog_Builder.res +9 -4
  48. package/src/components/EventLog/EventLog_Builder.res.mjs +7 -8
  49. package/src/components/EventMapper/EventMapper_Builder.res +6 -1
  50. package/src/components/EventMapper/EventMapper_Builder.res.mjs +4 -1
  51. package/src/components/EventTopic/EventTopic.res +1 -0
  52. package/src/components/EventTopic/EventTopic_Adapter.res +1 -0
  53. package/src/components/EventTopic/EventTopic_Builder.res +4 -3
  54. package/src/components/EventTopic/EventTopic_Builder.res.mjs +2 -2
  55. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res +11 -2
  56. package/src/components/ExtensionPoint/ExtensionPoint_Builder.res.mjs +8 -2
  57. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res +6 -1
  58. package/src/components/InboundTranslationSlice/InboundTranslationSlice_Builder.res.mjs +4 -1
  59. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res +12 -2
  60. package/src/components/OutboundTranslationSlice/OutboundTranslationSlice_Builder.res.mjs +8 -2
  61. package/src/components/QueryDb/QueryDb.res +1 -0
  62. package/src/components/QueryDb/QueryDb_Adapter.res +1 -0
  63. package/src/components/QueryDb/QueryDb_Builder.res +4 -3
  64. package/src/components/QueryDb/QueryDb_Builder.res.mjs +2 -2
  65. package/src/components/ReadModel/ReadModel_Builder.res +12 -2
  66. package/src/components/ReadModel/ReadModel_Builder.res.mjs +8 -2
  67. package/src/components/SideEffectHandler/SideEffectHandler_Builder.res +6 -1
  68. package/src/components/SideEffectHandler/SideEffectHandler_Builder.res.mjs +4 -1
  69. package/src/components/StateViewSlice/StateViewSlice_Builder.res +12 -2
  70. package/src/components/StateViewSlice/StateViewSlice_Builder.res.mjs +8 -2
  71. package/src/plugin/component/Plugin_Builder.res +6 -0
  72. package/src/plugin/component/Plugin_Builder.res.mjs +3 -0
  73. package/src/plugin/component/Plugin_Helpers.res +1 -1
  74. package/src/plugin/component/Plugin_Helpers.res.mjs +4 -1
  75. package/tests/ResourceAttributionTest.res +70 -0
  76. package/tests/aggregate/AggregateCacheTest.res +1 -1
  77. package/tests/aggregate/AggregateConflictTest.res +1 -1
  78. package/tests/aggregate/AggregateFixtures.res +1 -1
  79. package/tests/aggregate/AggregateSnapshotTest.res +1 -1
  80. package/tests/eventlog/EventLogFixtures.res +1 -1
  81. 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.174",
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.102",
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.79"
41
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.80"
42
42
  },
43
43
  "devDependencies": {
44
44
  "rescript": "12.3.0",
@@ -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
- | Core
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" :
@@ -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
- // All three are optional: absent in `.test()` and wherever the dispatch site has
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<effectHandler>> = Dict.make()
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
- let runEffect = effect => Runtime.runEffect(~correlationId?, ~causationId?, ~comp, effect)
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(handler => runEffect(handler(event, context)))
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(handler => runEffect(handler(event, context))));
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([RuntimeEnvironment.asEffectHandler(handler)]);
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
- ~comp=name,
37
+ ~extractSentTimestamp=RuntimeEnvironment.extractSentTimestamp,
38
+ ~extractRetryCount=RuntimeEnvironment.extractRetryCount,
39
+ ~comp,
35
40
  )
36
41
  ),
37
42
  ~memorySize,