arvo-event-handler
Version:
Type-safe event handler system with versioning, telemetry, and contract validation for distributed Arvo event-driven architectures, featuring routing and multi-handler support.
133 lines (132 loc) • 6.82 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MachineExecutionEngine = void 0;
var api_1 = require("@opentelemetry/api");
var arvo_core_1 = require("arvo-core");
var xstate_1 = require("xstate");
/**
* Handles state machine execution, event processing, and lifecycle management.
*/
var MachineExecutionEngine = /** @class */ (function () {
function MachineExecutionEngine() {
}
/**
* Executes a state machine and manages its lifecycle.
*
* @description
* Handles machine initialization/resumption, event processing, and state transitions.
* Manages event queues and volatile context during execution.
*
* @param params Configuration parameters:
* - machine: State machine definition
* - state: Optional existing state to resume from
* - event: Event triggering the execution
* @param opentelemetry Telemetry configuration for tracing
*
* @returns Object containing:
* - state: Final machine state
* - events: Generated events
* - finalOutput: Machine output or null
*
* @throws Error on invalid initialization events or execution failures
*/
MachineExecutionEngine.prototype.execute = function (_a, opentelemetry) {
var machine = _a.machine, state = _a.state, event = _a.event;
if (opentelemetry === void 0) { opentelemetry = {
inheritFrom: 'CONTEXT',
}; }
return arvo_core_1.ArvoOpenTelemetry.getInstance().startActiveSpan({
name: 'Execute Machine',
spanOptions: {
kind: api_1.SpanKind.INTERNAL,
attributes: __assign({ 'arvo.machine.type': machine.source, 'arvo.machine.version': machine.version }, event.otelAttributes),
},
context: opentelemetry.inheritFrom === 'EVENT'
? {
inheritFrom: 'TRACE_HEADERS',
traceHeaders: {
traceparent: event.traceparent,
tracestate: event.tracestate,
},
}
: {
inheritFrom: 'CONTEXT',
context: api_1.context.active(),
},
fn: function () {
var _a, _b, _c, _d, _e, _f, _g;
var eventQueue = [];
var errors = [];
var actor;
if (!state) {
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Starting new orchestration for machine '".concat(machine.source, "' with event type '").concat(event.type, "'"),
});
if (event.type !== machine.source) {
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."));
}
actor = (0, xstate_1.createActor)(machine.logic, {
input: event.toJSON(),
});
actor.on('*', function (event) { return eventQueue.push(event); });
actor.subscribe({ error: function (err) { return errors.push(err); } });
actor.start();
}
else {
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Resuming orchestration for machine '".concat(machine.source, "' from existing state with event '").concat(event.type, "'"),
});
actor = (0, xstate_1.createActor)(machine.logic, {
snapshot: state,
});
actor.on('*', function (event) { return eventQueue.push(event); });
actor.subscribe({ error: function (err) { return errors.push(err); } });
actor.start();
actor.send(event.toJSON());
}
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Machine '".concat(machine.source, "' execution completed successfully with ").concat(eventQueue.length, " queued events"),
});
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Extracting final state snapshot from machine '".concat(machine.source, "'"),
});
var extractedSnapshot = actor.getPersistedSnapshot();
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$$) {
// biome-ignore lint/complexity/noForEach: This is fine
((_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); });
extractedSnapshot.context.arvo$$.volatile$$ = undefined;
}
if (errors.length) {
throw errors[0];
}
var finalOutput = (_f = extractedSnapshot === null || extractedSnapshot === void 0 ? void 0 : extractedSnapshot.output) !== null && _f !== void 0 ? _f : null;
var existingOutput = (_g = state === null || state === void 0 ? void 0 : state.output) !== null && _g !== void 0 ? _g : null;
if (JSON.stringify(finalOutput !== null && finalOutput !== void 0 ? finalOutput : {}) === JSON.stringify(existingOutput !== null && existingOutput !== void 0 ? existingOutput : {})) {
finalOutput = null;
}
return {
state: extractedSnapshot,
events: eventQueue,
finalOutput: finalOutput,
};
},
});
};
return MachineExecutionEngine;
}());
exports.MachineExecutionEngine = MachineExecutionEngine;