UNPKG

realm-object-server-enterprise

Version:

Realm Object Server Enterprise

170 lines 6.66 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const events = require("events"); const realm_object_server_1 = require("realm-object-server"); var WorkerState; (function (WorkerState) { WorkerState[WorkerState["spare"] = 0] = "spare"; WorkerState[WorkerState["spareslave"] = 1] = "spareslave"; WorkerState[WorkerState["slave"] = 2] = "slave"; WorkerState[WorkerState["master"] = 3] = "master"; })(WorkerState || (WorkerState = {})); class Promoter extends events.EventEmitter { constructor(id, masterKey, slaveKey, csl) { super(); this.logger = new realm_object_server_1.MuteLogger(); const self = this; self.id = id; self.consul = csl; const sessionConfig = { lockdelay: "1s", name: self.id, }; self.mlock = self.consul.lock({ key: masterKey, session: sessionConfig }); self.slock = self.consul.lock({ key: slaveKey, session: sessionConfig }); } setLogger(logger) { this.logger = logger; } start() { const self = this; self.state = WorkerState.spare; process.nextTick(() => this.emit("spare")); self.mlock.on("error", (err, res) => { self.logger.error(`master lock operation failed: ${err}`); }); self.slock.on("error", (err, res) => { self.logger.error(`slave lock operation failed: ${err}`); }); self.mlock.on("acquire", () => { self.logger.debug("master lock aquired"); switch (self.state) { case WorkerState.spare: self.state = WorkerState.master; process.nextTick(() => self.emit("master")); break; case WorkerState.spareslave: case WorkerState.slave: self.state = WorkerState.master; process.nextTick(() => self.emit("master")); self.slock.release(); break; default: self.logger.fatal(`master lock acquired in unexpected state ${WorkerState[self.state]}`); break; } }); self.mlock.on("retry", (err) => __awaiter(this, void 0, void 0, function* () { self.logger.debug("master lock failed"); try { self.masterID = (yield self.consul.session.get({ id: err.leader })).Name; } catch (e) { return self.logger.error(`consul session operation failed: ${e}`); } if (self.masterID === self.id) { return self.logger.warn("master lock is held by someone with the same id, " + "probably a stale session, which should go away in a few seconds"); } self.logger.debug(`master lock is held by ${self.masterID}`); switch (self.state) { case WorkerState.spare: self.state = WorkerState.spareslave; self.slock.acquire(); break; } })); self.mlock.on("end", () => { self.logger.debug("master lock ended"); switch (self.state) { case WorkerState.master: self.state = WorkerState.spare; process.nextTick(() => self.emit("spare")); break; } setTimeout(() => { self.mlock.acquire(); }, 10000); }); self.slock.on("acquire", () => { self.logger.debug("slave lock acquired"); switch (self.state) { case WorkerState.spareslave: self.state = WorkerState.slave; process.nextTick(() => self.emit("slave", self.masterID)); break; } }); self.slock.on("retry", (err) => __awaiter(this, void 0, void 0, function* () { self.logger.debug("slave lock failed"); try { const slaveID = (yield self.consul.session.get({ id: err.leader })).Name; if (slaveID === self.id) { return self.logger.warn("slave lock is held by someone with the same id, " + "probably a stale session, which should go away in a few seconds"); } self.logger.debug(`slave lock is held by ${slaveID}`); } catch (e) { return self.logger.error(`consul session operation failed: ${e}`); } })); self.slock.on("end", () => { self.logger.debug("slave lock ended"); switch (self.state) { case WorkerState.spareslave: self.slock.acquire(); break; case WorkerState.slave: self.state = WorkerState.spare; process.nextTick(() => self.emit("spare")); break; } }); self.mlock.acquire(); } demote() { const self = this; switch (self.state) { case WorkerState.spareslave: case WorkerState.slave: self.state = WorkerState.spare; self.slock.release(); break; case WorkerState.master: self.state = WorkerState.spare; self.mlock.release(); break; } } stop() { const self = this; self.removeAllListeners(); self.mlock.removeAllListeners(); self.slock.removeAllListeners(); self.mlock.on("error", () => { }); self.slock.on("error", () => { }); try { self.mlock.release(); } catch (e) { } try { self.slock.release(); } catch (e) { } } } exports.Promoter = Promoter; //# sourceMappingURL=Promoter.js.map