@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
JavaScript
;
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;