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));