realm-object-server-enterprise
Version:
Realm Object Server Enterprise
170 lines • 6.66 kB
JavaScript
;
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