UNPKG

node-resque

Version:

an opinionated implementation of resque in node

136 lines (135 loc) 5.13 kB
"use strict"; /// <reference path="./../../node_modules/@types/ioredis/index.d.ts" /> Object.defineProperty(exports, "__esModule", { value: true }); exports.Connection = void 0; const events_1 = require("events"); const IORedis = require("ioredis"); const fs = require("fs"); const path = require("path"); class Connection extends events_1.EventEmitter { constructor(options = {}) { super(); const defaults = { pkg: "ioredis", host: "127.0.0.1", port: 6379, database: 0, namespace: "resque", options: {}, scanCount: 10, }; for (const i in defaults) { if (options[i] === null || options[i] === undefined) { options[i] = defaults[i]; } } this.options = options; this.eventListeners = {}; this.connected = false; } async connect() { const connectionTestAndLoadLua = async () => { try { await this.redis.set(this.key("connection_test_key"), "ok"); const data = await this.redis.get(this.key("connection_test_key")); if (data !== "ok") { throw new Error("cannot read connection test key"); } this.connected = true; this.loadLua(); } catch (error) { this.connected = false; this.emit("error", error); } }; if (this.options.redis) { this.redis = this.options.redis; await connectionTestAndLoadLua(); } else { if (this.options.pkg === "ioredis") { const Pkg = IORedis; this.options.options.db = this.options.database; this.redis = new Pkg(this.options.port, this.options.host, this.options.options); } else { const Pkg = require(this.options.pkg); this.redis = Pkg.createClient(this.options.port, this.options.host, this.options.options); } } this.eventListeners.error = (error) => { this.emit("error", error); }; this.eventListeners.end = () => { this.connected = false; }; this.redis.on("error", (err) => this.eventListeners.error(err)); this.redis.on("end", () => this.eventListeners.end()); if (!this.options.redis) { await this.redis.select(this.options.database); } await connectionTestAndLoadLua(); } loadLua() { const luaDir = path.join(__dirname, "..", "..", "lua"); const files = fs.readdirSync(luaDir); for (const file of files) { const { name } = path.parse(file); const contents = fs.readFileSync(path.join(luaDir, file)).toString(); const lines = contents.split("\n"); // see https://github.com/actionhero/node-resque/issues/465 for why we split only on *nix line breaks const encodedMetadata = lines[0].replace(/^-- /, ""); const metadata = JSON.parse(encodedMetadata); this.redis.defineCommand(name, { numberOfKeys: metadata.numberOfKeys, lua: contents, }); } } async getKeys(match, count = null, keysAry = [], cursor = 0) { if (count === null || count === undefined) { count = this.options.scanCount || 10; } if (this.redis && typeof this.redis.scan === "function") { const [newCursor, matches] = await this.redis.scan(cursor, "match", match, "count", count); if (matches && matches.length > 0) { keysAry = keysAry.concat(matches); } if (newCursor === "0") { return keysAry; } return this.getKeys(match, count, keysAry, parseInt(newCursor)); } this.emit("error", new Error("You must establish a connection to redis before running the getKeys command.")); } end() { Object.keys(this.listeners).forEach((eventName) => { this.redis.removeListener(eventName, this.listeners[eventName]); }); // Only disconnect if we established the redis connection on our own. if (!this.options.redis && this.connected) { if (typeof this.redis.disconnect === "function") { this.redis.disconnect(); } if (typeof this.redis.quit === "function") { this.redis.quit(); } } this.connected = false; } key(arg, arg2, arg3, arg4) { let args; args = arguments.length >= 1 ? [].slice.call(arguments, 0) : []; if (Array.isArray(this.options.namespace)) { args.unshift(...this.options.namespace); } else { args.unshift(this.options.namespace); } args = args.filter((e) => { return String(e).trim(); }); return args.join(":"); } } exports.Connection = Connection;