UNPKG

node-resque

Version:

an opinionated implementation of resque in node

130 lines (129 loc) 5.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Connection = void 0; const events_1 = require("events"); const fs = require("fs"); const path = require("path"); class Connection extends events_1.EventEmitter { constructor(options = {}) { var _a, _b, _c, _d, _e, _f, _g; super(); options.pkg = (_a = options.pkg) !== null && _a !== void 0 ? _a : "ioredis"; options.host = (_b = options.host) !== null && _b !== void 0 ? _b : "127.0.0.1"; options.port = (_c = options.port) !== null && _c !== void 0 ? _c : 6379; options.database = (_d = options.database) !== null && _d !== void 0 ? _d : 0; options.namespace = (_e = options.namespace) !== null && _e !== void 0 ? _e : "resque"; options.scanCount = (_f = options.scanCount) !== null && _f !== void 0 ? _f : 10; options.options = (_g = options.options) !== null && _g !== void 0 ? _g : {}; 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; } else { const Pkg = require(this.options.pkg); if (typeof Pkg.createClient === "function" && this.options.pkg !== "ioredis") { this.redis = Pkg.createClient(this.options.port, this.options.host, this.options.options); } else { this.options.options.db = this.options.database; this.redis = new Pkg(this.options.port, this.options.host, this.options.options); } } this.eventListeners.error = (error) => { this.emit("error", error); }; this.eventListeners.end = () => { this.connected = false; }; Object.entries(this.eventListeners).forEach(([eventName, eventHandler]) => { this.redis.on(eventName, eventHandler); }); if (!this.options.redis && typeof this.redis.select === "function") { await this.redis.select(this.options.database); } await connectionTestAndLoadLua(); } loadLua() { // even though ioredis-mock can run LUA, cjson is not available if (this.options.pkg === "ioredis-mock") return; 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.entries(this.eventListeners).forEach(([eventName, eventHandler]) => { this.redis.off(eventName, eventHandler); }); // 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;