From dd81dd03e0987fb8bee0353c0d2e86f76bbb7dcc Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Tue, 11 May 2021 12:18:45 -0600
Subject: [PATCH] fix(#9508): switch to ioredis (#9545)
* switch to ioredis
also need this fix in redisearch:
redis-search.js:98
```
redisClient.multi(cmds).exec(function(err, ids) {
if (err) {
return callback(err);
}
var errRes = ids[resultIndex];
if (errRes[0]) {
return callback(errRes[0]);
}
callback(null, errRes[1]);
});
```
* dbsearch compatible with ioredis
* fixed dbsearch?
---
install/package.json | 6 +++---
src/database/redis/connection.js | 37 ++++++++++++++++----------------
src/database/redis/hash.js | 8 +++++++
src/database/redis/helpers.js | 11 ++++++----
src/database/redis/sets.js | 3 +++
5 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/install/package.json b/install/package.json
index d734338dbc..cdd65a8581 100644
--- a/install/package.json
+++ b/install/package.json
@@ -85,7 +85,7 @@
"@nodebb/bootswatch": "3.4.2",
"nconf": "^0.11.2",
"nodebb-plugin-composer-default": "6.5.27",
- "nodebb-plugin-dbsearch": "4.2.0",
+ "nodebb-plugin-dbsearch": "5.0.1",
"nodebb-plugin-emoji": "^3.5.0",
"nodebb-plugin-emoji-android": "2.0.5",
"nodebb-plugin-markdown": "8.12.10",
@@ -107,7 +107,7 @@
"postcss": "8.2.15",
"postcss-clean": "1.2.0",
"prompt": "^1.1.0",
- "redis": "3.1.2",
+ "ioredis": "4.27.2",
"request": "2.88.2",
"request-promise-native": "^1.0.9",
"requirejs": "2.3.6",
@@ -182,4 +182,4 @@
"url": "https://github.com/barisusakli"
}
]
-}
\ No newline at end of file
+}
diff --git a/src/database/redis/connection.js b/src/database/redis/connection.js
index 6e685eadcf..1c8179a346 100644
--- a/src/database/redis/connection.js
+++ b/src/database/redis/connection.js
@@ -1,37 +1,34 @@
'use strict';
const nconf = require('nconf');
-const redis = require('redis');
+const Redis = require('ioredis');
const winston = require('winston');
-const _ = require('lodash');
const connection = module.exports;
-connection.getConnectionOptions = function (redis) {
- redis = redis || nconf.get('redis');
- const connOptions = {};
- if (redis.password) {
- connOptions.auth_pass = redis.password;
- }
- if (redis.hasOwnProperty('database')) {
- connOptions.db = redis.database;
- }
- return _.merge(connOptions, redis.options || {});
-};
-
connection.connect = async function (options) {
return new Promise((resolve, reject) => {
options = options || nconf.get('redis');
const redis_socket_or_host = options.host;
- const connOptions = connection.getConnectionOptions(options);
let cxn;
if (redis_socket_or_host && String(redis_socket_or_host).indexOf('/') >= 0) {
- /* If redis.host contains a path name character, use the unix dom sock connection. ie, /tmp/redis.sock */
- cxn = redis.createClient(options.host, connOptions);
+ // If redis.host contains a path name character, use the unix dom sock connection. ie, /tmp/redis.sock
+ cxn = new Redis({
+ ...options.options,
+ path: redis_socket_or_host,
+ password: options.password,
+ db: options.database,
+ });
} else {
- /* Else, connect over tcp/ip */
- cxn = redis.createClient(options.port, options.host, connOptions);
+ // Else, connect over tcp/ip
+ cxn = new Redis({
+ ...options.options,
+ host: redis_socket_or_host,
+ port: options.port,
+ password: options.password,
+ db: options.database,
+ });
}
const dbIdx = parseInt(options.database, 10);
@@ -44,6 +41,8 @@ connection.connect = async function (options) {
reject(err);
});
cxn.on('ready', () => {
+ // back-compat with node_redis
+ cxn.batch = cxn.pipeline;
resolve(cxn);
});
diff --git a/src/database/redis/hash.js b/src/database/redis/hash.js
index 42a1fccffc..24630ba371 100644
--- a/src/database/redis/hash.js
+++ b/src/database/redis/hash.js
@@ -111,6 +111,14 @@ module.exports = function (module) {
data = [await module.client.async.hgetall(unCachedKeys[0])];
}
+ // convert empty objects into null for back-compat with node_redis
+ data = data.map((elem) => {
+ if (!Object.keys(elem).length) {
+ return null;
+ }
+ return elem;
+ });
+
unCachedKeys.forEach((key, i) => {
cachedData[key] = data[i] || null;
cache.set(key, cachedData[key]);
diff --git a/src/database/redis/helpers.js b/src/database/redis/helpers.js
index 30b440d4e2..8961da8255 100644
--- a/src/database/redis/helpers.js
+++ b/src/database/redis/helpers.js
@@ -1,14 +1,17 @@
'use strict';
-const util = require('util');
-
const helpers = module.exports;
helpers.noop = function () {};
helpers.execBatch = async function (batch) {
- const proFn = util.promisify(batch.exec).bind(batch);
- return await proFn();
+ const results = await batch.exec();
+ return results.map(([err, res]) => {
+ if (err) {
+ throw err;
+ }
+ return res;
+ });
};
helpers.resultsToBool = function (results) {
diff --git a/src/database/redis/sets.js b/src/database/redis/sets.js
index 2146e1ae5e..a0431995a4 100644
--- a/src/database/redis/sets.js
+++ b/src/database/redis/sets.js
@@ -29,6 +29,9 @@ module.exports = function (module) {
if (!Array.isArray(key)) {
key = [key];
}
+ if (!value.length) {
+ return;
+ }
const batch = module.client.batch();
key.forEach(k => batch.srem(String(k), value));