arvo-event-handler
Version:
A complete set of orthogonal event handler and orchestration primitives for Arvo based applications, featuring declarative state machines (XState), imperative resumables for agentic workflows, contract-based routing, OpenTelemetry observability, and in-me
185 lines (184 loc) • 9.32 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.processRawEventsIntoEmittables = exports.createEmittableEvent = void 0;
var arvo_core_1 = require("arvo-core");
var ArvoDomain_1 = require("../ArvoDomain");
var errors_1 = require("../errors");
/**
* Creates a fully-formed emittable event from raw event parameters.
*
* Transforms machine-emitted event data into valid Arvo events by:
* - Validating against appropriate contracts (self or service)
* - Resolving domains for routing
* - Generating proper subjects for orchestration events
* - Adding tracing context and metadata
*
* Handles three event types differently:
* 1. Completion events - routed to workflow initiator with parent subject
* 2. Service orchestrator events - creates/extends orchestration subjects
* 3. Regular service events - standard external service calls
*
* @returns Fully-formed Arvo event ready for emission
* @throws {ContractViolation} When event data fails schema validation
* @throws {ExecutionViolation} When orchestration subject creation fails
*/
var createEmittableEvent = function (_a, span) {
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
var event = _a.event, otelHeaders = _a.otelHeaders, orchestrationParentSubject = _a.orchestrationParentSubject, sourceEvent = _a.sourceEvent, selfContract = _a.selfContract, serviceContracts = _a.serviceContracts, initEventId = _a.initEventId, _domain = _a.domain, executionunits = _a.executionunits, source = _a.source;
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Creating emittable event: ".concat(event.type),
}, span);
var serviceContractMap = Object.fromEntries(Object.values(serviceContracts).map(function (item) { return [
item.accepts.type,
item,
]; }));
var schema = null;
var contract = null;
var subject = sourceEvent.subject;
var parentId = sourceEvent.id;
var domain = (0, ArvoDomain_1.resolveEventDomain)({
domainToResolve: _domain,
parentSubject: orchestrationParentSubject,
currentSubject: sourceEvent.subject,
handlerSelfContract: selfContract,
eventContract: null,
triggeringEvent: sourceEvent,
});
if (event.type === selfContract.metadata.completeEventType) {
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Creating event for workflow completion: ".concat(event.type),
}, span);
contract = selfContract;
schema = selfContract.emits[selfContract.metadata.completeEventType];
subject = orchestrationParentSubject !== null && orchestrationParentSubject !== void 0 ? orchestrationParentSubject : sourceEvent.subject;
parentId = initEventId;
domain = (0, ArvoDomain_1.resolveEventDomain)({
domainToResolve: _domain,
parentSubject: orchestrationParentSubject,
currentSubject: sourceEvent.subject,
handlerSelfContract: selfContract,
eventContract: selfContract,
triggeringEvent: sourceEvent,
});
}
else if (serviceContractMap[event.type]) {
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Creating service event for external system: ".concat(event.type),
}, span);
contract = serviceContractMap[event.type];
schema = serviceContractMap[event.type].accepts.schema;
domain = (0, ArvoDomain_1.resolveEventDomain)({
domainToResolve: _domain,
parentSubject: orchestrationParentSubject,
currentSubject: sourceEvent.subject,
handlerSelfContract: selfContract,
eventContract: contract,
triggeringEvent: sourceEvent,
});
if (contract.metadata.contractType === 'ArvoOrchestratorContract') {
if (event.data.parentSubject$$) {
try {
arvo_core_1.ArvoOrchestrationSubject.parse(event.data.parentSubject$$);
}
catch (_o) {
throw new errors_1.ExecutionViolation("[Emittable Event Creation] Invalid parentSubject$$ for the event(type='".concat(event.type, "', uri='").concat((_b = event.dataschema) !== null && _b !== void 0 ? _b : arvo_core_1.EventDataschemaUtil.create(contract), "'). It must be follow the ArvoOrchestrationSubject schema. The easiest way is to use the current orchestration subject by storing the subject via the context block in the machine definition."));
}
}
try {
if (event.data.parentSubject$$) {
subject = arvo_core_1.ArvoOrchestrationSubject.from({
orchestator: contract.accepts.type,
version: contract.version,
subject: event.data.parentSubject$$,
domain: domain !== null && domain !== void 0 ? domain : null,
meta: {
redirectto: (_c = event.redirectto) !== null && _c !== void 0 ? _c : source,
},
});
}
else {
subject = arvo_core_1.ArvoOrchestrationSubject.new({
version: contract.version,
orchestator: contract.accepts.type,
initiator: source,
domain: domain !== null && domain !== void 0 ? domain : undefined,
meta: {
redirectto: (_d = event.redirectto) !== null && _d !== void 0 ? _d : source,
},
});
}
}
catch (error) {
throw new errors_1.ExecutionViolation("[Emittable Event Creation] Orchestration subject creation failed due to invalid parameters - Event: ".concat(event.type, " - ").concat(error === null || error === void 0 ? void 0 : error.message));
}
}
}
var finalDataschema = event.dataschema;
var finalData = event.data;
if (contract && schema) {
try {
finalData = schema.parse(event.data);
finalDataschema = arvo_core_1.EventDataschemaUtil.create(contract);
}
catch (error) {
throw new errors_1.ContractViolation("[Emittable Event Creation] Invalid event data: Schema validation failed.\nEvent type: ".concat(event.type, "\nDetails: ").concat(error.message));
}
}
var emittableEvent = (0, arvo_core_1.createArvoEvent)({
id: event.id,
source: source,
type: event.type,
subject: subject,
dataschema: finalDataschema !== null && finalDataschema !== void 0 ? finalDataschema : undefined,
data: finalData,
to: (_e = event.to) !== null && _e !== void 0 ? _e : event.type,
accesscontrol: (_g = (_f = event.accesscontrol) !== null && _f !== void 0 ? _f : sourceEvent.accesscontrol) !== null && _g !== void 0 ? _g : undefined,
redirectto: (_h = event.redirectto) !== null && _h !== void 0 ? _h : source,
executionunits: (_j = event.executionunits) !== null && _j !== void 0 ? _j : executionunits,
traceparent: (_k = otelHeaders.traceparent) !== null && _k !== void 0 ? _k : undefined,
tracestate: (_l = otelHeaders.tracestate) !== null && _l !== void 0 ? _l : undefined,
parentid: parentId,
domain: domain !== null && domain !== void 0 ? domain : undefined,
}, (_m = event.__extensions) !== null && _m !== void 0 ? _m : {});
(0, arvo_core_1.logToSpan)({
level: 'INFO',
message: "Event created successfully: ".concat(emittableEvent.type),
}, span);
return emittableEvent;
};
exports.createEmittableEvent = createEmittableEvent;
/**
* Processes raw events into emittable events with domain resolution
*/
var processRawEventsIntoEmittables = function (params, span) {
var _a;
var emittables = [];
for (var _i = 0, _b = params.rawEvents; _i < _b.length; _i++) {
var item = _b[_i];
for (var _c = 0, _d = Array.from(new Set((_a = item.domain) !== null && _a !== void 0 ? _a : [ArvoDomain_1.ArvoDomain.LOCAL])); _c < _d.length; _c++) {
var _dom = _d[_c];
var evt = (0, exports.createEmittableEvent)({
event: item,
otelHeaders: params.otelHeaders,
orchestrationParentSubject: params.orchestrationParentSubject,
sourceEvent: params.sourceEvent,
selfContract: params.selfContract,
serviceContracts: params.serviceContracts,
initEventId: params.initEventId,
domain: _dom,
executionunits: params.executionunits,
source: params.source,
}, span);
emittables.push(evt);
for (var _e = 0, _f = Object.entries(emittables[emittables.length - 1].otelAttributes); _e < _f.length; _e++) {
var _g = _f[_e], key = _g[0], value = _g[1];
span.setAttribute("emittables.".concat(emittables.length - 1, ".").concat(key), value);
}
}
}
return emittables;
};
exports.processRawEventsIntoEmittables = processRawEventsIntoEmittables;