n8n
Version:
n8n Workflow Automation Tool
148 lines • 6.46 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.N8NCheckpointStorage = void 0;
const backend_common_1 = require("@n8n/backend-common");
const config_1 = require("@n8n/config");
const constants_1 = require("@n8n/constants");
const decorators_1 = require("@n8n/decorators");
const di_1 = require("@n8n/di");
const n8n_core_1 = require("n8n-core");
const n8n_workflow_1 = require("n8n-workflow");
const node_assert_1 = require("node:assert");
const agent_checkpoint_repository_1 = require("../repositories/agent-checkpoint.repository");
let N8NCheckpointStorage = class N8NCheckpointStorage {
constructor(instanceSettings, agentCheckpointRepository, logger, agentsConfig, moduleRegistry) {
this.instanceSettings = instanceSettings;
this.agentCheckpointRepository = agentCheckpointRepository;
this.logger = logger;
this.agentsConfig = agentsConfig;
this.moduleRegistry = moduleRegistry;
this.isStopping = false;
this.isInitialized = false;
this.logger = this.logger.scoped('agents');
this.isInitialized = this.moduleRegistry.isActive('agents');
}
getStorage(agentId) {
return {
save: async (key, state) => await this.save(key, state, agentId),
load: async (key) => await this.load(key),
delete: async (key) => await this.delete(key),
};
}
init() {
(0, node_assert_1.strict)(this.instanceSettings.instanceRole !== 'unset', 'Instance role is not set');
if (this.instanceSettings.isLeader)
this.startPruning();
}
async save(key, state, agentId = null) {
const existing = await this.agentCheckpointRepository.findOneBy({ runId: key });
if (existing) {
existing.state = JSON.stringify(state);
existing.expired = false;
await this.agentCheckpointRepository.save(existing);
}
else {
const checkpoint = this.agentCheckpointRepository.create({
runId: key,
agentId,
state: JSON.stringify(state),
expired: false,
});
await this.agentCheckpointRepository.save(checkpoint);
}
}
async load(key) {
const checkpoint = await this.agentCheckpointRepository.findOneBy({ runId: key });
if (!checkpoint)
return undefined;
if (checkpoint.expired || checkpoint.state === null) {
throw new n8n_workflow_1.UserError('This action has expired and cannot be resumed');
}
return (0, n8n_workflow_1.jsonParse)(checkpoint.state);
}
async getStatus(key) {
const checkpoint = await this.agentCheckpointRepository.findOneBy({ runId: key });
if (!checkpoint)
return { status: 'not-found' };
if (checkpoint.expired || checkpoint.state === null)
return { status: 'expired' };
return { status: 'active', checkpoint: (0, n8n_workflow_1.jsonParse)(checkpoint.state) };
}
async delete(key) {
await this.agentCheckpointRepository.update({ runId: key }, { expired: true, state: null });
}
startPruning() {
this.isStopping = false;
this.scheduleNextPrune(0);
}
stopPruning() {
clearTimeout(this.pruneTimeout);
this.pruneTimeout = undefined;
}
shutdown() {
this.isStopping = true;
this.stopPruning();
}
scheduleNextPrune(delayMs = constants_1.Time.hours.toMilliseconds) {
if (this.isStopping || !this.isInitialized)
return;
this.pruneTimeout = setTimeout(async () => {
await this.pruneStaleSuspensions();
}, delayMs);
}
async pruneStaleSuspensions() {
const ttlMs = this.agentsConfig.checkpointTtlSeconds * constants_1.Time.seconds.toMilliseconds;
const cutoffDate = new Date(Date.now() - ttlMs);
try {
const count = await this.agentCheckpointRepository.markExpired(cutoffDate);
if (count > 0) {
this.logger.info('Marked stale agent checkpoints as expired', { count });
}
else {
this.logger.debug('No stale agent checkpoints to expire');
}
this.scheduleNextPrune();
}
catch (error) {
this.logger.warn('Failed to expire stale agent checkpoints', { error });
this.scheduleNextPrune(constants_1.Time.seconds.toMilliseconds * 30);
}
}
};
exports.N8NCheckpointStorage = N8NCheckpointStorage;
__decorate([
(0, decorators_1.OnLeaderTakeover)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], N8NCheckpointStorage.prototype, "startPruning", null);
__decorate([
(0, decorators_1.OnLeaderStepdown)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], N8NCheckpointStorage.prototype, "stopPruning", null);
__decorate([
(0, decorators_1.OnShutdown)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], N8NCheckpointStorage.prototype, "shutdown", null);
exports.N8NCheckpointStorage = N8NCheckpointStorage = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [n8n_core_1.InstanceSettings,
agent_checkpoint_repository_1.AgentCheckpointRepository,
backend_common_1.Logger,
config_1.AgentsConfig,
backend_common_1.ModuleRegistry])
], N8NCheckpointStorage);
//# sourceMappingURL=n8n-checkpoint-storage.js.map