UNPKG

n8n

Version:

n8n Workflow Automation Tool

102 lines (99 loc) 4.34 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.LeaderElectionClient = void 0; const redis_client_service_1 = require("../services/redis-client.service"); const config_1 = require("@n8n/config"); const di_1 = require("@n8n/di"); const n8n_core_1 = require("n8n-core"); const n8n_workflow_1 = require("n8n-workflow"); const COMMAND_TIMEOUT_MS = 5_000; const INCREASE_TTL_IF_LEADER = ` -- Renew only if we still hold the lock local currentValue = redis.call("GET", KEYS[1]) if not currentValue then return -1 end if currentValue ~= ARGV[1] then return currentValue end return redis.call("EXPIRE", KEYS[1], tonumber(ARGV[2])) `; let LeaderElectionClient = class LeaderElectionClient { get hostId() { return this.instanceSettings.hostId; } constructor(instanceSettings, globalConfig, redisClientService) { this.instanceSettings = instanceSettings; const prefix = redisClientService.toValidPrefix(globalConfig.redis.prefix); this.leaderKey = prefix + ':main_instance_leader'; this.leaderKeyTtlInS = globalConfig.multiMainSetup.ttl; this.redisClient = redisClientService.createClient({ type: 'leader(n8n)', extraOptions: { commandTimeout: COMMAND_TIMEOUT_MS }, }); } async getLeader() { try { return (0, n8n_workflow_1.createResultOk)(await this.redisClient.get(this.leaderKey)); } catch (e) { return (0, n8n_workflow_1.createResultError)((0, n8n_workflow_1.ensureError)(e)); } } async setLeaderIfNotExists() { try { const result = await this.redisClient.set(this.leaderKey, this.hostId, 'EX', this.leaderKeyTtlInS, 'NX'); return (0, n8n_workflow_1.createResultOk)(result === 'OK'); } catch (e) { return (0, n8n_workflow_1.createResultError)((0, n8n_workflow_1.ensureError)(e)); } } async tryRenewLeaderTtl() { try { const result = await this.redisClient.eval(INCREASE_TTL_IF_LEADER, 1, this.leaderKey, this.hostId, this.leaderKeyTtlInS); if (result === -1 || result === 0) { return (0, n8n_workflow_1.createResultOk)({ id: 'key-missing' }); } if (result === 1) { return (0, n8n_workflow_1.createResultOk)({ id: 'success' }); } if (typeof result === 'string') { return (0, n8n_workflow_1.createResultOk)({ id: 'other-host-is-leader', currentLeaderId: result }); } return (0, n8n_workflow_1.createResultError)(new Error(`Unexpected result from Redis script: ${JSON.stringify(result)}`)); } catch (e) { return (0, n8n_workflow_1.createResultError)((0, n8n_workflow_1.ensureError)(e)); } } async clearLeader() { try { await this.redisClient.del(this.leaderKey); return (0, n8n_workflow_1.createResultOk)(undefined); } catch (e) { return (0, n8n_workflow_1.createResultError)((0, n8n_workflow_1.ensureError)(e)); } } destroy() { this.redisClient.disconnect(); } }; exports.LeaderElectionClient = LeaderElectionClient; exports.LeaderElectionClient = LeaderElectionClient = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [n8n_core_1.InstanceSettings, config_1.GlobalConfig, redis_client_service_1.RedisClientService]) ], LeaderElectionClient); //# sourceMappingURL=leader-election-client.js.map