UNPKG

@hotmeshio/hotmesh

Version:

Permanent-Memory Workflows & AI Agents

159 lines (158 loc) 6.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Interrupt = void 0; const errors_1 = require("../../modules/errors"); const collator_1 = require("../collator"); const pipe_1 = require("../pipe"); const telemetry_1 = require("../telemetry"); const activity_1 = require("./activity"); class Interrupt 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('interrupt-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); if (this.isInterruptingSelf()) { await this.interruptSelf(telemetry); } else { await this.interruptAnother(telemetry); } } catch (error) { if (error instanceof errors_1.InactiveJobError) { this.logger.error('interrupt-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('interrupt-get-state-error', { error }); return; } else if (error instanceof errors_1.CollationError) { if (error.fault === 'duplicate') { this.logger.info('interrupt-collation-overage', { job_id: this.context.metadata.jid, guid: this.context.metadata.guid, }); return; } //unknown collation error this.logger.error('interrupt-collation-error', { error }); } else { this.logger.error('interrupt-process-error', { error }); } telemetry?.setActivityError(error.message); throw error; } finally { telemetry?.endActivitySpan(); this.logger.debug('interrupt-process-end', { jid: this.context.metadata.jid, gid: this.context.metadata.gid, aid: this.metadata.aid, }); } } async interruptSelf(telemetry) { // Apply final updates to THIS job's state if (this.config.job?.maps) { this.mapJobData(); await this.setState(); } // Interrupt THIS job const messageId = await this.interrupt(); // Notarize completion and log telemetry.mapActivityAttributes(); const transaction = this.store.transact(); await collator_1.CollatorService.notarizeEarlyCompletion(this, transaction); await this.setStatus(-1, transaction); const txResponse = (await transaction.exec()); const jobStatus = this.resolveStatus(txResponse); telemetry.setActivityAttributes({ 'app.activity.mid': messageId, 'app.job.jss': jobStatus, }); return this.context.metadata.aid; } async interruptAnother(telemetry) { // Interrupt ANOTHER job const messageId = await this.interrupt(); const attrs = { 'app.activity.mid': messageId }; // Apply updates to THIS job's state telemetry.mapActivityAttributes(); this.adjacencyList = await this.filterAdjacent(); if (this.config.job?.maps || this.config.output?.maps) { this.mapOutputData(); this.mapJobData(); const transaction = this.store.transact(); await this.setState(transaction); } // Notarize completion const transaction = this.store.transact(); await collator_1.CollatorService.notarizeEarlyCompletion(this, transaction); await this.setStatus(this.adjacencyList.length - 1, transaction); const txResponse = (await transaction.exec()); const jobStatus = this.resolveStatus(txResponse); attrs['app.job.jss'] = jobStatus; // Transition next generation and log const messageIds = await this.transition(this.adjacencyList, jobStatus); if (messageIds.length) { attrs['app.activity.mids'] = messageIds.join(','); } telemetry.setActivityAttributes(attrs); return this.context.metadata.aid; } isInterruptingSelf() { if (!this.config.target) { return true; } const resolvedJob = pipe_1.Pipe.resolve(this.config.target, this.context); return resolvedJob == this.context.metadata.jid; } resolveInterruptOptions() { return { reason: this.config.reason !== undefined ? pipe_1.Pipe.resolve(this.config.reason, this.context) : undefined, throw: this.config.throw !== undefined ? pipe_1.Pipe.resolve(this.config.throw, this.context) : undefined, descend: this.config.descend !== undefined ? pipe_1.Pipe.resolve(this.config.descend, this.context) : undefined, code: this.config.code !== undefined ? pipe_1.Pipe.resolve(this.config.code, this.context) : undefined, expire: this.config.expire !== undefined ? pipe_1.Pipe.resolve(this.config.expire, this.context) : undefined, stack: this.config.stack !== undefined ? pipe_1.Pipe.resolve(this.config.stack, this.context) : undefined, }; } async interrupt() { const options = this.resolveInterruptOptions(); return await this.engine.interrupt(this.config.topic !== undefined ? pipe_1.Pipe.resolve(this.config.topic, this.context) : this.context.metadata.tpc, this.config.target !== undefined ? pipe_1.Pipe.resolve(this.config.target, this.context) : this.context.metadata.jid, options); } } exports.Interrupt = Interrupt;