UNPKG

actionhero

Version:

The reusable, scalable, and quick node.js API server for stateless and stateful applications

146 lines (145 loc) 6.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisInitializer = void 0; const dotProp = require("dot-prop"); const index_1 = require("../index"); /** * Redis helpers and connections. */ class RedisInitializer extends index_1.Initializer { constructor() { super(); this.name = "redis"; this.loadPriority = 200; this.startPriority = 101; this.stopPriority = 99999; } async initialize() { var _a; index_1.api.redis = { clients: {}, subscriptionHandlers: {}, rpcCallbacks: {}, status: { subscribed: false, }, }; index_1.api.redis.subscriptionHandlers.do = async (message) => { if (!message.connectionId || (index_1.api.connections && index_1.api.connections.connections[message.connectionId])) { const cmdParts = message.method.split("."); const cmd = cmdParts.shift(); if (cmd !== "api") { throw new Error("cannot operate on a method outside of the api object"); } const callableApi = Object.assign(index_1.api, { log: index_1.log }); const method = dotProp.get(callableApi, cmdParts.join(".")); let args = message.args; if (args === null) { args = []; } if (!Array.isArray(args)) { args = [args]; } if (method) { const response = await method.apply(null, args); await index_1.redis.respondCluster(message.messageId, response); } else { (0, index_1.log)("RPC method `" + cmdParts.join(".") + "` not found", "crit"); } } }; index_1.api.redis.subscriptionHandlers.doResponse = function (message) { if (index_1.api.redis.rpcCallbacks[message.messageId]) { const { resolve, timer } = index_1.api.redis.rpcCallbacks[message.messageId]; clearTimeout(timer); resolve(message.response); delete index_1.api.redis.rpcCallbacks[message.messageId]; } }; const connectionNames = ["client", "subscriber", "tasks"]; for (const r of connectionNames) { if (index_1.config.redis[r].buildNew === true) { index_1.api.redis.clients[r] = new index_1.config.redis[r].konstructor(...((_a = index_1.config.redis[r].args) !== null && _a !== void 0 ? _a : [])); index_1.api.redis.clients[r].on("error", (error) => { (0, index_1.log)(`Redis connection \`${r}\` error`, "alert", error); }); index_1.api.redis.clients[r].on("connect", () => { (0, index_1.log)(`Redis connection \`${r}\` connected`, "debug"); }); index_1.api.redis.clients[r].on("ready", () => { (0, index_1.log)(`Redis connection \`${r}\` ready`, "debug"); }); index_1.api.redis.clients[r].on("close", () => { (0, index_1.log)(`Redis connection \`${r}\` closed`, "debug"); }); index_1.api.redis.clients[r].on("end", () => { (0, index_1.log)(`Redis connection \`${r}\` ended`, "debug"); }); index_1.api.redis.clients[r].on("reconnecting", () => { (0, index_1.log)(`Redis connection \`${r}\` reconnecting`, "info"); }); } else { index_1.api.redis.clients[r] = index_1.config.redis[r].konstructor(index_1.config.redis[r].args); index_1.api.redis.clients[r].on("error", (error) => { (0, index_1.log)(`Redis connection \`${r}\` error`, "alert", error); }); (0, index_1.log)(`Redis connection \`${r}\` connected`, "debug"); } if (r !== "subscriber") await index_1.api.redis.clients[r].get("_test"); } if (!index_1.api.redis.status.subscribed) { await index_1.api.redis.clients.subscriber.subscribe(index_1.config.general.channel); index_1.api.redis.status.subscribed = true; const messageHandler = async (messageChannel, stringifiedMessage) => { let message; try { message = JSON.parse(stringifiedMessage); } catch (e) { message = {}; } if (messageChannel === index_1.config.general.channel && message.serverToken === index_1.config.general.serverToken) { if (index_1.api.redis.subscriptionHandlers[message.messageType]) { await index_1.api.redis.subscriptionHandlers[message.messageType](message); } } }; index_1.api.redis.clients.subscriber.on("message", messageHandler); } } async start() { await index_1.redis.doCluster("api.log", [ `actionhero member ${index_1.id} has joined the cluster`, ]); } async stop() { await index_1.api.redis.clients.subscriber.unsubscribe(); index_1.api.redis.status.subscribed = false; await index_1.redis.doCluster("api.log", [ `actionhero member ${index_1.id} has left the cluster`, ]); await index_1.utils.sleep(index_1.config.redis.stopTimeout); // allow some time for the goodbye message to propagate const keys = Object.keys(index_1.api.redis.clients); for (const i in keys) { const client = index_1.api.redis.clients[keys[i]]; //@ts-ignore if (typeof client.end === "function") { //@ts-ignore await client.end(); } else if (typeof client.quit === "function") { await client.quit(); } else if (typeof client.disconnect === "function") { await client.disconnect(); } } await index_1.utils.sleep(index_1.config.redis.stopTimeout); // allow some time for the connection to close } } exports.RedisInitializer = RedisInitializer;