UNPKG

@socket.io/redis-streams-adapter

Version:

The Socket.IO adapter based on Redis Streams, allowing to broadcast events between several Socket.IO servers

161 lines (160 loc) 4.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GETDEL = exports.SET = exports.XRANGE = exports.XADD = exports.XREAD = exports.hasBinary = void 0; function hasBinary(obj, toJSON) { if (!obj || typeof obj !== "object") { return false; } if (obj instanceof ArrayBuffer || ArrayBuffer.isView(obj)) { return true; } if (Array.isArray(obj)) { for (let i = 0, l = obj.length; i < l; i++) { if (hasBinary(obj[i])) { return true; } } return false; } for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key) && hasBinary(obj[key])) { return true; } } if (obj.toJSON && typeof obj.toJSON === "function" && !toJSON) { return hasBinary(obj.toJSON(), true); } return false; } exports.hasBinary = hasBinary; /** * Whether the client comes from the `redis` package * * @param redisClient * * @see https://github.com/redis/node-redis */ function isRedisV4Client(redisClient) { return typeof redisClient.sSubscribe === "function"; } /** * Map the output of the XREAD/XRANGE command with the ioredis package to the format of the redis package * @param result */ function mapResult(result) { const id = result[0]; const inlineValues = result[1]; const message = {}; for (let i = 0; i < inlineValues.length; i += 2) { message[inlineValues[i]] = inlineValues[i + 1]; } return { id, message, }; } /** * @see https://redis.io/commands/xread/ */ function XREAD(redisClient, streamName, offset, readCount) { if (isRedisV4Client(redisClient)) { return Promise.resolve().then(() => require("redis")).then((redisPackage) => { return redisClient.xRead(redisPackage.commandOptions({ isolated: true, }), [ { key: streamName, id: offset, }, ], { COUNT: readCount, BLOCK: 5000, }); }); } else { return redisClient .xread("BLOCK", 100, "COUNT", readCount, "STREAMS", streamName, offset) .then((results) => { if (results === null) { return null; } return [ { messages: results[0][1].map(mapResult), }, ]; }); } } exports.XREAD = XREAD; /** * @see https://redis.io/commands/xadd/ */ function XADD(redisClient, streamName, payload, maxLenThreshold) { if (isRedisV4Client(redisClient)) { return redisClient.xAdd(streamName, "*", payload, { TRIM: { strategy: "MAXLEN", strategyModifier: "~", threshold: maxLenThreshold, }, }); } else { const args = [streamName, "MAXLEN", "~", maxLenThreshold, "*"]; Object.keys(payload).forEach((k) => { args.push(k, payload[k]); }); return redisClient.xadd.call(redisClient, args); } } exports.XADD = XADD; /** * @see https://redis.io/commands/xrange/ */ function XRANGE(redisClient, streamName, start, end) { if (isRedisV4Client(redisClient)) { return redisClient.xRange(streamName, start, end); } else { return redisClient.xrange(streamName, start, end).then((res) => { return res.map(mapResult); }); } } exports.XRANGE = XRANGE; /** * @see https://redis.io/commands/set/ */ function SET(redisClient, key, value, expiryInSeconds) { if (isRedisV4Client(redisClient)) { return redisClient.set(key, value, { PX: expiryInSeconds, }); } else { return redisClient.set(key, value, "PX", expiryInSeconds); } } exports.SET = SET; /** * @see https://redis.io/commands/getdel/ */ function GETDEL(redisClient, key) { if (isRedisV4Client(redisClient)) { // note: GETDEL was added in Redis version 6.2 return redisClient.multi().get(key).del(key).exec(); } else { return redisClient .multi() .get(key) .del(key) .exec() .then((res) => { return [res[0][1]]; }); } } exports.GETDEL = GETDEL;