UNPKG

n8n

Version:

n8n Workflow Automation Tool

185 lines 7.95 kB
"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.RedisInstanceStorage = void 0; const api_types_1 = require("@n8n/api-types"); const backend_common_1 = require("@n8n/backend-common"); const config_1 = require("@n8n/config"); const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); const redis_client_service_1 = require("../../../services/redis-client.service"); const instance_registry_types_1 = require("../instance-registry.types"); const lua_scripts_1 = require("./lua-scripts"); let RedisInstanceStorage = class RedisInstanceStorage { constructor(logger, globalConfig, redisClientService) { this.kind = 'redis'; this.logger = logger.scoped(['instance-registry', 'redis']); this.redisPrefix = globalConfig.redis.prefix; this.redisClient = redisClientService.createClient({ type: 'registry(n8n)', extraOptions: { commandTimeout: instance_registry_types_1.REGISTRY_CONSTANTS.OPERATION_TIMEOUT_MS }, }); } async register(registration) { await this.upsertRegistration(registration); } async heartbeat(registration) { try { await this.upsertRegistration(registration); } catch (error) { this.logger.warn('Failed to heartbeat instance', { instanceKey: registration.instanceKey, error: (0, n8n_workflow_1.ensureError)(error).message, }); } } async unregister(instanceKey) { try { await this.redisClient.eval(lua_scripts_1.UNREGISTER_SCRIPT, 2, this.instanceKey(instanceKey), this.membershipSetKey()); } catch (error) { this.logger.warn('Failed to unregister instance', { instanceKey, error: (0, n8n_workflow_1.ensureError)(error).message, }); } } async getAllRegistrations() { try { const raw = await this.redisClient.eval(lua_scripts_1.READ_ALL_SCRIPT, 1, this.membershipSetKey()); if (!Array.isArray(raw)) return []; const results = raw.filter((item) => typeof item === 'string'); return results .map((json) => { try { const parsed = api_types_1.instanceRegistrationSchema.safeParse((0, n8n_workflow_1.jsonParse)(json)); if (!parsed.success) { this.logger.warn('Skipping invalid registration entry', { error: parsed.error.message, }); return null; } return parsed.data; } catch (error) { this.logger.warn('Skipping malformed registration entry', { error: (0, n8n_workflow_1.ensureError)(error).message, }); return null; } }) .filter((r) => r !== null); } catch (error) { this.logger.warn('Failed to get all registrations', { error: (0, n8n_workflow_1.ensureError)(error).message, }); return []; } } async getRegistration(instanceKey) { try { const json = await this.redisClient.get(this.instanceKey(instanceKey)); if (json === null) return null; const parsed = api_types_1.instanceRegistrationSchema.safeParse((0, n8n_workflow_1.jsonParse)(json)); if (!parsed.success) { this.logger.warn('Invalid registration data', { instanceKey, error: parsed.error.message, }); return null; } return parsed.data; } catch (error) { this.logger.warn('Failed to get registration', { instanceKey, error: (0, n8n_workflow_1.ensureError)(error).message, }); return null; } } async getLastKnownState() { try { const json = await this.redisClient.get(this.stateKey()); if (json === null) return new Map(); const record = (0, n8n_workflow_1.jsonParse)(json); const state = new Map(); for (const [key, value] of Object.entries(record)) { const parsed = api_types_1.instanceRegistrationSchema.safeParse(value); if (parsed.success) { state.set(key, parsed.data); } else { this.logger.warn('Skipping invalid state entry', { instanceKey: key, error: parsed.error.message, }); } } return state; } catch (error) { this.logger.warn('Failed to get last known state', { error: (0, n8n_workflow_1.ensureError)(error).message, }); return new Map(); } } async saveLastKnownState(state) { try { const record = Object.fromEntries(state); await this.redisClient.set(this.stateKey(), (0, n8n_workflow_1.jsonStringify)(record), 'EX', instance_registry_types_1.REGISTRY_CONSTANTS.STATE_TTL_SECONDS); } catch (error) { this.logger.warn('Failed to save last known state', { error: (0, n8n_workflow_1.ensureError)(error).message, }); } } async cleanupStaleMembers() { try { const removed = await this.redisClient.eval(lua_scripts_1.CLEANUP_SCRIPT, 1, this.membershipSetKey()); return typeof removed === 'number' ? removed : 0; } catch (error) { this.logger.warn('Failed to cleanup stale members', { error: (0, n8n_workflow_1.ensureError)(error).message, }); return 0; } } async destroy() { this.redisClient.disconnect(); } async upsertRegistration(registration) { await this.redisClient.eval(lua_scripts_1.REGISTER_SCRIPT, 2, this.instanceKey(registration.instanceKey), this.membershipSetKey(), (0, n8n_workflow_1.jsonStringify)(registration), String(instance_registry_types_1.REGISTRY_CONSTANTS.REGISTRATION_TTL_SECONDS)); } instanceKey(key) { return instance_registry_types_1.REDIS_KEY_PATTERNS.instanceKey(this.redisPrefix, key); } membershipSetKey() { return instance_registry_types_1.REDIS_KEY_PATTERNS.membershipSet(this.redisPrefix); } stateKey() { return instance_registry_types_1.REDIS_KEY_PATTERNS.stateKey(this.redisPrefix); } }; exports.RedisInstanceStorage = RedisInstanceStorage; exports.RedisInstanceStorage = RedisInstanceStorage = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [backend_common_1.Logger, config_1.GlobalConfig, redis_client_service_1.RedisClientService]) ], RedisInstanceStorage); //# sourceMappingURL=redis-instance-storage.js.map