arvo-event-handler 2.3.3 → 3.0.1
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/dist/AbstractArvoEventHandler/index.d.ts +1 -1
- package/dist/ArvoEventHandler/helpers.d.ts +40 -6
- package/dist/ArvoEventHandler/helpers.js +40 -6
- package/dist/ArvoEventHandler/index.d.ts +78 -49
- package/dist/ArvoEventHandler/index.js +151 -82
- package/dist/ArvoEventHandler/types.d.ts +25 -2
- package/dist/ArvoMachine/createMachine.d.ts +208 -0
- package/dist/ArvoMachine/createMachine.js +283 -0
- package/dist/ArvoMachine/index.d.ts +93 -0
- package/dist/ArvoMachine/index.js +160 -0
- package/dist/ArvoMachine/types.d.ts +194 -0
- package/dist/ArvoMachine/utils.d.ts +40 -0
- package/dist/ArvoMachine/utils.js +70 -0
- package/dist/ArvoOrchestrator/error.d.ts +16 -0
- package/dist/ArvoOrchestrator/error.js +43 -0
- package/dist/ArvoOrchestrator/factory.d.ts +28 -0
- package/dist/ArvoOrchestrator/factory.js +56 -0
- package/dist/ArvoOrchestrator/index.d.ts +69 -0
- package/dist/ArvoOrchestrator/index.js +597 -0
- package/dist/ArvoOrchestrator/types.d.ts +98 -0
- package/dist/ArvoResumable/factory.d.ts +50 -0
- package/dist/ArvoResumable/factory.js +70 -0
- package/dist/ArvoResumable/index.d.ts +141 -0
- package/dist/ArvoResumable/index.js +694 -0
- package/dist/ArvoResumable/types.d.ts +147 -0
- package/dist/ArvoResumable/types.js +2 -0
- package/dist/MachineExecutionEngine/index.d.ts +29 -0
- package/dist/MachineExecutionEngine/index.js +132 -0
- package/dist/MachineExecutionEngine/interface.d.ts +14 -0
- package/dist/MachineExecutionEngine/interface.js +2 -0
- package/dist/MachineExecutionEngine/types.d.ts +14 -0
- package/dist/MachineExecutionEngine/types.js +2 -0
- package/dist/MachineMemory/Simple.d.ts +51 -0
- package/dist/MachineMemory/Simple.js +158 -0
- package/dist/MachineMemory/TelemetredSimple.d.ts +51 -0
- package/dist/MachineMemory/TelemetredSimple.js +230 -0
- package/dist/MachineMemory/interface.d.ts +57 -0
- package/dist/MachineMemory/interface.js +2 -0
- package/dist/MachineMemory/utils.d.ts +1 -0
- package/dist/MachineMemory/utils.js +18 -0
- package/dist/MachineRegistry/index.d.ts +37 -0
- package/dist/MachineRegistry/index.js +87 -0
- package/dist/MachineRegistry/interface.d.ts +21 -0
- package/dist/MachineRegistry/interface.js +2 -0
- package/dist/SyncEventResource/index.d.ts +110 -0
- package/dist/SyncEventResource/index.js +280 -0
- package/dist/SyncEventResource/types.d.ts +2 -0
- package/dist/SyncEventResource/types.js +2 -0
- package/dist/index.d.ts +26 -8
- package/dist/index.js +39 -16
- package/dist/utils/SimpleEventBroker/helper.d.ts +166 -0
- package/dist/utils/SimpleEventBroker/helper.js +276 -0
- package/dist/utils/SimpleEventBroker/index.d.ts +96 -0
- package/dist/utils/SimpleEventBroker/index.js +259 -0
- package/dist/utils/SimpleEventBroker/types.d.ts +6 -0
- package/dist/utils/SimpleEventBroker/types.js +2 -0
- package/dist/utils/SimpleEventBroker/utils.d.ts +1 -0
- package/dist/utils/SimpleEventBroker/utils.js +10 -0
- package/dist/{utils.d.ts → utils/index.d.ts} +3 -36
- package/dist/utils/index.js +91 -0
- package/dist/utils/object/index.d.ts +37 -0
- package/dist/utils/object/index.js +63 -0
- package/package.json +5 -3
- package/dist/ArvoEventRouter/helpers.d.ts +0 -19
- package/dist/ArvoEventRouter/helpers.js +0 -22
- package/dist/ArvoEventRouter/index.d.ts +0 -89
- package/dist/ArvoEventRouter/index.js +0 -268
- package/dist/ArvoEventRouter/types.d.ts +0 -36
- package/dist/ArvoEventRouter/utils.d.ts +0 -30
- package/dist/ArvoEventRouter/utils.js +0 -43
- package/dist/MultiArvoEventHandler/helpers.d.ts +0 -48
- package/dist/MultiArvoEventHandler/helpers.js +0 -56
- package/dist/MultiArvoEventHandler/index.d.ts +0 -68
- package/dist/MultiArvoEventHandler/index.js +0 -205
- package/dist/MultiArvoEventHandler/types.d.ts +0 -64
- package/dist/utils.js +0 -191
- /package/dist/{ArvoEventRouter → ArvoMachine}/types.js +0 -0
- /package/dist/{MultiArvoEventHandler → ArvoOrchestrator}/types.js +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { VersionedArvoContract, ArvoSemanticVersion, InferVersionedArvoContract, ArvoContract, ArvoEvent, InferArvoEvent } from 'arvo-core';
|
|
2
|
+
import type { EnqueueArvoEventActionParam } from '../ArvoMachine/types';
|
|
3
|
+
import type { Span } from '@opentelemetry/api';
|
|
4
|
+
type ExtractServiceEventTypes<TServiceContract extends Record<string, VersionedArvoContract<any, any>>> = {
|
|
5
|
+
[K in keyof TServiceContract]: {
|
|
6
|
+
[L in keyof InferVersionedArvoContract<TServiceContract[K]>['emits']]: {
|
|
7
|
+
type: InferVersionedArvoContract<TServiceContract[K]>['emits'][L]['type'];
|
|
8
|
+
event: InferVersionedArvoContract<TServiceContract[K]>['emits'][L];
|
|
9
|
+
};
|
|
10
|
+
}[keyof InferVersionedArvoContract<TServiceContract[K]>['emits']] | {
|
|
11
|
+
type: InferVersionedArvoContract<TServiceContract[K]>['systemError']['type'];
|
|
12
|
+
event: InferVersionedArvoContract<TServiceContract[K]>['systemError'];
|
|
13
|
+
};
|
|
14
|
+
}[keyof TServiceContract];
|
|
15
|
+
type AllServiceEventTypes<TServiceContract extends Record<string, VersionedArvoContract<any, any>>> = ExtractServiceEventTypes<TServiceContract>['type'];
|
|
16
|
+
type ServiceEventTypeMap<TServiceContract extends Record<string, VersionedArvoContract<any, any>>> = {
|
|
17
|
+
[T in ExtractServiceEventTypes<TServiceContract> as T['type']]: T['event'];
|
|
18
|
+
};
|
|
19
|
+
type Handler<TState extends ArvoResumableState<Record<string, any>>, TSelfContract extends VersionedArvoContract<any, any>, TServiceContract extends Record<string, VersionedArvoContract<any, any>>> = (param: {
|
|
20
|
+
span: Span;
|
|
21
|
+
metadata: Omit<TState, 'state$$'> | null;
|
|
22
|
+
collectedEvents: Partial<{
|
|
23
|
+
[K in AllServiceEventTypes<TServiceContract>]: ServiceEventTypeMap<TServiceContract>[K][];
|
|
24
|
+
}>;
|
|
25
|
+
context: TState['state$$'] | null;
|
|
26
|
+
input: InferVersionedArvoContract<TSelfContract>['accepts'] | null;
|
|
27
|
+
service: {
|
|
28
|
+
[K in keyof TServiceContract]: {
|
|
29
|
+
[L in keyof InferVersionedArvoContract<TServiceContract[K]>['emits']]: InferVersionedArvoContract<TServiceContract[K]>['emits'][L];
|
|
30
|
+
}[keyof InferVersionedArvoContract<TServiceContract[K]>['emits']] | InferVersionedArvoContract<TServiceContract[K]>['systemError'];
|
|
31
|
+
}[keyof TServiceContract] | null;
|
|
32
|
+
contracts: {
|
|
33
|
+
self: TSelfContract;
|
|
34
|
+
services: TServiceContract;
|
|
35
|
+
};
|
|
36
|
+
}) => Promise<{
|
|
37
|
+
context?: TState['state$$'];
|
|
38
|
+
output?: {
|
|
39
|
+
[L in keyof InferVersionedArvoContract<TSelfContract>['emits']]: EnqueueArvoEventActionParam<InferVersionedArvoContract<TSelfContract>['emits'][L]['data'], InferVersionedArvoContract<TSelfContract>['emits'][L]['type']>['data'];
|
|
40
|
+
}[keyof InferVersionedArvoContract<TSelfContract>['emits']];
|
|
41
|
+
services?: Array<{
|
|
42
|
+
[K in keyof TServiceContract]: EnqueueArvoEventActionParam<InferVersionedArvoContract<TServiceContract[K]>['accepts']['data'], InferVersionedArvoContract<TServiceContract[K]>['accepts']['type']>;
|
|
43
|
+
}[keyof TServiceContract]>;
|
|
44
|
+
} | void>;
|
|
45
|
+
/**
|
|
46
|
+
* The versioned orchestration handlers in ArvoResumable workflows
|
|
47
|
+
*
|
|
48
|
+
* It maps each version of an orchestrator contract to its corresponding handler function.
|
|
49
|
+
* Each handler receives workflow context (state, events, contracts) and returns execution results
|
|
50
|
+
* that can update state, complete the workflow, or invoke external services.
|
|
51
|
+
*
|
|
52
|
+
* The handler is called for each event that matches the orchestrator's contract, whether it's
|
|
53
|
+
* an initialization event or a service response. The handler must be deterministic and
|
|
54
|
+
* idempotent to ensure reliable workflow execution across potential retries.
|
|
55
|
+
*
|
|
56
|
+
* @param param - Handler execution context
|
|
57
|
+
* @param param.span - OpenTelemetry span for distributed tracing
|
|
58
|
+
* @param param.metadata - Complete workflow metadata (null for new workflows)
|
|
59
|
+
* @param param.collectedEvents - Type-safe map of event types to their corresponding typed event arrays,
|
|
60
|
+
* enabling strongly-typed access with full IntelliSense support.
|
|
61
|
+
* @param param.context - Current workflow state (null for new workflows)
|
|
62
|
+
* @param param.init - Initialization event data (only present for workflow start events)
|
|
63
|
+
* @param param.service - Service response event data (only present for service callbacks)
|
|
64
|
+
* @param param.contracts - Available contracts for type validation and event creation
|
|
65
|
+
* @param param.contracts.self - The orchestrator's own versioned contract
|
|
66
|
+
* @param param.contracts.services - External service contracts for invocation
|
|
67
|
+
*
|
|
68
|
+
* @returns Promise resolving to execution result or void
|
|
69
|
+
* @returns result.context - Updated workflow state to persist
|
|
70
|
+
* @returns result.complete - Workflow completion event to emit (ends the workflow)
|
|
71
|
+
* @returns result.services - Array of service invocation events to emit
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* - Each version key must match a valid semantic version in the self contract
|
|
75
|
+
* - Handlers should be pure functions without side effects beyond the returned actions
|
|
76
|
+
* - State updates are atomic - either all changes persist or none do
|
|
77
|
+
* - Only one of `init` or `service` will be non-null for any given invocation
|
|
78
|
+
* - Returning void or an empty object indicates no state changes or events to emit
|
|
79
|
+
* - Service events are supposed to queued for execution and may trigger callback events
|
|
80
|
+
* - Completion events terminate the workflow and route to the parent orchestrator
|
|
81
|
+
*/
|
|
82
|
+
export type ArvoResumableHandler<TState extends ArvoResumableState<Record<string, any>>, TSelfContract extends ArvoContract, TServiceContract extends Record<string, VersionedArvoContract<any, any>>> = {
|
|
83
|
+
[V in ArvoSemanticVersion & keyof TSelfContract['versions']]: Handler<TState, VersionedArvoContract<TSelfContract, V>, TServiceContract>;
|
|
84
|
+
};
|
|
85
|
+
export type ArvoResumableState<T extends Record<string, any>> = {
|
|
86
|
+
/**
|
|
87
|
+
* Current execution status of the orchestration workflow
|
|
88
|
+
*
|
|
89
|
+
* This field tracks the lifecycle state of the workflow instance to determine
|
|
90
|
+
* whether it can accept new events and continue processing or has reached
|
|
91
|
+
* its terminal state.
|
|
92
|
+
*
|
|
93
|
+
* @remarks
|
|
94
|
+
* - **active**: The workflow is running and can accept events for processing.
|
|
95
|
+
* It may be waiting for service responses, processing initialization events,
|
|
96
|
+
* or handling intermediate workflow steps. The orchestrator will continue
|
|
97
|
+
* to route events to active workflows.
|
|
98
|
+
*
|
|
99
|
+
* - **done**: The workflow has completed its execution lifecycle. This status
|
|
100
|
+
* is set when the handler returns a `complete` event, indicating the workflow
|
|
101
|
+
* has finished successfully. Done workflows will not process additional events
|
|
102
|
+
* and their state is preserved for audit/debugging purposes.
|
|
103
|
+
*/
|
|
104
|
+
status: 'active' | 'done';
|
|
105
|
+
/** Unique identifier for the machine instance */
|
|
106
|
+
subject: string;
|
|
107
|
+
/**
|
|
108
|
+
* Reference to the parent orchestration's subject when orchestrations are nested or chained.
|
|
109
|
+
* This enables hierarchical orchestration patterns where one orchestration can spawn
|
|
110
|
+
* sub-orchestrations. When the current orchestration completes, its completion event
|
|
111
|
+
* is routed back to this parent subject rather than staying within the current context.
|
|
112
|
+
*
|
|
113
|
+
* - For root orchestrations: null
|
|
114
|
+
* - For nested orchestrations: contains the subject of the parent orchestration
|
|
115
|
+
* - Extracted from the `parentSubject$$` field in initialization events
|
|
116
|
+
*/
|
|
117
|
+
parentSubject: string | null;
|
|
118
|
+
/**
|
|
119
|
+
* The unique identifier of the event that originally initiated this entire orchestration workflow.
|
|
120
|
+
* This serves as the root identifier for tracking the complete execution chain from start to finish.
|
|
121
|
+
*
|
|
122
|
+
* - For new orchestrations: set to the current event's ID
|
|
123
|
+
* - For resumed orchestrations: retrieved from the stored state
|
|
124
|
+
* - Used as the `parentid` for completion events to create a direct lineage back to the workflow's origin
|
|
125
|
+
*
|
|
126
|
+
* This enables tracing the entire execution path and ensures completion events reference
|
|
127
|
+
* the original triggering event rather than just the immediate previous step.
|
|
128
|
+
*/
|
|
129
|
+
initEventId: string;
|
|
130
|
+
events: {
|
|
131
|
+
/** The event consumed by the machine in the last session */
|
|
132
|
+
consumed: InferArvoEvent<ArvoEvent> | null;
|
|
133
|
+
/**
|
|
134
|
+
* The domained events produced by the machine in the last session
|
|
135
|
+
*/
|
|
136
|
+
produced: InferArvoEvent<ArvoEvent>[];
|
|
137
|
+
/**
|
|
138
|
+
* The events expected by the resumable. These events are collected on each execution
|
|
139
|
+
* as long as the event parent id and the expected key matches. The expected key is the
|
|
140
|
+
* event.id of the produced event.
|
|
141
|
+
*/
|
|
142
|
+
expected: Record<string, InferArvoEvent<ArvoEvent>[]> | null;
|
|
143
|
+
};
|
|
144
|
+
/** The state used by the resumable */
|
|
145
|
+
state$$: T | null;
|
|
146
|
+
};
|
|
147
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { IMachineExectionEngine } from './interface';
|
|
2
|
+
import type { ExecuteMachineInput, ExecuteMachineOutput } from './types';
|
|
3
|
+
import type { ArvoEventHandlerOpenTelemetryOptions } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Handles state machine execution, event processing, and lifecycle management.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MachineExecutionEngine implements IMachineExectionEngine {
|
|
8
|
+
/**
|
|
9
|
+
* Executes a state machine and manages its lifecycle.
|
|
10
|
+
*
|
|
11
|
+
* @description
|
|
12
|
+
* Handles machine initialization/resumption, event processing, and state transitions.
|
|
13
|
+
* Manages event queues and volatile context during execution.
|
|
14
|
+
*
|
|
15
|
+
* @param params Configuration parameters:
|
|
16
|
+
* - machine: State machine definition
|
|
17
|
+
* - state: Optional existing state to resume from
|
|
18
|
+
* - event: Event triggering the execution
|
|
19
|
+
* @param opentelemetry Telemetry configuration for tracing
|
|
20
|
+
*
|
|
21
|
+
* @returns Object containing:
|
|
22
|
+
* - state: Final machine state
|
|
23
|
+
* - events: Generated events
|
|
24
|
+
* - finalOutput: Machine output or null
|
|
25
|
+
*
|
|
26
|
+
* @throws Error on invalid initialization events or execution failures
|
|
27
|
+
*/
|
|
28
|
+
execute({ machine, state, event }: ExecuteMachineInput, opentelemetry?: ArvoEventHandlerOpenTelemetryOptions): ExecuteMachineOutput;
|
|
29
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.MachineExecutionEngine = void 0;
|
|
15
|
+
var api_1 = require("@opentelemetry/api");
|
|
16
|
+
var arvo_core_1 = require("arvo-core");
|
|
17
|
+
var xstate_1 = require("xstate");
|
|
18
|
+
/**
|
|
19
|
+
* Handles state machine execution, event processing, and lifecycle management.
|
|
20
|
+
*/
|
|
21
|
+
var MachineExecutionEngine = /** @class */ (function () {
|
|
22
|
+
function MachineExecutionEngine() {
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Executes a state machine and manages its lifecycle.
|
|
26
|
+
*
|
|
27
|
+
* @description
|
|
28
|
+
* Handles machine initialization/resumption, event processing, and state transitions.
|
|
29
|
+
* Manages event queues and volatile context during execution.
|
|
30
|
+
*
|
|
31
|
+
* @param params Configuration parameters:
|
|
32
|
+
* - machine: State machine definition
|
|
33
|
+
* - state: Optional existing state to resume from
|
|
34
|
+
* - event: Event triggering the execution
|
|
35
|
+
* @param opentelemetry Telemetry configuration for tracing
|
|
36
|
+
*
|
|
37
|
+
* @returns Object containing:
|
|
38
|
+
* - state: Final machine state
|
|
39
|
+
* - events: Generated events
|
|
40
|
+
* - finalOutput: Machine output or null
|
|
41
|
+
*
|
|
42
|
+
* @throws Error on invalid initialization events or execution failures
|
|
43
|
+
*/
|
|
44
|
+
MachineExecutionEngine.prototype.execute = function (_a, opentelemetry) {
|
|
45
|
+
var machine = _a.machine, state = _a.state, event = _a.event;
|
|
46
|
+
if (opentelemetry === void 0) { opentelemetry = {
|
|
47
|
+
inheritFrom: 'CONTEXT',
|
|
48
|
+
}; }
|
|
49
|
+
return arvo_core_1.ArvoOpenTelemetry.getInstance().startActiveSpan({
|
|
50
|
+
name: 'Execute Machine',
|
|
51
|
+
spanOptions: {
|
|
52
|
+
kind: api_1.SpanKind.INTERNAL,
|
|
53
|
+
attributes: __assign({ 'arvo.machine.type': machine.source, 'arvo.machine.version': machine.version }, event.otelAttributes),
|
|
54
|
+
},
|
|
55
|
+
context: opentelemetry.inheritFrom === 'EVENT'
|
|
56
|
+
? {
|
|
57
|
+
inheritFrom: 'TRACE_HEADERS',
|
|
58
|
+
traceHeaders: {
|
|
59
|
+
traceparent: event.traceparent,
|
|
60
|
+
tracestate: event.tracestate,
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
: {
|
|
64
|
+
inheritFrom: 'CONTEXT',
|
|
65
|
+
context: api_1.context.active(),
|
|
66
|
+
},
|
|
67
|
+
fn: function () {
|
|
68
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
69
|
+
var eventQueue = [];
|
|
70
|
+
var errors = [];
|
|
71
|
+
var actor;
|
|
72
|
+
if (!state) {
|
|
73
|
+
(0, arvo_core_1.logToSpan)({
|
|
74
|
+
level: 'INFO',
|
|
75
|
+
message: "Starting new orchestration for machine '".concat(machine.source, "' with event type '").concat(event.type, "'"),
|
|
76
|
+
});
|
|
77
|
+
if (event.type !== machine.source) {
|
|
78
|
+
throw new Error("Invalid initialization event: Machine requires source event '".concat(machine.source, "' to start, but received event '").concat(event.type, "' instead. This likely indicates a mismatch between the expected workflow trigger and the actual event sent."));
|
|
79
|
+
}
|
|
80
|
+
actor = (0, xstate_1.createActor)(machine.logic, {
|
|
81
|
+
input: event.toJSON(),
|
|
82
|
+
});
|
|
83
|
+
actor.on('*', function (event) { return eventQueue.push(event); });
|
|
84
|
+
actor.subscribe({ error: function (err) { return errors.push(err); } });
|
|
85
|
+
actor.start();
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
(0, arvo_core_1.logToSpan)({
|
|
89
|
+
level: 'INFO',
|
|
90
|
+
message: "Resuming orchestration for machine '".concat(machine.source, "' from existing state with event '").concat(event.type, "'"),
|
|
91
|
+
});
|
|
92
|
+
actor = (0, xstate_1.createActor)(machine.logic, {
|
|
93
|
+
snapshot: state,
|
|
94
|
+
});
|
|
95
|
+
actor.on('*', function (event) { return eventQueue.push(event); });
|
|
96
|
+
actor.subscribe({ error: function (err) { return errors.push(err); } });
|
|
97
|
+
actor.start();
|
|
98
|
+
actor.send(event.toJSON());
|
|
99
|
+
}
|
|
100
|
+
(0, arvo_core_1.logToSpan)({
|
|
101
|
+
level: 'INFO',
|
|
102
|
+
message: "Machine '".concat(machine.source, "' execution completed successfully with ").concat(eventQueue.length, " queued events"),
|
|
103
|
+
});
|
|
104
|
+
(0, arvo_core_1.logToSpan)({
|
|
105
|
+
level: 'INFO',
|
|
106
|
+
message: "Extracting final state snapshot from machine '".concat(machine.source, "'"),
|
|
107
|
+
});
|
|
108
|
+
var extractedSnapshot = actor.getPersistedSnapshot();
|
|
109
|
+
if ((_b = (_a = extractedSnapshot === null || extractedSnapshot === void 0 ? void 0 : extractedSnapshot.context) === null || _a === void 0 ? void 0 : _a.arvo$$) === null || _b === void 0 ? void 0 : _b.volatile$$) {
|
|
110
|
+
// biome-ignore lint/complexity/noForEach: TODO - fix it later
|
|
111
|
+
((_e = (_d = (_c = extractedSnapshot === null || extractedSnapshot === void 0 ? void 0 : extractedSnapshot.context) === null || _c === void 0 ? void 0 : _c.arvo$$) === null || _d === void 0 ? void 0 : _d.volatile$$) === null || _e === void 0 ? void 0 : _e.eventQueue$$).forEach(function (item) { return eventQueue.push(item); });
|
|
112
|
+
extractedSnapshot.context.arvo$$.volatile$$ = undefined;
|
|
113
|
+
}
|
|
114
|
+
if (errors.length) {
|
|
115
|
+
throw errors[0];
|
|
116
|
+
}
|
|
117
|
+
var finalOutput = (_f = extractedSnapshot === null || extractedSnapshot === void 0 ? void 0 : extractedSnapshot.output) !== null && _f !== void 0 ? _f : null;
|
|
118
|
+
var existingOutput = (_g = state === null || state === void 0 ? void 0 : state.output) !== null && _g !== void 0 ? _g : null;
|
|
119
|
+
if (JSON.stringify(finalOutput !== null && finalOutput !== void 0 ? finalOutput : {}) === JSON.stringify(existingOutput !== null && existingOutput !== void 0 ? existingOutput : {})) {
|
|
120
|
+
finalOutput = null;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
state: extractedSnapshot,
|
|
124
|
+
events: eventQueue,
|
|
125
|
+
finalOutput: finalOutput,
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
return MachineExecutionEngine;
|
|
131
|
+
}());
|
|
132
|
+
exports.MachineExecutionEngine = MachineExecutionEngine;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ArvoEventHandlerOpenTelemetryOptions } from '../types';
|
|
2
|
+
import type { ExecuteMachineInput, ExecuteMachineOutput } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Interface defining a machine execution engine.
|
|
5
|
+
*/
|
|
6
|
+
export interface IMachineExectionEngine {
|
|
7
|
+
/**
|
|
8
|
+
* Executes a state machine and processes events.
|
|
9
|
+
* @param param - Input parameters for machine execution
|
|
10
|
+
* @param opentelemetry - Telemetry configuration options
|
|
11
|
+
* @returns Machine execution results including state and events
|
|
12
|
+
*/
|
|
13
|
+
execute: (param: ExecuteMachineInput, opentelemetry: ArvoEventHandlerOpenTelemetryOptions) => ExecuteMachineOutput;
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ArvoEvent } from 'arvo-core';
|
|
2
|
+
import type { Snapshot } from 'xstate';
|
|
3
|
+
import type ArvoMachine from '../ArvoMachine';
|
|
4
|
+
import type { EnqueueArvoEventActionParam } from '../ArvoMachine/types';
|
|
5
|
+
export type ExecuteMachineInput = {
|
|
6
|
+
machine: ArvoMachine<any, any, any, any, any>;
|
|
7
|
+
state: Snapshot<any> | null;
|
|
8
|
+
event: ArvoEvent;
|
|
9
|
+
};
|
|
10
|
+
export type ExecuteMachineOutput = {
|
|
11
|
+
state: Snapshot<any>;
|
|
12
|
+
events: EnqueueArvoEventActionParam[];
|
|
13
|
+
finalOutput: any;
|
|
14
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { IMachineMemory } from './interface';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory implementation of machine state storage for single-instance NodeJS apps.
|
|
4
|
+
*
|
|
5
|
+
* Best for: Container apps, request-scoped workflows, testing, demos
|
|
6
|
+
* Not for: Multi-instance deployments, persistent workflows, distributed systems
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const memory = new SimpleMachineMemory();
|
|
10
|
+
* const orchestrator = createArvoOrchestrator({
|
|
11
|
+
* memory,
|
|
12
|
+
* executionunits: 1,
|
|
13
|
+
* machines: [workflow]
|
|
14
|
+
* });
|
|
15
|
+
*/
|
|
16
|
+
export declare class SimpleMachineMemory<T extends Record<string, any> = Record<string, any>> implements IMachineMemory<T> {
|
|
17
|
+
private readonly memoryMap;
|
|
18
|
+
private readonly lockMap;
|
|
19
|
+
/**
|
|
20
|
+
* Gets stored state for a machine instance
|
|
21
|
+
* @param id Machine instance ID
|
|
22
|
+
* @returns State data or null if not found
|
|
23
|
+
* @throws {Error} When id is empty or undefined
|
|
24
|
+
*/
|
|
25
|
+
read(id: string): Promise<T | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Stores state for a machine instance
|
|
28
|
+
* @param id Machine instance ID
|
|
29
|
+
* @param data State to store
|
|
30
|
+
* @throws {Error} When id is empty/undefined or data is null/undefined
|
|
31
|
+
*/
|
|
32
|
+
write(id: string, data: T): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Attempts to acquire lock for machine instance
|
|
35
|
+
* @param id Machine instance ID
|
|
36
|
+
* @returns Success status of lock acquisition
|
|
37
|
+
* @throws {Error} When id is empty or undefined
|
|
38
|
+
*/
|
|
39
|
+
lock(id: string): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Releases lock for machine instance
|
|
42
|
+
* @param id Machine instance ID
|
|
43
|
+
* @returns True when lock is released
|
|
44
|
+
* @throws {Error} When id is empty or undefined
|
|
45
|
+
*/
|
|
46
|
+
unlock(id: string): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Clears all stored data and locks
|
|
49
|
+
*/
|
|
50
|
+
clear(key?: string): void;
|
|
51
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.SimpleMachineMemory = void 0;
|
|
51
|
+
/**
|
|
52
|
+
* In-memory implementation of machine state storage for single-instance NodeJS apps.
|
|
53
|
+
*
|
|
54
|
+
* Best for: Container apps, request-scoped workflows, testing, demos
|
|
55
|
+
* Not for: Multi-instance deployments, persistent workflows, distributed systems
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const memory = new SimpleMachineMemory();
|
|
59
|
+
* const orchestrator = createArvoOrchestrator({
|
|
60
|
+
* memory,
|
|
61
|
+
* executionunits: 1,
|
|
62
|
+
* machines: [workflow]
|
|
63
|
+
* });
|
|
64
|
+
*/
|
|
65
|
+
var SimpleMachineMemory = /** @class */ (function () {
|
|
66
|
+
function SimpleMachineMemory() {
|
|
67
|
+
this.memoryMap = new Map();
|
|
68
|
+
this.lockMap = new Map();
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Gets stored state for a machine instance
|
|
72
|
+
* @param id Machine instance ID
|
|
73
|
+
* @returns State data or null if not found
|
|
74
|
+
* @throws {Error} When id is empty or undefined
|
|
75
|
+
*/
|
|
76
|
+
SimpleMachineMemory.prototype.read = function (id) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
78
|
+
var _a;
|
|
79
|
+
return __generator(this, function (_b) {
|
|
80
|
+
if (!id) {
|
|
81
|
+
throw new Error('Machine ID is required for read operation');
|
|
82
|
+
}
|
|
83
|
+
return [2 /*return*/, (_a = this.memoryMap.get(id)) !== null && _a !== void 0 ? _a : null];
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Stores state for a machine instance
|
|
89
|
+
* @param id Machine instance ID
|
|
90
|
+
* @param data State to store
|
|
91
|
+
* @throws {Error} When id is empty/undefined or data is null/undefined
|
|
92
|
+
*/
|
|
93
|
+
SimpleMachineMemory.prototype.write = function (id, data) {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
95
|
+
return __generator(this, function (_a) {
|
|
96
|
+
if (!id) {
|
|
97
|
+
throw new Error('Machine ID is required for write operation');
|
|
98
|
+
}
|
|
99
|
+
if (!data) {
|
|
100
|
+
throw new Error('Data is required for write operation');
|
|
101
|
+
}
|
|
102
|
+
this.memoryMap.set(id, __assign({}, data));
|
|
103
|
+
return [2 /*return*/];
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Attempts to acquire lock for machine instance
|
|
109
|
+
* @param id Machine instance ID
|
|
110
|
+
* @returns Success status of lock acquisition
|
|
111
|
+
* @throws {Error} When id is empty or undefined
|
|
112
|
+
*/
|
|
113
|
+
SimpleMachineMemory.prototype.lock = function (id) {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
115
|
+
return __generator(this, function (_a) {
|
|
116
|
+
if (!id) {
|
|
117
|
+
throw new Error('Machine ID is required for lock operation');
|
|
118
|
+
}
|
|
119
|
+
if (this.lockMap.get(id)) {
|
|
120
|
+
return [2 /*return*/, false];
|
|
121
|
+
}
|
|
122
|
+
this.lockMap.set(id, true);
|
|
123
|
+
return [2 /*return*/, true];
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Releases lock for machine instance
|
|
129
|
+
* @param id Machine instance ID
|
|
130
|
+
* @returns True when lock is released
|
|
131
|
+
* @throws {Error} When id is empty or undefined
|
|
132
|
+
*/
|
|
133
|
+
SimpleMachineMemory.prototype.unlock = function (id) {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
135
|
+
return __generator(this, function (_a) {
|
|
136
|
+
if (!id) {
|
|
137
|
+
throw new Error('Machine ID is required for unlock operation');
|
|
138
|
+
}
|
|
139
|
+
this.lockMap.delete(id);
|
|
140
|
+
return [2 /*return*/, !this.lockMap.get(id)];
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Clears all stored data and locks
|
|
146
|
+
*/
|
|
147
|
+
SimpleMachineMemory.prototype.clear = function (key) {
|
|
148
|
+
if (key) {
|
|
149
|
+
this.memoryMap.delete(key);
|
|
150
|
+
this.lockMap.delete(key);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
this.memoryMap.clear();
|
|
154
|
+
this.lockMap.clear();
|
|
155
|
+
};
|
|
156
|
+
return SimpleMachineMemory;
|
|
157
|
+
}());
|
|
158
|
+
exports.SimpleMachineMemory = SimpleMachineMemory;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { IMachineMemory } from './interface';
|
|
2
|
+
/**
|
|
3
|
+
* A telemetred In-memory implementation of machine state storage for single-instance NodeJS apps.
|
|
4
|
+
*
|
|
5
|
+
* Best for: Container apps, request-scoped workflows, testing, demos
|
|
6
|
+
* Not for: Multi-instance deployments, persistent workflows, distributed systems
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const memory = new TelemetredSimpleMachineMemory();
|
|
10
|
+
* const orchestrator = createArvoOrchestrator({
|
|
11
|
+
* memory,
|
|
12
|
+
* executionunits: 0.1,
|
|
13
|
+
* machines: [workflow]
|
|
14
|
+
* });
|
|
15
|
+
*/
|
|
16
|
+
export declare class TelemetredSimpleMachineMemory<T extends Record<string, any> = Record<string, any>> implements IMachineMemory<T> {
|
|
17
|
+
private readonly memoryMap;
|
|
18
|
+
private readonly lockMap;
|
|
19
|
+
/**
|
|
20
|
+
* Gets stored state for a machine instance
|
|
21
|
+
* @param id Machine instance ID
|
|
22
|
+
* @returns State data or null if not found
|
|
23
|
+
* @throws {Error} When id is empty or undefined
|
|
24
|
+
*/
|
|
25
|
+
read(id: string): Promise<T | null>;
|
|
26
|
+
/**
|
|
27
|
+
* Stores state for a machine instance
|
|
28
|
+
* @param id Machine instance ID
|
|
29
|
+
* @param data State to store
|
|
30
|
+
* @throws {Error} When id is empty/undefined or data is null/undefined
|
|
31
|
+
*/
|
|
32
|
+
write(id: string, data: T): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Attempts to acquire lock for machine instance
|
|
35
|
+
* @param id Machine instance ID
|
|
36
|
+
* @returns Success status of lock acquisition
|
|
37
|
+
* @throws {Error} When id is empty or undefined
|
|
38
|
+
*/
|
|
39
|
+
lock(id: string): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Releases lock for machine instance
|
|
42
|
+
* @param id Machine instance ID
|
|
43
|
+
* @returns True when lock is released
|
|
44
|
+
* @throws {Error} When id is empty or undefined
|
|
45
|
+
*/
|
|
46
|
+
unlock(id: string): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Clears all stored data and locks
|
|
49
|
+
*/
|
|
50
|
+
clear(key?: string): void;
|
|
51
|
+
}
|