@reventlessdev/reventless-core 3.0.0-alpha.174 → 3.0.0-alpha.176
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 +27 -0
- package/package.json +7 -7
- package/src/ComponentType.res +4 -4
- package/src/ComponentType.res.mjs +6 -6
- 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 +8 -2
- package/src/plugin/component/Plugin_Builder.res.mjs +4 -1
- package/src/plugin/component/Plugin_Helpers.res +1 -1
- package/src/plugin/component/Plugin_Helpers.res.mjs +4 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res +26 -12
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +8 -8
- package/src/util/Interstack.res +1 -1
- package/src/util/Interstack.res.mjs +3 -3
- package/src/util/Interstack.resi +1 -1
- package/src/util/Util_StackRefs.res +2 -2
- package/src/util/Util_StackRefs.res.mjs +4 -4
- 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
|
@@ -58,7 +58,12 @@ module Make = (
|
|
|
58
58
|
let timeout = ReventlessInfra.RuntimeHints.resolveTimeout(runtime, ~default=30)
|
|
59
59
|
|
|
60
60
|
module SpecificQueryDb = QueryDb_Builder.Make(Spec, QueryDbStorage, QueryDbResolvers)
|
|
61
|
-
let queryDb = SpecificQueryDb.make(
|
|
61
|
+
let queryDb = SpecificQueryDb.make(
|
|
62
|
+
~api,
|
|
63
|
+
~apiRole,
|
|
64
|
+
~owner={kind: ComponentType.ReadModel, name: Spec.name},
|
|
65
|
+
~opts,
|
|
66
|
+
)
|
|
62
67
|
|
|
63
68
|
let toProjectionOperations: SpecificQueryDb.operations => projectionOperations = ({
|
|
64
69
|
load,
|
|
@@ -114,7 +119,12 @@ module Make = (
|
|
|
114
119
|
->Component.operations
|
|
115
120
|
->Pulumi.Output.apply(operations => {
|
|
116
121
|
let eventTopics = allEventTopics->EventTopic.filter(sourceNames)
|
|
117
|
-
let eventCollector = SpecificEventCollector.make(
|
|
122
|
+
let eventCollector = SpecificEventCollector.make(
|
|
123
|
+
~name,
|
|
124
|
+
~eventTopics,
|
|
125
|
+
~owner={kind: ComponentType.ReadModel, name: Spec.name},
|
|
126
|
+
~opts,
|
|
127
|
+
)
|
|
118
128
|
|
|
119
129
|
module Callback = ReadModel_Callback.Make(
|
|
120
130
|
Spec,
|
|
@@ -27,7 +27,10 @@ function Make(Spec) {
|
|
|
27
27
|
let memorySize = RuntimeHints$ReventlessInfra.resolveMemory(runtime, 1024);
|
|
28
28
|
let timeout = RuntimeHints$ReventlessInfra.resolveTimeout(runtime, 30);
|
|
29
29
|
let SpecificQueryDb = QueryDb_Builder$ReventlessCore.Make(Spec)(QueryDbStorage)(QueryDbResolvers);
|
|
30
|
-
let queryDb = SpecificQueryDb.make(api, apiRole, undefined,
|
|
30
|
+
let queryDb = SpecificQueryDb.make(api, apiRole, undefined, {
|
|
31
|
+
kind: "ReadModel",
|
|
32
|
+
name: Spec.name
|
|
33
|
+
}, opts);
|
|
31
34
|
let toProjectionOperations = param => {
|
|
32
35
|
let deleteBatch = param.deleteBatch;
|
|
33
36
|
let $$delete = param.delete;
|
|
@@ -64,7 +67,10 @@ function Make(Spec) {
|
|
|
64
67
|
let SpecificEventCollector = EventCollector_Builder$ReventlessCore.Make(RuntimeEnvironment)(EventCollectorChannel);
|
|
65
68
|
let eventCollector = Component$ReventlessCore.operations(queryDb).apply(operations => {
|
|
66
69
|
let eventTopics = EventTopic$ReventlessCore.filter(allEventTopics, sourceNames);
|
|
67
|
-
let eventCollector = SpecificEventCollector.make(name, eventTopics,
|
|
70
|
+
let eventCollector = SpecificEventCollector.make(name, eventTopics, {
|
|
71
|
+
kind: "ReadModel",
|
|
72
|
+
name: Spec.name
|
|
73
|
+
}, opts);
|
|
68
74
|
let operations$1 = toProjectionOperations(operations);
|
|
69
75
|
let Callback = ReadModel_Callback$ReventlessCore.Make(Spec)(Mappings)({
|
|
70
76
|
ReadModelSpec: Spec,
|
|
@@ -27,7 +27,12 @@ module Make = (
|
|
|
27
27
|
->Belt.Set.String.fromArray
|
|
28
28
|
|
|
29
29
|
let eventTopics = allEventTopics->EventTopic.filter(aggregateNames)
|
|
30
|
-
let eventCollector = SpecificEventCollector.make(
|
|
30
|
+
let eventCollector = SpecificEventCollector.make(
|
|
31
|
+
~name,
|
|
32
|
+
~eventTopics,
|
|
33
|
+
~owner={kind: ComponentType.SideEffectHandler, name},
|
|
34
|
+
~opts,
|
|
35
|
+
)
|
|
31
36
|
|
|
32
37
|
module Callback = SideEffectHandler_Callback.Make({
|
|
33
38
|
let sideEffects = sideEffects
|
|
@@ -24,7 +24,10 @@ function Make(RuntimeEnvironment) {
|
|
|
24
24
|
};
|
|
25
25
|
let aggregateNames = Belt_SetString.fromArray(sideEffects.map(SideEffect => SideEffect.Source.name));
|
|
26
26
|
let eventTopics = EventTopic$ReventlessCore.filter(allEventTopics, aggregateNames);
|
|
27
|
-
let eventCollector = SpecificEventCollector.make(extra$1, eventTopics,
|
|
27
|
+
let eventCollector = SpecificEventCollector.make(extra$1, eventTopics, {
|
|
28
|
+
kind: "SideEffectHandler",
|
|
29
|
+
name: extra$1
|
|
30
|
+
}, opts);
|
|
28
31
|
let Callback = SideEffectHandler_Callback$ReventlessCore.Make({
|
|
29
32
|
sideEffects: sideEffects,
|
|
30
33
|
queryEngine: queryEngine
|
|
@@ -63,7 +63,12 @@ module Make = (
|
|
|
63
63
|
let memorySize = ReventlessInfra.RuntimeHints.resolveMemory(runtime, ~default=1024)
|
|
64
64
|
let timeout = ReventlessInfra.RuntimeHints.resolveTimeout(runtime, ~default=30)
|
|
65
65
|
|
|
66
|
-
let queryDb = SpecificQueryDb.make(
|
|
66
|
+
let queryDb = SpecificQueryDb.make(
|
|
67
|
+
~api=Api.api(),
|
|
68
|
+
~apiRole=Api.apiRole(),
|
|
69
|
+
~owner={kind: ComponentType.StateViewSlice, name: Spec.name},
|
|
70
|
+
~opts,
|
|
71
|
+
)
|
|
67
72
|
|
|
68
73
|
let dcbEventTopicOutputs: EventTopic.outputs = (dcbEventLog->Component.outputs).eventTopic
|
|
69
74
|
let allEventTopics = Dict.fromArray([(Spec.name, dcbEventTopicOutputs)])
|
|
@@ -74,7 +79,12 @@ module Make = (
|
|
|
74
79
|
->Pulumi.Output.apply(queryDbOps => {
|
|
75
80
|
let projectionOps = toProjectionOps(queryDbOps)
|
|
76
81
|
|
|
77
|
-
let ec = SpecificEventCollector.make(
|
|
82
|
+
let ec = SpecificEventCollector.make(
|
|
83
|
+
~name=Spec.name,
|
|
84
|
+
~eventTopics=allEventTopics,
|
|
85
|
+
~owner={kind: ComponentType.StateViewSlice, name: Spec.name},
|
|
86
|
+
~opts,
|
|
87
|
+
)
|
|
78
88
|
|
|
79
89
|
let comp = `StateViewSlice(${Spec.name})`
|
|
80
90
|
|
|
@@ -61,7 +61,10 @@ function Make(RuntimeEnvironment) {
|
|
|
61
61
|
};
|
|
62
62
|
let memorySize = RuntimeHints$ReventlessInfra.resolveMemory(runtime, 1024);
|
|
63
63
|
let timeout = RuntimeHints$ReventlessInfra.resolveTimeout(runtime, 30);
|
|
64
|
-
let queryDb = SpecificQueryDb.make(Api.api(), Api.apiRole(), undefined,
|
|
64
|
+
let queryDb = SpecificQueryDb.make(Api.api(), Api.apiRole(), undefined, {
|
|
65
|
+
kind: "StateViewSlice",
|
|
66
|
+
name: Spec.name
|
|
67
|
+
}, opts);
|
|
65
68
|
let dcbEventTopicOutputs = Component$ReventlessCore.outputs(dcbEventLog).eventTopic;
|
|
66
69
|
let allEventTopics = Object.fromEntries([[
|
|
67
70
|
Spec.name,
|
|
@@ -69,7 +72,10 @@ function Make(RuntimeEnvironment) {
|
|
|
69
72
|
]]);
|
|
70
73
|
let eventCollector = Component$ReventlessCore.operations(queryDb).apply(queryDbOps => {
|
|
71
74
|
let projectionOps = toProjectionOps(queryDbOps);
|
|
72
|
-
let ec = SpecificEventCollector.make(Spec.name, allEventTopics,
|
|
75
|
+
let ec = SpecificEventCollector.make(Spec.name, allEventTopics, {
|
|
76
|
+
kind: "StateViewSlice",
|
|
77
|
+
name: Spec.name
|
|
78
|
+
}, opts);
|
|
73
79
|
let comp = `StateViewSlice(` + Spec.name + `)`;
|
|
74
80
|
let jsonEventsHandler = stream => Effect.flatMap(Stream.runCollect(stream), events => {
|
|
75
81
|
let total = events.length.toString();
|
|
@@ -67,6 +67,11 @@ module Make = (
|
|
|
67
67
|
let _prevPluginName = Logger.currentPluginName.contents
|
|
68
68
|
Logger.currentPluginName := Some(name)
|
|
69
69
|
|
|
70
|
+
// Publish the owning plugin/platform for resource attribution, so adapters
|
|
71
|
+
// creating infrastructure below this point can tag it without every adapter
|
|
72
|
+
// signature having to carry the two names. Restored at the end of construct.
|
|
73
|
+
let _prevAttribution = ResourceAttribution.enter(~platform=Spec.platformName, ~plugin=name)
|
|
74
|
+
|
|
70
75
|
// Register every component → plugin so runtime logs (fired after construct
|
|
71
76
|
// returns) can resolve a comp like `StateChangeSlice(AddProduct)` to its
|
|
72
77
|
// owning plugin via `Logger.componentPluginRegistry`. Also register the
|
|
@@ -570,8 +575,8 @@ module Make = (
|
|
|
570
575
|
let builderOutputs = {
|
|
571
576
|
// Resolve admin extension point data — from Interstack (AWS cross-stack reference).
|
|
572
577
|
let interstackAdminExtensionPoints =
|
|
573
|
-
Interstack.
|
|
574
|
-
|
|
578
|
+
Interstack.platformStackReference->Option.mapOr(Pulumi.Output.make(None), platformStack =>
|
|
579
|
+
platformStack->Pulumi.StackReference.getOutput("extensionPoints")
|
|
575
580
|
)
|
|
576
581
|
|
|
577
582
|
// Derive local admin extension point resolved data (passed from makePlatform).
|
|
@@ -975,6 +980,7 @@ module Make = (
|
|
|
975
980
|
)
|
|
976
981
|
|
|
977
982
|
Logger.currentPluginName := _prevPluginName
|
|
983
|
+
ResourceAttribution.restore(_prevAttribution)
|
|
978
984
|
}
|
|
979
985
|
|
|
980
986
|
let makeAutoUIManifest = (
|
|
@@ -31,6 +31,7 @@ import * as AdapterDeploytime$ReventlessCore from "../../adapter/AdapterDeployti
|
|
|
31
31
|
import * as ExtensionMapping$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/ExtensionMapping.res.mjs";
|
|
32
32
|
import * as ExtensionPoint$ReventlessInterop from "@reventlessdev/reventless-interop/src/components/ExtensionPoint.res.mjs";
|
|
33
33
|
import * as Heartbeat_Builder$ReventlessCore from "../../components/Heartbeat/Heartbeat_Builder.res.mjs";
|
|
34
|
+
import * as ResourceAttribution$ReventlessCore from "../../ResourceAttribution.res.mjs";
|
|
34
35
|
import * as PluginExtensionPointSpec$ReventlessInfra from "@reventlessdev/reventless-infra/src/types/PluginExtensionPointSpec.res.mjs";
|
|
35
36
|
import * as Plugin_SubscriptionSchema$ReventlessCore from "./Plugin_SubscriptionSchema.res.mjs";
|
|
36
37
|
|
|
@@ -121,6 +122,7 @@ function Make(Spec) {
|
|
|
121
122
|
return Component$ReventlessCore.make(ComponentType$ReventlessCore.toString(Plugin$ReventlessCore.componentType), name, (extra, extra$1) => {
|
|
122
123
|
let _prevPluginName = Logger$ReventlessCore.currentPluginName.contents;
|
|
123
124
|
Logger$ReventlessCore.currentPluginName.contents = extra$1;
|
|
125
|
+
let _prevAttribution = ResourceAttribution$ReventlessCore.enter(Spec.platformName, extra$1);
|
|
124
126
|
Logger$ReventlessCore.registerComponentPlugin(extra$1, extra$1);
|
|
125
127
|
aggregates.forEach(M => Logger$ReventlessCore.registerComponentPlugin(M.Spec.name, extra$1));
|
|
126
128
|
readModels.forEach(R => Logger$ReventlessCore.registerComponentPlugin(R.Spec.name, extra$1));
|
|
@@ -397,7 +399,7 @@ function Make(Spec) {
|
|
|
397
399
|
components: components
|
|
398
400
|
});
|
|
399
401
|
}
|
|
400
|
-
let interstackAdminExtensionPoints = Stdlib_Option.mapOr(Interstack$ReventlessCore.
|
|
402
|
+
let interstackAdminExtensionPoints = Stdlib_Option.mapOr(Interstack$ReventlessCore.platformStackReference, Pulumi.output(undefined), platformStack => platformStack.getOutput("extensionPoints"));
|
|
401
403
|
let localAdminResolvedEP = Output$Pulumi.flatMap(Spec.hooks.adminExtensionPoints.contents, eps => {
|
|
402
404
|
let ep = eps[PluginExtensionPointSpec$ReventlessInfra.name];
|
|
403
405
|
if (ep !== undefined) {
|
|
@@ -626,6 +628,7 @@ function Make(Spec) {
|
|
|
626
628
|
Component$ReventlessCore.setOutputs(extra, pluginOutputs);
|
|
627
629
|
Plugin_Helpers$ReventlessCore.interopMetaOutput.contents = builderOutputs.apply(outputs => S.reverseConvertToJsonOrThrow(Plugin_Helpers$ReventlessCore.toInteropMeta(outputs), ExportMeta$ReventlessInterop.schema));
|
|
628
630
|
Logger$ReventlessCore.currentPluginName.contents = _prevPluginName;
|
|
631
|
+
return ResourceAttribution$ReventlessCore.restore(_prevAttribution);
|
|
629
632
|
}, opts);
|
|
630
633
|
};
|
|
631
634
|
return {
|
|
@@ -449,7 +449,7 @@ module MakeEventCollectorHelper = (
|
|
|
449
449
|
EventCollectorChannel,
|
|
450
450
|
)
|
|
451
451
|
let make = (~name, ~eventTopics, ~opts) => {
|
|
452
|
-
let eventCollector = PluginEventCollector.make(~name, ~eventTopics, ~opts)
|
|
452
|
+
let eventCollector = PluginEventCollector.make(~name, ~eventTopics, ~owner={kind: ComponentType.Plugin, name}, ~opts)
|
|
453
453
|
let eventCollectorOutputs = eventCollector->Component.outputs
|
|
454
454
|
// pluginDefinition.eventCollector must identify the EC's inbound queue
|
|
455
455
|
// ARN — admin's `manageSubscriptions` uses it as the subscription target
|
|
@@ -255,7 +255,10 @@ function MakeEventCollectorHelper(RuntimeEnvironment) {
|
|
|
255
255
|
return EventCollectorChannel => (PluginRuntimeBuilder => {
|
|
256
256
|
let PluginEventCollector = EventCollector_Builder$ReventlessCore.Make(RuntimeEnvironment)(EventCollectorChannel);
|
|
257
257
|
let make = (name, eventTopics, opts) => {
|
|
258
|
-
let eventCollector = PluginEventCollector.make(name, eventTopics,
|
|
258
|
+
let eventCollector = PluginEventCollector.make(name, eventTopics, {
|
|
259
|
+
kind: "Plugin",
|
|
260
|
+
name: name
|
|
261
|
+
}, opts);
|
|
259
262
|
let eventCollectorOutputs = Component$ReventlessCore.outputs(eventCollector);
|
|
260
263
|
let resources = eventCollectorOutputs.resources;
|
|
261
264
|
let r = resources[resources.length - 1 | 0];
|
|
@@ -47,7 +47,7 @@ module Make = (Spec: Spec) => {
|
|
|
47
47
|
switch jsons {
|
|
48
48
|
| [] =>
|
|
49
49
|
EffectLogger.logWarn(
|
|
50
|
-
~comp=
|
|
50
|
+
~comp=PluginExtensionPointSpec.name,
|
|
51
51
|
`ForwardCommand: Couldn't find Plugin with ExtensionPoint ${extensionPointName}`,
|
|
52
52
|
)->Effect.runSync
|
|
53
53
|
| plugins =>
|
|
@@ -66,28 +66,31 @@ module Make = (Spec: Spec) => {
|
|
|
66
66
|
) {
|
|
67
67
|
| _ =>
|
|
68
68
|
EffectLogger.logInfo(
|
|
69
|
-
~comp=
|
|
69
|
+
~comp=PluginExtensionPointSpec.name,
|
|
70
70
|
`ForwardCommand: published command to ${plugin.name} ${extensionPoint.commandTopic}`,
|
|
71
71
|
)->Effect.runSync
|
|
72
72
|
| exception err =>
|
|
73
73
|
let errMsg =
|
|
74
74
|
err->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("unknown")
|
|
75
75
|
EffectLogger.logError(
|
|
76
|
-
~comp=
|
|
76
|
+
~comp=PluginExtensionPointSpec.name,
|
|
77
77
|
`ForwardCommand: Error on publish command: ${errMsg}`,
|
|
78
78
|
)->Effect.runSync
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
| None =>
|
|
82
82
|
EffectLogger.logWarn(
|
|
83
|
-
~comp=
|
|
83
|
+
~comp=PluginExtensionPointSpec.name,
|
|
84
84
|
`ForwardCommand: Couldn't find ExtensionPoint ${extensionPointName} in ${plugin.name}`,
|
|
85
85
|
)->Effect.runSync
|
|
86
86
|
}
|
|
87
87
|
| exception err =>
|
|
88
88
|
let errMsg =
|
|
89
89
|
err->JsExn.fromException->Option.flatMap(JsExn.message)->Option.getOr("unknown")
|
|
90
|
-
EffectLogger.logError(
|
|
90
|
+
EffectLogger.logError(
|
|
91
|
+
~comp=PluginExtensionPointSpec.name,
|
|
92
|
+
`ForwardCommand: Couldn't decode Plugin: ${errMsg}`,
|
|
93
|
+
)->Effect.runSync
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
}
|
|
@@ -105,7 +108,7 @@ module Make = (Spec: Spec) => {
|
|
|
105
108
|
rate: timeout->ScheduleOps.minutesFromNow,
|
|
106
109
|
payload: {
|
|
107
110
|
Message.id,
|
|
108
|
-
meta: Message.generateMeta(~service=
|
|
111
|
+
meta: Message.generateMeta(~service=PluginExtensionPointSpec.name, ~user="Scheduler"),
|
|
109
112
|
command: PluginExtensionPointSpec.DisconnectPlugin,
|
|
110
113
|
}
|
|
111
114
|
->Message.encodeCommand'(S.string, PluginExtensionPointSpec.commandSchema)
|
|
@@ -155,7 +158,10 @@ module Make = (Spec: Spec) => {
|
|
|
155
158
|
PublishCommand(Plugin.name(id), Delegate.Heartbeat(Plugin.version(id))),
|
|
156
159
|
// Re-arm the disconnect schedule with an interval-scaled grace so a
|
|
157
160
|
// single late beat doesn't trip a spurious disconnect (see disconnectGrace).
|
|
158
|
-
HandleDirective(
|
|
161
|
+
HandleDirective(
|
|
162
|
+
directiveHandler,
|
|
163
|
+
CreateDisconnectSchedule(id, disconnectGrace(interval)),
|
|
164
|
+
),
|
|
159
165
|
]
|
|
160
166
|
| RedetectPlugin(interval) => [
|
|
161
167
|
// Deploy-time re-detect: drive Redetect (not Heartbeat) so an already-connected
|
|
@@ -163,7 +169,10 @@ module Make = (Spec: Spec) => {
|
|
|
163
169
|
// re-arm the disconnect schedule exactly like a heartbeat so liveness tracking
|
|
164
170
|
// continues from the deploy moment.
|
|
165
171
|
PublishCommand(Plugin.name(id), Delegate.Redetect(Plugin.version(id))),
|
|
166
|
-
HandleDirective(
|
|
172
|
+
HandleDirective(
|
|
173
|
+
directiveHandler,
|
|
174
|
+
CreateDisconnectSchedule(id, disconnectGrace(interval)),
|
|
175
|
+
),
|
|
167
176
|
]
|
|
168
177
|
| ConnectPlugin(pluginDefinition) =>
|
|
169
178
|
// Validate protocol versions declared by the connecting plugin.
|
|
@@ -172,7 +181,7 @@ module Make = (Spec: Spec) => {
|
|
|
172
181
|
let protocolErrors =
|
|
173
182
|
pluginDefinition.extensionProtocols->Array.flatMap(proto =>
|
|
174
183
|
ReventlessInterop.Compat.validateProtocol(
|
|
175
|
-
~host=ReventlessInterop.CompatMatrix.
|
|
184
|
+
~host=ReventlessInterop.CompatMatrix.platformPlugin,
|
|
176
185
|
~extensionPointName=proto.extensionPointName,
|
|
177
186
|
~commandVersion=proto.commandVersion,
|
|
178
187
|
~eventVersion=proto.eventVersion,
|
|
@@ -180,7 +189,7 @@ module Make = (Spec: Spec) => {
|
|
|
180
189
|
)
|
|
181
190
|
let reportAction = if protocolErrors->Array.length > 0 {
|
|
182
191
|
EffectLogger.logWarn(
|
|
183
|
-
~comp=
|
|
192
|
+
~comp=PluginExtensionPointSpec.name,
|
|
184
193
|
`Protocol version mismatch for plugin ${pluginDefinition.id}: ${protocolErrors
|
|
185
194
|
->JSON.stringifyAny
|
|
186
195
|
->Option.getOr("[]")}`,
|
|
@@ -197,7 +206,9 @@ module Make = (Spec: Spec) => {
|
|
|
197
206
|
PublishCommand(Plugin.name(id), Delegate.Disconnect(Plugin.version(id))),
|
|
198
207
|
HandleDirective(directiveHandler, DeleteDisconnectSchedule(id)),
|
|
199
208
|
]
|
|
200
|
-
| ForwardCommand(forwardCommand) => [
|
|
209
|
+
| ForwardCommand(forwardCommand) => [
|
|
210
|
+
HandleDirective(directiveHandler, ForwardCommand(forwardCommand)),
|
|
211
|
+
]
|
|
201
212
|
// Routed to the UiFragmentRegistry slice by the sibling UI-fragment mapping, not the
|
|
202
213
|
// Plugin aggregate — a no-op here.
|
|
203
214
|
| RegisterUiFragment(_) => []
|
|
@@ -212,7 +223,10 @@ module Make = (Spec: Spec) => {
|
|
|
212
223
|
// definition publish with `def.id` (= name@version), preserving the prior
|
|
213
224
|
// cross-plugin wire id.
|
|
214
225
|
| Delegate.VersionDetected(version) => [
|
|
215
|
-
PublishEvent(
|
|
226
|
+
PublishEvent(
|
|
227
|
+
Plugin.makeId(id, version),
|
|
228
|
+
PluginExtensionPointSpec.UnknownPluginDetected,
|
|
229
|
+
),
|
|
216
230
|
]
|
|
217
231
|
| VersionConnected(pluginDefinition)
|
|
218
232
|
| VersionPromoted(pluginDefinition) => [
|
|
@@ -43,7 +43,7 @@ function Make(Spec) {
|
|
|
43
43
|
]
|
|
44
44
|
], 1000);
|
|
45
45
|
if (jsons.length === 0) {
|
|
46
|
-
return Effect.runSync(EffectLogger$ReventlessCore.logWarn(
|
|
46
|
+
return Effect.runSync(EffectLogger$ReventlessCore.logWarn(PluginExtensionPointSpec$ReventlessInfra.name, undefined, `ForwardCommand: Couldn't find Plugin with ExtensionPoint ` + extensionPointName));
|
|
47
47
|
}
|
|
48
48
|
let plugin = jsons[0];
|
|
49
49
|
let exit = 0;
|
|
@@ -54,12 +54,12 @@ function Make(Spec) {
|
|
|
54
54
|
} catch (raw_err) {
|
|
55
55
|
let err = Primitive_exceptions.internalToException(raw_err);
|
|
56
56
|
let errMsg = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(err), Stdlib_JsExn.message), "unknown");
|
|
57
|
-
return Effect.runSync(EffectLogger$ReventlessCore.logError(
|
|
57
|
+
return Effect.runSync(EffectLogger$ReventlessCore.logError(PluginExtensionPointSpec$ReventlessInfra.name, undefined, `ForwardCommand: Couldn't decode Plugin: ` + errMsg));
|
|
58
58
|
}
|
|
59
59
|
if (exit === 1) {
|
|
60
60
|
let extensionPoint = plugin$1.extensionPoints.find(extensionPoint => extensionPoint.name === extensionPointName);
|
|
61
61
|
if (extensionPoint === undefined) {
|
|
62
|
-
return Effect.runSync(EffectLogger$ReventlessCore.logWarn(
|
|
62
|
+
return Effect.runSync(EffectLogger$ReventlessCore.logWarn(PluginExtensionPointSpec$ReventlessInfra.name, undefined, `ForwardCommand: Couldn't find ExtensionPoint ` + extensionPointName + ` in ` + plugin$1.name));
|
|
63
63
|
}
|
|
64
64
|
let exit$1 = 0;
|
|
65
65
|
let val;
|
|
@@ -69,10 +69,10 @@ function Make(Spec) {
|
|
|
69
69
|
} catch (raw_err$1) {
|
|
70
70
|
let err$1 = Primitive_exceptions.internalToException(raw_err$1);
|
|
71
71
|
let errMsg$1 = Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_JsExn.fromException(err$1), Stdlib_JsExn.message), "unknown");
|
|
72
|
-
return Effect.runSync(EffectLogger$ReventlessCore.logError(
|
|
72
|
+
return Effect.runSync(EffectLogger$ReventlessCore.logError(PluginExtensionPointSpec$ReventlessInfra.name, undefined, `ForwardCommand: Error on publish command: ` + errMsg$1));
|
|
73
73
|
}
|
|
74
74
|
if (exit$1 === 2) {
|
|
75
|
-
return Effect.runSync(EffectLogger$ReventlessCore.logInfo(
|
|
75
|
+
return Effect.runSync(EffectLogger$ReventlessCore.logInfo(PluginExtensionPointSpec$ReventlessInfra.name, undefined, `ForwardCommand: published command to ` + plugin$1.name + ` ` + extensionPoint.commandTopic));
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
};
|
|
@@ -85,7 +85,7 @@ function Make(Spec) {
|
|
|
85
85
|
rate: ScheduleOps$ReventlessCore.minutesFromNow(directive._1),
|
|
86
86
|
payload: JSON.stringify(Message$ReventlessCore.encodeCommand$p({
|
|
87
87
|
id: id,
|
|
88
|
-
meta: Message$ReventlessCore.generateMeta(
|
|
88
|
+
meta: Message$ReventlessCore.generateMeta(PluginExtensionPointSpec$ReventlessInfra.name, undefined, "Scheduler", undefined, undefined, undefined, undefined, undefined),
|
|
89
89
|
command: "DisconnectPlugin"
|
|
90
90
|
}, S.string, PluginExtensionPointSpec$ReventlessInfra.commandSchema))
|
|
91
91
|
});
|
|
@@ -162,8 +162,8 @@ function Make(Spec) {
|
|
|
162
162
|
];
|
|
163
163
|
case "ConnectPlugin" :
|
|
164
164
|
let pluginDefinition = cmd._0;
|
|
165
|
-
let protocolErrors = pluginDefinition.extensionProtocols.flatMap(proto => Compat$ReventlessInterop.validateProtocol(CompatMatrix$ReventlessInterop.
|
|
166
|
-
let reportAction = protocolErrors.length !== 0 ? (Effect.runSync(EffectLogger$ReventlessCore.logWarn(
|
|
165
|
+
let protocolErrors = pluginDefinition.extensionProtocols.flatMap(proto => Compat$ReventlessInterop.validateProtocol(CompatMatrix$ReventlessInterop.platformPlugin, proto.extensionPointName, proto.commandVersion, proto.eventVersion));
|
|
166
|
+
let reportAction = protocolErrors.length !== 0 ? (Effect.runSync(EffectLogger$ReventlessCore.logWarn(PluginExtensionPointSpec$ReventlessInfra.name, undefined, `Protocol version mismatch for plugin ` + pluginDefinition.id + `: ` + Stdlib_Option.getOr(JSON.stringify(protocolErrors), "[]"))), [{
|
|
167
167
|
TAG: "PublishCommand",
|
|
168
168
|
_0: Plugin$ReventlessCore.name(id),
|
|
169
169
|
_1: {
|
package/src/util/Interstack.res
CHANGED
|
@@ -10,7 +10,7 @@ import * as Query$ReventlessInterop from "@reventlessdev/reventless-interop/src/
|
|
|
10
10
|
import * as EventMapper$ReventlessInterop from "@reventlessdev/reventless-interop/src/components/EventMapper.res.mjs";
|
|
11
11
|
import * as ExtensionPoint$ReventlessInterop from "@reventlessdev/reventless-interop/src/components/ExtensionPoint.res.mjs";
|
|
12
12
|
|
|
13
|
-
let
|
|
13
|
+
let platformStackReference = Stdlib_Option.map(new Pulumi.Config("platform").get("stack"), stack => new Pulumi.StackReference(stack + "-interstack", {
|
|
14
14
|
name: stack
|
|
15
15
|
}));
|
|
16
16
|
|
|
@@ -115,7 +115,7 @@ let mergeEventMappers = DefaultEventMapperQuery.mergeWith;
|
|
|
115
115
|
let mergeExtensionPoints = DefaultExtensionPointQuery.mergeWith;
|
|
116
116
|
|
|
117
117
|
export {
|
|
118
|
-
|
|
118
|
+
platformStackReference,
|
|
119
119
|
stackDependenciesTasks,
|
|
120
120
|
stackDependenciesEventMappers,
|
|
121
121
|
stackDependenciesExtensionPoints,
|
|
@@ -123,4 +123,4 @@ export {
|
|
|
123
123
|
mergeEventMappers,
|
|
124
124
|
mergeExtensionPoints,
|
|
125
125
|
}
|
|
126
|
-
/*
|
|
126
|
+
/* platformStackReference Not a pure module */
|
package/src/util/Interstack.resi
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
let stackRefs: dict<Pulumi.StackReference.t> = Dict.make()
|
|
2
2
|
|
|
3
|
-
let
|
|
3
|
+
let platformStackName = Pulumi.Config.make(Some("platform"))->Pulumi.Config.get("stack")
|
|
4
4
|
|
|
5
5
|
let stackName = pluginName =>
|
|
6
|
-
|
|
6
|
+
platformStackName->Option.map(name => {
|
|
7
7
|
let parts = name->String.split("/")
|
|
8
8
|
parts->Array.set(1, pluginName)
|
|
9
9
|
parts->Array.joinUnsafe("/")
|
|
@@ -6,10 +6,10 @@ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js
|
|
|
6
6
|
|
|
7
7
|
let stackRefs = {};
|
|
8
8
|
|
|
9
|
-
let
|
|
9
|
+
let platformStackName = new Pulumi.Config("platform").get("stack");
|
|
10
10
|
|
|
11
11
|
function stackName(pluginName) {
|
|
12
|
-
return Stdlib_Option.map(
|
|
12
|
+
return Stdlib_Option.map(platformStackName, name => {
|
|
13
13
|
let parts = name.split("/");
|
|
14
14
|
parts[1] = pluginName;
|
|
15
15
|
return parts.join("/");
|
|
@@ -32,8 +32,8 @@ function get(pluginName) {
|
|
|
32
32
|
|
|
33
33
|
export {
|
|
34
34
|
stackRefs,
|
|
35
|
-
|
|
35
|
+
platformStackName,
|
|
36
36
|
stackName,
|
|
37
37
|
get,
|
|
38
38
|
}
|
|
39
|
-
/*
|
|
39
|
+
/* platformStackName Not a pure module */
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
open JestGlobals
|
|
2
|
+
|
|
3
|
+
// The attribution vocabulary is the shared contract between the AWS tag renderer
|
|
4
|
+
// and the Kubernetes label renderer. These guard the wire spellings (which land
|
|
5
|
+
// in deployed resource metadata and in downstream inventories) and the ambient
|
|
6
|
+
// context's save/restore discipline, which is what keeps a plugin's resources
|
|
7
|
+
// from being attributed to whichever plugin was constructed before it.
|
|
8
|
+
|
|
9
|
+
module Attribution = ResourceAttribution
|
|
10
|
+
|
|
11
|
+
describe("ResourceAttribution.Scope — wire spellings", () => {
|
|
12
|
+
testSync("scopes render lower-case", () => {
|
|
13
|
+
expect(
|
|
14
|
+
[Attribution.Scope.Component, Plugin, Platform]->Array.map(Attribution.Scope.toString),
|
|
15
|
+
)->toEqual(["component", "plugin", "platform"])
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
describe("ResourceAttribution.Role — wire spellings", () => {
|
|
20
|
+
testSync("piece roles render as their constructor name", () => {
|
|
21
|
+
expect(
|
|
22
|
+
[Attribution.Role.EventLog, QueryDb, Runtime, DeadLetter]->Array.map(
|
|
23
|
+
Attribution.Role.toString,
|
|
24
|
+
),
|
|
25
|
+
)->toEqual(["EventLog", "QueryDb", "Runtime", "DeadLetter"])
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
testSync("Other carries the caller's name verbatim", () => {
|
|
29
|
+
expect(Attribution.Role.Other("ChangeFeed")->Attribution.Role.toString)->toBe("ChangeFeed")
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
testSync("platform-level things are Platform, not Core", () => {
|
|
33
|
+
// `Core` predates the platform/plugin split and names nothing the framework
|
|
34
|
+
// builds; it also reads as the built-in core PLUGIN, which is a different
|
|
35
|
+
// thing. Platform substrate is attributed to `Platform`, matching
|
|
36
|
+
// `reventless:platform` and `Scope.Platform`.
|
|
37
|
+
expect(ComponentType.Platform->ComponentType.toString)->toBe("Platform")
|
|
38
|
+
expect(ComponentType.ofString("Platform"))->toEqual(Some(ComponentType.Platform))
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
testSync("a role is NOT a component kind — Runtime has no ComponentType twin", () => {
|
|
42
|
+
// The whole point of splitting role from kind: `Runtime` is a deployment
|
|
43
|
+
// piece, not something the domain model can be. If this ever resolves, the
|
|
44
|
+
// two vocabularies have started to merge again.
|
|
45
|
+
expect(ComponentType.ofString("Runtime"))->toEqual(None)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
describe("ResourceAttribution — ambient plugin context", () => {
|
|
50
|
+
testSync("outside any plugin construct, nothing is attributed", () => {
|
|
51
|
+
expect(Attribution.current.contents.plugin)->toEqual(None)
|
|
52
|
+
expect(Attribution.current.contents.platform)->toEqual(None)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
testSync("enter publishes the plugin and platform under construction", () => {
|
|
56
|
+
let previous = Attribution.enter(~platform="online-shop", ~plugin="Ordering")
|
|
57
|
+
expect(Attribution.current.contents.plugin)->toEqual(Some("Ordering"))
|
|
58
|
+
expect(Attribution.current.contents.platform)->toEqual(Some("online-shop"))
|
|
59
|
+
Attribution.restore(previous)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
testSync("restore unwinds to the previous context, so plugins don't leak", () => {
|
|
63
|
+
let outer = Attribution.enter(~platform="online-shop", ~plugin="Catalog")
|
|
64
|
+
let inner = Attribution.enter(~platform="online-shop", ~plugin="Ordering")
|
|
65
|
+
Attribution.restore(inner)
|
|
66
|
+
expect(Attribution.current.contents.plugin)->toEqual(Some("Catalog"))
|
|
67
|
+
Attribution.restore(outer)
|
|
68
|
+
expect(Attribution.current.contents.plugin)->toEqual(None)
|
|
69
|
+
})
|
|
70
|
+
})
|
|
@@ -166,7 +166,7 @@ module TestOps = {
|
|
|
166
166
|
}
|
|
167
167
|
type component = Component.t<OuterEventLog.t, OuterEventLog.outputs, operations>
|
|
168
168
|
// Never called — satisfies module type only
|
|
169
|
-
let make = (~name as _: string, ~opts as _=?): component => Obj.magic(0)
|
|
169
|
+
let make = (~name as _: string, ~owner as _=?, ~opts as _=?): component => Obj.magic(0)
|
|
170
170
|
}
|
|
171
171
|
let eventLog: EventLog.operations = {
|
|
172
172
|
append: mock.appendFn,
|
|
@@ -126,7 +126,7 @@ module TestOps = {
|
|
|
126
126
|
writeSnapshot: (string, EventLog.snapshot) => promise<result<unit, string>>,
|
|
127
127
|
}
|
|
128
128
|
type component = Component.t<OuterEventLog.t, OuterEventLog.outputs, operations>
|
|
129
|
-
let make = (~name as _: string, ~opts as _=?): component => Obj.magic(0)
|
|
129
|
+
let make = (~name as _: string, ~owner as _=?, ~opts as _=?): component => Obj.magic(0)
|
|
130
130
|
}
|
|
131
131
|
let eventLog: EventLog.operations = {
|
|
132
132
|
append: mock.appendFn,
|
|
@@ -142,7 +142,7 @@ module TestOps = {
|
|
|
142
142
|
}
|
|
143
143
|
type component = Component.t<OuterEventLog.t, OuterEventLog.outputs, operations>
|
|
144
144
|
// Never called — satisfies module type only
|
|
145
|
-
let make = (~name as _: string, ~opts as _=?): component => Obj.magic(0)
|
|
145
|
+
let make = (~name as _: string, ~owner as _=?, ~opts as _=?): component => Obj.magic(0)
|
|
146
146
|
}
|
|
147
147
|
let eventLog: EventLog.operations = {
|
|
148
148
|
append: mock.appendFn,
|
|
@@ -188,7 +188,7 @@ module MakeOps = (B: {let name: string}) => {
|
|
|
188
188
|
writeSnapshot: (string, EventLog.snapshot) => promise<result<unit, string>>,
|
|
189
189
|
}
|
|
190
190
|
type component = Component.t<OuterEventLog.t, OuterEventLog.outputs, operations>
|
|
191
|
-
let make = (~name as _: string, ~opts as _=?): component => Obj.magic(0)
|
|
191
|
+
let make = (~name as _: string, ~owner as _=?, ~opts as _=?): component => Obj.magic(0)
|
|
192
192
|
}
|
|
193
193
|
let eventLog: EventLog.operations = {
|
|
194
194
|
append: mock.appendFn,
|
|
@@ -84,7 +84,7 @@ module MockEventTopic: EventTopic.T
|
|
|
84
84
|
publishJsonStream: ReventlessInfra.EventTopic.publishJsonStream,
|
|
85
85
|
}
|
|
86
86
|
type component = Component.t<EventTopic.t, EventTopic.outputs, operations>
|
|
87
|
-
let make = (~name as _, ~storageResources as _, ~opts as _=?): component => Obj.magic(0)
|
|
87
|
+
let make = (~name as _, ~storageResources as _, ~owner as _=?, ~opts as _=?): component => Obj.magic(0)
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
let mockEventTopicOps: MockEventTopic.operations = {
|