@hotmeshio/hotmesh
Version:
Permanent-Memory Workflows & AI Agents
113 lines (112 loc) • 4.75 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cycle = void 0;
const errors_1 = require("../../modules/errors");
const utils_1 = require("../../modules/utils");
const collator_1 = require("../collator");
const telemetry_1 = require("../telemetry");
const activity_1 = require("./activity");
class Cycle extends activity_1.Activity {
constructor(config, data, metadata, hook, engine, context) {
super(config, data, metadata, hook, engine, context);
}
//******** LEG 1 ENTRY ********//
async process() {
this.logger.debug('cycle-process', {
jid: this.context.metadata.jid,
gid: this.context.metadata.gid,
aid: this.metadata.aid,
});
let telemetry;
try {
await this.verifyEntry();
telemetry = new telemetry_1.TelemetryService(this.engine.appId, this.config, this.metadata, this.context);
telemetry.startActivitySpan(this.leg);
this.mapInputData();
//set state/status
let transaction = this.store.transact();
await this.setState(transaction);
await this.setStatus(0, transaction); //leg 1 never changes job status
const txResponse = (await transaction.exec());
telemetry.mapActivityAttributes();
const jobStatus = this.resolveStatus(txResponse);
//cycle the target ancestor
transaction = this.store.transact();
const messageId = await this.cycleAncestorActivity(transaction);
telemetry.setActivityAttributes({
'app.activity.mid': messageId,
'app.job.jss': jobStatus,
});
//exit early (`Cycle` activities only execute Leg 1)
await collator_1.CollatorService.notarizeEarlyExit(this, transaction);
(await transaction.exec());
return this.context.metadata.aid;
}
catch (error) {
if (error instanceof errors_1.InactiveJobError) {
this.logger.error('cycle-inactive-job-error', { error });
return;
}
else if (error instanceof errors_1.GenerationalError) {
this.logger.info('process-event-generational-job-error', { error });
return;
}
else if (error instanceof errors_1.GetStateError) {
this.logger.error('cycle-get-state-error', { error });
return;
}
else if (error instanceof errors_1.CollationError) {
if (error.fault === 'duplicate') {
this.logger.info('cycle-collation-overage', {
job_id: this.context.metadata.jid,
guid: this.context.metadata.guid,
});
return;
}
//unknown collation error
this.logger.error('cycle-collation-error', { error });
}
else {
this.logger.error('cycle-process-error', { error });
}
telemetry?.setActivityError(error.message);
throw error;
}
finally {
telemetry?.endActivitySpan();
this.logger.debug('cycle-process-end', {
jid: this.context.metadata.jid,
gid: this.context.metadata.gid,
aid: this.metadata.aid,
});
}
}
/**
* Trigger the target ancestor to execute in a cycle,
* without violating the constraints of the DAG. Immutable
* `individual activity state` will execute in a new dimensional
* thread while `shared job state` can change. This
* pattern allows for retries without violating the DAG.
*/
async cycleAncestorActivity(transaction) {
//Cycle activity L1 is a standin for the target ancestor L1.
//Input data mapping (mapInputData) allows for the
//next dimensonal thread to execute with different
//input data than the current dimensional thread
this.mapInputData();
const streamData = {
metadata: {
guid: (0, utils_1.guid)(),
jid: this.context.metadata.jid,
gid: this.context.metadata.gid,
dad: collator_1.CollatorService.resolveReentryDimension(this),
aid: this.config.ancestor,
spn: this.context['$self'].output.metadata?.l1s,
trc: this.context.metadata.trc,
},
data: this.context.data,
};
return (await this.engine.router?.publishMessage(null, streamData, transaction));
}
}
exports.Cycle = Cycle;