mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-07 22:45:46 +01:00
Node redis (#13500)
* refactor: start migrating to node-redis * few more zset fixes * fix: db.scan * fix: list methods * fix set methods * fix: hash methods * use hasOwn, remove cloning * sorted set fixes * fix: so data is converted to strings before saving otherwise node-redis throws below error TypeError: "arguments[2]" must be of type "string | Buffer", got number instead. * chore: remove comments * fix: zrank string param * use new close * chore: up dbsearch * test: add log * test: more log * test: log failing test * test: catch errors in formatApiResponse add await so exception goes to catch * tetst: add log * fix: dont set null/undefined values * test: more fixes
This commit is contained in:
@@ -98,7 +98,7 @@
|
|||||||
"nconf": "0.13.0",
|
"nconf": "0.13.0",
|
||||||
"nodebb-plugin-2factor": "7.5.10",
|
"nodebb-plugin-2factor": "7.5.10",
|
||||||
"nodebb-plugin-composer-default": "10.2.51",
|
"nodebb-plugin-composer-default": "10.2.51",
|
||||||
"nodebb-plugin-dbsearch": "6.2.19",
|
"nodebb-plugin-dbsearch": "6.3.0",
|
||||||
"nodebb-plugin-emoji": "6.0.3",
|
"nodebb-plugin-emoji": "6.0.3",
|
||||||
"nodebb-plugin-emoji-android": "4.1.1",
|
"nodebb-plugin-emoji-android": "4.1.1",
|
||||||
"nodebb-plugin-markdown": "13.2.1",
|
"nodebb-plugin-markdown": "13.2.1",
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
"postcss-clean": "1.2.0",
|
"postcss-clean": "1.2.0",
|
||||||
"progress-webpack-plugin": "1.0.16",
|
"progress-webpack-plugin": "1.0.16",
|
||||||
"prompt": "1.3.0",
|
"prompt": "1.3.0",
|
||||||
"ioredis": "5.6.1",
|
"redis": "5.5.6",
|
||||||
"rimraf": "6.0.1",
|
"rimraf": "6.0.1",
|
||||||
"rss": "1.2.2",
|
"rss": "1.2.2",
|
||||||
"rtlcss": "4.3.0",
|
"rtlcss": "4.3.0",
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ ActivityPub.resolveInboxes = async (ids) => {
|
|||||||
}, [[], []]);
|
}, [[], []]);
|
||||||
const categoryData = await categories.getCategoriesFields(cids, ['inbox', 'sharedInbox']);
|
const categoryData = await categories.getCategoriesFields(cids, ['inbox', 'sharedInbox']);
|
||||||
const userData = await user.getUsersFields(uids, ['inbox', 'sharedInbox']);
|
const userData = await user.getUsersFields(uids, ['inbox', 'sharedInbox']);
|
||||||
|
|
||||||
currentIds.forEach((id) => {
|
currentIds.forEach((id) => {
|
||||||
if (cids.includes(id)) {
|
if (cids.includes(id)) {
|
||||||
const data = categoryData[cids.indexOf(id)];
|
const data = categoryData[cids.indexOf(id)];
|
||||||
|
|||||||
@@ -145,14 +145,15 @@ Controller.postInbox = async (req, res) => {
|
|||||||
const method = String(req.body.type).toLowerCase();
|
const method = String(req.body.type).toLowerCase();
|
||||||
if (!activitypub.inbox.hasOwnProperty(method)) {
|
if (!activitypub.inbox.hasOwnProperty(method)) {
|
||||||
winston.warn(`[activitypub/inbox] Received Activity of type ${method} but unable to handle. Ignoring.`);
|
winston.warn(`[activitypub/inbox] Received Activity of type ${method} but unable to handle. Ignoring.`);
|
||||||
|
console.log('[activitypub/inbox] method not found', method, req.body);
|
||||||
return res.sendStatus(200);
|
return res.sendStatus(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await activitypub.inbox[method](req);
|
await activitypub.inbox[method](req);
|
||||||
await activitypub.record(req.body);
|
await activitypub.record(req.body);
|
||||||
helpers.formatApiResponse(202, res);
|
await helpers.formatApiResponse(202, res);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
helpers.formatApiResponse(500, res, e);
|
helpers.formatApiResponse(500, res, e).catch(err => winston.error(err.stack));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -448,6 +448,10 @@ helpers.getHomePageRoutes = async function (uid) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
helpers.formatApiResponse = async (statusCode, res, payload) => {
|
helpers.formatApiResponse = async (statusCode, res, payload) => {
|
||||||
|
if (!res.hasOwnProperty('req')) {
|
||||||
|
console.log('formatApiResponse', statusCode, payload);
|
||||||
|
}
|
||||||
|
|
||||||
if (res.req.method === 'HEAD') {
|
if (res.req.method === 'HEAD') {
|
||||||
return res.sendStatus(statusCode);
|
return res.sendStatus(statusCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ redisModule.checkCompatibilityVersion = function (version, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
redisModule.close = async function () {
|
redisModule.close = async function () {
|
||||||
await redisModule.client.quit();
|
await redisModule.client.close();
|
||||||
if (redisModule.objectCache) {
|
if (redisModule.objectCache) {
|
||||||
redisModule.objectCache.reset();
|
redisModule.objectCache.reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const nconf = require('nconf');
|
const nconf = require('nconf');
|
||||||
const Redis = require('ioredis');
|
const { createClient, createCluster, createSentinel } = require('redis');
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
|
|
||||||
const connection = module.exports;
|
const connection = module.exports;
|
||||||
@@ -13,28 +13,40 @@ connection.connect = async function (options) {
|
|||||||
|
|
||||||
let cxn;
|
let cxn;
|
||||||
if (options.cluster) {
|
if (options.cluster) {
|
||||||
cxn = new Redis.Cluster(options.cluster, options.options);
|
const rootNodes = options.cluster.map(node => ({ url : `redis://${node.host}:${node.port}` }));
|
||||||
} else if (options.sentinels) {
|
cxn = createCluster({
|
||||||
cxn = new Redis({
|
|
||||||
sentinels: options.sentinels,
|
|
||||||
...options.options,
|
...options.options,
|
||||||
|
rootNodes: rootNodes,
|
||||||
|
});
|
||||||
|
} else if (options.sentinels) {
|
||||||
|
const sentinelRootNodes = options.sentinels.map(sentinel => ({ host: sentinel.host, port: sentinel.port }));
|
||||||
|
cxn = createSentinel({
|
||||||
|
...options.options,
|
||||||
|
name: 'sentinel-db',
|
||||||
|
sentinelRootNodes,
|
||||||
});
|
});
|
||||||
} else if (redis_socket_or_host && String(redis_socket_or_host).indexOf('/') >= 0) {
|
} else 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
|
// If redis.host contains a path name character, use the unix dom sock connection. ie, /tmp/redis.sock
|
||||||
cxn = new Redis({
|
cxn = createClient({
|
||||||
...options.options,
|
...options.options,
|
||||||
path: redis_socket_or_host,
|
|
||||||
password: options.password,
|
password: options.password,
|
||||||
db: options.database,
|
database: options.database,
|
||||||
|
socket: {
|
||||||
|
path: redis_socket_or_host,
|
||||||
|
reconnectStrategy: 3000,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Else, connect over tcp/ip
|
// Else, connect over tcp/ip
|
||||||
cxn = new Redis({
|
cxn = createClient({
|
||||||
...options.options,
|
...options.options,
|
||||||
host: redis_socket_or_host,
|
host: redis_socket_or_host,
|
||||||
port: options.port,
|
port: options.port,
|
||||||
password: options.password,
|
password: options.password,
|
||||||
db: options.database,
|
database: options.database,
|
||||||
|
socket: {
|
||||||
|
reconnectStrategy: 3000,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,9 +61,14 @@ connection.connect = async function (options) {
|
|||||||
});
|
});
|
||||||
cxn.on('ready', () => {
|
cxn.on('ready', () => {
|
||||||
// back-compat with node_redis
|
// back-compat with node_redis
|
||||||
cxn.batch = cxn.pipeline;
|
cxn.batch = cxn.multi;
|
||||||
resolve(cxn);
|
resolve(cxn);
|
||||||
});
|
});
|
||||||
|
cxn.connect().then(() => {
|
||||||
|
winston.info('Connected to Redis successfully');
|
||||||
|
}).catch((err) => {
|
||||||
|
winston.error('Error connecting to Redis:', err);
|
||||||
|
});
|
||||||
|
|
||||||
if (options.password) {
|
if (options.password) {
|
||||||
cxn.auth(options.password);
|
cxn.auth(options.password);
|
||||||
|
|||||||
@@ -25,12 +25,13 @@ module.exports = function (module) {
|
|||||||
if (!Object.keys(data).length) {
|
if (!Object.keys(data).length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const strObj = helpers.objectFieldsToString(data);
|
||||||
if (Array.isArray(key)) {
|
if (Array.isArray(key)) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
key.forEach(k => batch.hmset(k, data));
|
key.forEach(k => batch.hSet(k, strObj));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
} else {
|
} else {
|
||||||
await module.client.hmset(key, data);
|
await module.client.hSet(key, strObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
@@ -49,10 +50,16 @@ module.exports = function (module) {
|
|||||||
|
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
if (Object.keys(item[1]).length) {
|
Object.keys(item[1]).forEach((key) => {
|
||||||
batch.hmset(item[0], item[1]);
|
if (item[1][key] === undefined || item[1][key] === null) {
|
||||||
|
delete item[1][key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (Object.keys(item[1]).length) {
|
||||||
|
batch.hSet(item[0], helpers.objectFieldsToString(item[1]));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
cache.del(data.map(item => item[0]));
|
cache.del(data.map(item => item[0]));
|
||||||
};
|
};
|
||||||
@@ -61,12 +68,15 @@ module.exports = function (module) {
|
|||||||
if (!field) {
|
if (!field) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Array.isArray(key)) {
|
if (Array.isArray(key)) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
key.forEach(k => batch.hset(k, field, value));
|
key.forEach(k => batch.hSet(k, field, String(value)));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
} else {
|
} else {
|
||||||
await module.client.hset(key, field, value);
|
await module.client.hSet(key, field, String(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
@@ -92,9 +102,9 @@ module.exports = function (module) {
|
|||||||
const cachedData = {};
|
const cachedData = {};
|
||||||
cache.getUnCachedKeys([key], cachedData);
|
cache.getUnCachedKeys([key], cachedData);
|
||||||
if (cachedData[key]) {
|
if (cachedData[key]) {
|
||||||
return cachedData[key].hasOwnProperty(field) ? cachedData[key][field] : null;
|
return Object.hasOwn(cachedData[key], field) ? cachedData[key][field] : null;
|
||||||
}
|
}
|
||||||
return await module.client.hget(key, String(field));
|
return await module.client.hGet(key, String(field));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getObjectFields = async function (key, fields) {
|
module.getObjectFields = async function (key, fields) {
|
||||||
@@ -116,10 +126,10 @@ module.exports = function (module) {
|
|||||||
let data = [];
|
let data = [];
|
||||||
if (unCachedKeys.length > 1) {
|
if (unCachedKeys.length > 1) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
unCachedKeys.forEach(k => batch.hgetall(k));
|
unCachedKeys.forEach(k => batch.hGetAll(k));
|
||||||
data = await helpers.execBatch(batch);
|
data = await helpers.execBatch(batch);
|
||||||
} else if (unCachedKeys.length === 1) {
|
} else if (unCachedKeys.length === 1) {
|
||||||
data = [await module.client.hgetall(unCachedKeys[0])];
|
data = [await module.client.hGetAll(unCachedKeys[0])];
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert empty objects into null for back-compat with node_redis
|
// convert empty objects into null for back-compat with node_redis
|
||||||
@@ -149,21 +159,21 @@ module.exports = function (module) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.getObjectKeys = async function (key) {
|
module.getObjectKeys = async function (key) {
|
||||||
return await module.client.hkeys(key);
|
return await module.client.hKeys(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getObjectValues = async function (key) {
|
module.getObjectValues = async function (key) {
|
||||||
return await module.client.hvals(key);
|
return await module.client.hVals(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.isObjectField = async function (key, field) {
|
module.isObjectField = async function (key, field) {
|
||||||
const exists = await module.client.hexists(key, field);
|
const exists = await module.client.hExists(key, String(field));
|
||||||
return exists === 1;
|
return exists === 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.isObjectFields = async function (key, fields) {
|
module.isObjectFields = async function (key, fields) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
fields.forEach(f => batch.hexists(String(key), String(f)));
|
fields.forEach(f => batch.hExists(String(key), String(f)));
|
||||||
const results = await helpers.execBatch(batch);
|
const results = await helpers.execBatch(batch);
|
||||||
return Array.isArray(results) ? helpers.resultsToBool(results) : null;
|
return Array.isArray(results) ? helpers.resultsToBool(results) : null;
|
||||||
};
|
};
|
||||||
@@ -174,7 +184,7 @@ module.exports = function (module) {
|
|||||||
}
|
}
|
||||||
field = field.toString();
|
field = field.toString();
|
||||||
if (field) {
|
if (field) {
|
||||||
await module.client.hdel(key, field);
|
await module.client.hDel(key, field);
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -189,10 +199,10 @@ module.exports = function (module) {
|
|||||||
}
|
}
|
||||||
if (Array.isArray(key)) {
|
if (Array.isArray(key)) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
key.forEach(k => batch.hdel(k, fields));
|
key.forEach(k => batch.hDel(k, fields));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
} else {
|
} else {
|
||||||
await module.client.hdel(key, fields);
|
await module.client.hDel(key, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
@@ -214,10 +224,10 @@ module.exports = function (module) {
|
|||||||
let result;
|
let result;
|
||||||
if (Array.isArray(key)) {
|
if (Array.isArray(key)) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
key.forEach(k => batch.hincrby(k, field, value));
|
key.forEach(k => batch.hIncrBy(k, field, value));
|
||||||
result = await helpers.execBatch(batch);
|
result = await helpers.execBatch(batch);
|
||||||
} else {
|
} else {
|
||||||
result = await module.client.hincrby(key, field, value);
|
result = await module.client.hIncrBy(key, field, value);
|
||||||
}
|
}
|
||||||
cache.del(key);
|
cache.del(key);
|
||||||
return Array.isArray(result) ? result.map(value => parseInt(value, 10)) : parseInt(result, 10);
|
return Array.isArray(result) ? result.map(value => parseInt(value, 10)) : parseInt(result, 10);
|
||||||
@@ -231,7 +241,7 @@ module.exports = function (module) {
|
|||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
for (const [field, value] of Object.entries(item[1])) {
|
for (const [field, value] of Object.entries(item[1])) {
|
||||||
batch.hincrby(item[0], field, value);
|
batch.hIncrBy(item[0], field, value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
|
|||||||
@@ -5,13 +5,8 @@ const helpers = module.exports;
|
|||||||
helpers.noop = function () {};
|
helpers.noop = function () {};
|
||||||
|
|
||||||
helpers.execBatch = async function (batch) {
|
helpers.execBatch = async function (batch) {
|
||||||
const results = await batch.exec();
|
const results = await batch.execAsPipeline();
|
||||||
return results.map(([err, res]) => {
|
return results;
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
helpers.resultsToBool = function (results) {
|
helpers.resultsToBool = function (results) {
|
||||||
@@ -21,10 +16,29 @@ helpers.resultsToBool = function (results) {
|
|||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
helpers.zsetToObjectArray = function (data) {
|
helpers.objectFieldsToString = function (obj) {
|
||||||
const objects = new Array(data.length / 2);
|
const stringified = Object.fromEntries(
|
||||||
for (let i = 0, k = 0; i < objects.length; i += 1, k += 2) {
|
Object.entries(obj).map(([key, value]) => [key, String(value)])
|
||||||
objects[i] = { value: data[k], score: parseFloat(data[k + 1]) };
|
);
|
||||||
}
|
return stringified;
|
||||||
return objects;
|
};
|
||||||
|
|
||||||
|
helpers.normalizeLexRange = function (min, max, reverse) {
|
||||||
|
let minmin;
|
||||||
|
let maxmax;
|
||||||
|
if (reverse) {
|
||||||
|
minmin = '+';
|
||||||
|
maxmax = '-';
|
||||||
|
} else {
|
||||||
|
minmin = '-';
|
||||||
|
maxmax = '+';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min !== minmin && !min.match(/^[[(]/)) {
|
||||||
|
min = `[${min}`;
|
||||||
|
}
|
||||||
|
if (max !== maxmax && !max.match(/^[[(]/)) {
|
||||||
|
max = `[${max}`;
|
||||||
|
}
|
||||||
|
return { lmin: min, lmax: max };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = function (module) {
|
module.exports = function (module) {
|
||||||
const helpers = require('./helpers');
|
|
||||||
|
|
||||||
module.listPrepend = async function (key, value) {
|
module.listPrepend = async function (key, value) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await module.client.lpush(key, value);
|
await module.client.lPush(key, Array.isArray(value) ? value.map(String) : String(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.listAppend = async function (key, value) {
|
module.listAppend = async function (key, value) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await module.client.rpush(key, value);
|
await module.client.rPush(key, Array.isArray(value) ? value.map(String) : String(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.listRemoveLast = async function (key) {
|
module.listRemoveLast = async function (key) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return await module.client.rpop(key);
|
return await module.client.rPop(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.listRemoveAll = async function (key, value) {
|
module.listRemoveAll = async function (key, value) {
|
||||||
@@ -29,11 +27,11 @@ module.exports = function (module) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.multi();
|
||||||
value.forEach(value => batch.lrem(key, 0, value));
|
value.forEach(value => batch.lRem(key, 0, value));
|
||||||
await helpers.execBatch(batch);
|
await batch.execAsPipeline();
|
||||||
} else {
|
} else {
|
||||||
await module.client.lrem(key, 0, value);
|
await module.client.lRem(key, 0, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,17 +39,17 @@ module.exports = function (module) {
|
|||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await module.client.ltrim(key, start, stop);
|
await module.client.lTrim(key, start, stop);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getListRange = async function (key, start, stop) {
|
module.getListRange = async function (key, start, stop) {
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return await module.client.lrange(key, start, stop);
|
return await module.client.lRange(key, start, stop);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.listLength = async function (key) {
|
module.listLength = async function (key) {
|
||||||
return await module.client.llen(key);
|
return await module.client.lLen(key);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module.exports = function (module) {
|
|||||||
const helpers = require('./helpers');
|
const helpers = require('./helpers');
|
||||||
|
|
||||||
module.flushdb = async function () {
|
module.flushdb = async function () {
|
||||||
await module.client.send_command('flushdb', []);
|
await module.client.sendCommand(['FLUSHDB']);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.emptydb = async function () {
|
module.emptydb = async function () {
|
||||||
@@ -32,9 +32,9 @@ module.exports = function (module) {
|
|||||||
const seen = Object.create(null);
|
const seen = Object.create(null);
|
||||||
do {
|
do {
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
const res = await module.client.scan(cursor, 'MATCH', params.match, 'COUNT', 10000);
|
const res = await module.client.scan(cursor, { MATCH: params.match, COUNT: 10000 });
|
||||||
cursor = res[0];
|
cursor = res.cursor;
|
||||||
const values = res[1].filter((value) => {
|
const values = res.keys.filter((value) => {
|
||||||
const isSeen = !!seen[value];
|
const isSeen = !!seen[value];
|
||||||
if (!isSeen) {
|
if (!isSeen) {
|
||||||
seen[value] = 1;
|
seen[value] = 1;
|
||||||
@@ -67,7 +67,7 @@ module.exports = function (module) {
|
|||||||
if (!keys || !Array.isArray(keys) || !keys.length) {
|
if (!keys || !Array.isArray(keys) || !keys.length) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return await module.client.mget(keys);
|
return await module.client.mGet(keys);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.set = async function (key, value) {
|
module.set = async function (key, value) {
|
||||||
@@ -96,26 +96,26 @@ module.exports = function (module) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.expire = async function (key, seconds) {
|
module.expire = async function (key, seconds) {
|
||||||
await module.client.expire(key, seconds);
|
await module.client.EXPIRE(key, seconds);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.expireAt = async function (key, timestamp) {
|
module.expireAt = async function (key, timestamp) {
|
||||||
await module.client.expireat(key, timestamp);
|
await module.client.EXPIREAT(key, timestamp);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.pexpire = async function (key, ms) {
|
module.pexpire = async function (key, ms) {
|
||||||
await module.client.pexpire(key, ms);
|
await module.client.PEXPIRE(key, ms);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.pexpireAt = async function (key, timestamp) {
|
module.pexpireAt = async function (key, timestamp) {
|
||||||
await module.client.pexpireat(key, timestamp);
|
await module.client.PEXPIREAT(key, timestamp);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.ttl = async function (key) {
|
module.ttl = async function (key) {
|
||||||
return await module.client.ttl(key);
|
return await module.client.TTL(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.pttl = async function (key) {
|
module.pttl = async function (key) {
|
||||||
return await module.client.pttl(key);
|
return await module.client.PTTL(key);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module.exports = function (module) {
|
|||||||
if (!value.length) {
|
if (!value.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await module.client.sadd(key, value);
|
await module.client.sAdd(key, value.map(String));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.setsAdd = async function (keys, value) {
|
module.setsAdd = async function (keys, value) {
|
||||||
@@ -18,7 +18,7 @@ module.exports = function (module) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.sadd(String(k), String(value)));
|
keys.forEach(k => batch.sAdd(String(k), String(value)));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34,57 +34,57 @@ module.exports = function (module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
key.forEach(k => batch.srem(String(k), value));
|
key.forEach(k => batch.sRem(String(k), value.map(String)));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.setsRemove = async function (keys, value) {
|
module.setsRemove = async function (keys, value) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.srem(String(k), value));
|
keys.forEach(k => batch.sRem(String(k), String(value)));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.isSetMember = async function (key, value) {
|
module.isSetMember = async function (key, value) {
|
||||||
const result = await module.client.sismember(key, value);
|
const result = await module.client.sIsMember(key, String(value));
|
||||||
return result === 1;
|
return result === 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.isSetMembers = async function (key, values) {
|
module.isSetMembers = async function (key, values) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
values.forEach(v => batch.sismember(String(key), String(v)));
|
values.forEach(v => batch.sIsMember(String(key), String(v)));
|
||||||
const results = await helpers.execBatch(batch);
|
const results = await helpers.execBatch(batch);
|
||||||
return results ? helpers.resultsToBool(results) : null;
|
return results ? helpers.resultsToBool(results) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.isMemberOfSets = async function (sets, value) {
|
module.isMemberOfSets = async function (sets, value) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
sets.forEach(s => batch.sismember(String(s), String(value)));
|
sets.forEach(s => batch.sIsMember(String(s), String(value)));
|
||||||
const results = await helpers.execBatch(batch);
|
const results = await helpers.execBatch(batch);
|
||||||
return results ? helpers.resultsToBool(results) : null;
|
return results ? helpers.resultsToBool(results) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSetMembers = async function (key) {
|
module.getSetMembers = async function (key) {
|
||||||
return await module.client.smembers(key);
|
return await module.client.sMembers(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSetsMembers = async function (keys) {
|
module.getSetsMembers = async function (keys) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.smembers(String(k)));
|
keys.forEach(k => batch.sMembers(String(k)));
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.setCount = async function (key) {
|
module.setCount = async function (key) {
|
||||||
return await module.client.scard(key);
|
return await module.client.sCard(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.setsCount = async function (keys) {
|
module.setsCount = async function (keys) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.scard(String(k)));
|
keys.forEach(k => batch.sCard(String(k)));
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.setRemoveRandom = async function (key) {
|
module.setRemoveRandom = async function (key) {
|
||||||
return await module.client.spop(key);
|
return await module.client.sPop(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
|
|||||||
@@ -11,34 +11,74 @@ module.exports = function (module) {
|
|||||||
require('./sorted/intersect')(module);
|
require('./sorted/intersect')(module);
|
||||||
|
|
||||||
module.getSortedSetRange = async function (key, start, stop) {
|
module.getSortedSetRange = async function (key, start, stop) {
|
||||||
return await sortedSetRange('zrange', key, start, stop, '-inf', '+inf', false);
|
return await sortedSetRange(key, start, stop, '-inf', '+inf', false, false, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetRevRange = async function (key, start, stop) {
|
module.getSortedSetRevRange = async function (key, start, stop) {
|
||||||
return await sortedSetRange('zrevrange', key, start, stop, '-inf', '+inf', false);
|
return await sortedSetRange(key, start, stop, '-inf', '+inf', false, true, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetRangeWithScores = async function (key, start, stop) {
|
module.getSortedSetRangeWithScores = async function (key, start, stop) {
|
||||||
return await sortedSetRange('zrange', key, start, stop, '-inf', '+inf', true);
|
return await sortedSetRange(key, start, stop, '-inf', '+inf', true, false, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetRevRangeWithScores = async function (key, start, stop) {
|
module.getSortedSetRevRangeWithScores = async function (key, start, stop) {
|
||||||
return await sortedSetRange('zrevrange', key, start, stop, '-inf', '+inf', true);
|
return await sortedSetRange(key, start, stop, '-inf', '+inf', true, true, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function sortedSetRange(method, key, start, stop, min, max, withScores) {
|
module.getSortedSetRangeByScore = async function (key, start, count, min, max) {
|
||||||
|
return await sortedSetRangeByScore(key, start, count, min, max, false, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.getSortedSetRevRangeByScore = async function (key, start, count, max, min) {
|
||||||
|
return await sortedSetRangeByScore(key, start, count, max, min, false, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.getSortedSetRangeByScoreWithScores = async function (key, start, count, min, max) {
|
||||||
|
return await sortedSetRangeByScore(key, start, count, min, max, true, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.getSortedSetRevRangeByScoreWithScores = async function (key, start, count, max, min) {
|
||||||
|
return await sortedSetRangeByScore(key, start, count, max, min, true, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function sortedSetRangeByScore(key, start, count, min, max, withScores, rev) {
|
||||||
|
if (parseInt(count, 10) === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const stop = (parseInt(count, 10) === -1) ? -1 : (start + count - 1);
|
||||||
|
return await sortedSetRange(key, start, stop, min, max, withScores, rev, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sortedSetRange(key, start, stop, min, max, withScores, rev, byScore) {
|
||||||
|
const opts = {};
|
||||||
|
const cmd = withScores ? 'zRangeWithScores' : 'zRange';
|
||||||
|
if (byScore) {
|
||||||
|
opts.BY = 'SCORE';
|
||||||
|
opts.LIMIT = { offset: start, count: stop !== -1 ? stop + 1 : stop };
|
||||||
|
}
|
||||||
|
if (rev) {
|
||||||
|
opts.REV = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(key)) {
|
if (Array.isArray(key)) {
|
||||||
if (!key.length) {
|
if (!key.length) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
key.forEach(key => batch[method](genParams(method, key, 0, stop, min, max, true)));
|
|
||||||
|
if (byScore) {
|
||||||
|
key.forEach(key => batch.zRangeWithScores(key, min, max, {
|
||||||
|
...opts,
|
||||||
|
LIMIT: { offset: 0, count: stop !== -1 ? stop + 1 : stop },
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
key.forEach(key => batch.zRangeWithScores(key, 0, stop, { ...opts }));
|
||||||
|
}
|
||||||
|
|
||||||
const data = await helpers.execBatch(batch);
|
const data = await helpers.execBatch(batch);
|
||||||
|
const batchData = data;
|
||||||
const batchData = data.map(setData => helpers.zsetToObjectArray(setData));
|
let objects = dbHelpers.mergeBatch(batchData, 0, stop, rev ? -1 : 1);
|
||||||
|
|
||||||
let objects = dbHelpers.mergeBatch(batchData, 0, stop, method === 'zrange' ? 1 : -1);
|
|
||||||
|
|
||||||
if (start > 0) {
|
if (start > 0) {
|
||||||
objects = objects.slice(start, stop !== -1 ? stop + 1 : undefined);
|
objects = objects.slice(start, stop !== -1 ? stop + 1 : undefined);
|
||||||
}
|
}
|
||||||
@@ -48,63 +88,25 @@ module.exports = function (module) {
|
|||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = genParams(method, key, start, stop, min, max, withScores);
|
let data;
|
||||||
const data = await module.client[method](params);
|
if (byScore) {
|
||||||
|
data = await module.client[cmd](key, min, max, opts);
|
||||||
|
} else {
|
||||||
|
data = await module.client[cmd](key, start, stop, opts);
|
||||||
|
}
|
||||||
|
|
||||||
if (!withScores) {
|
if (!withScores) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
const objects = helpers.zsetToObjectArray(data);
|
return data;
|
||||||
return objects;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genParams(method, key, start, stop, min, max, withScores) {
|
|
||||||
const params = {
|
|
||||||
zrevrange: [key, start, stop],
|
|
||||||
zrange: [key, start, stop],
|
|
||||||
zrangebyscore: [key, min, max],
|
|
||||||
zrevrangebyscore: [key, max, min],
|
|
||||||
};
|
|
||||||
if (withScores) {
|
|
||||||
params[method].push('WITHSCORES');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method === 'zrangebyscore' || method === 'zrevrangebyscore') {
|
|
||||||
const count = stop !== -1 ? stop - start + 1 : stop;
|
|
||||||
params[method].push('LIMIT', start, count);
|
|
||||||
}
|
|
||||||
return params[method];
|
|
||||||
}
|
|
||||||
|
|
||||||
module.getSortedSetRangeByScore = async function (key, start, count, min, max) {
|
|
||||||
return await sortedSetRangeByScore('zrangebyscore', key, start, count, min, max, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.getSortedSetRevRangeByScore = async function (key, start, count, max, min) {
|
|
||||||
return await sortedSetRangeByScore('zrevrangebyscore', key, start, count, min, max, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.getSortedSetRangeByScoreWithScores = async function (key, start, count, min, max) {
|
|
||||||
return await sortedSetRangeByScore('zrangebyscore', key, start, count, min, max, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.getSortedSetRevRangeByScoreWithScores = async function (key, start, count, max, min) {
|
|
||||||
return await sortedSetRangeByScore('zrevrangebyscore', key, start, count, min, max, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
async function sortedSetRangeByScore(method, key, start, count, min, max, withScores) {
|
|
||||||
if (parseInt(count, 10) === 0) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const stop = (parseInt(count, 10) === -1) ? -1 : (start + count - 1);
|
|
||||||
return await sortedSetRange(method, key, start, stop, min, max, withScores);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.sortedSetCount = async function (key, min, max) {
|
module.sortedSetCount = async function (key, min, max) {
|
||||||
return await module.client.zcount(key, min, max);
|
return await module.client.zCount(key, min, max);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetCard = async function (key) {
|
module.sortedSetCard = async function (key) {
|
||||||
return await module.client.zcard(key);
|
return await module.client.zCard(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetsCard = async function (keys) {
|
module.sortedSetsCard = async function (keys) {
|
||||||
@@ -112,7 +114,7 @@ module.exports = function (module) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.zcard(String(k)));
|
keys.forEach(k => batch.zCard(String(k)));
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,26 +127,26 @@ module.exports = function (module) {
|
|||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
if (min !== '-inf' || max !== '+inf') {
|
if (min !== '-inf' || max !== '+inf') {
|
||||||
keys.forEach(k => batch.zcount(String(k), min, max));
|
keys.forEach(k => batch.zCount(String(k), min, max));
|
||||||
} else {
|
} else {
|
||||||
keys.forEach(k => batch.zcard(String(k)));
|
keys.forEach(k => batch.zCard(String(k)));
|
||||||
}
|
}
|
||||||
const counts = await helpers.execBatch(batch);
|
const counts = await helpers.execBatch(batch);
|
||||||
return counts.reduce((acc, val) => acc + val, 0);
|
return counts.reduce((acc, val) => acc + val, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetRank = async function (key, value) {
|
module.sortedSetRank = async function (key, value) {
|
||||||
return await module.client.zrank(key, value);
|
return await module.client.zRank(key, String(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetRevRank = async function (key, value) {
|
module.sortedSetRevRank = async function (key, value) {
|
||||||
return await module.client.zrevrank(key, value);
|
return await module.client.zRevRank(key, String(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetsRanks = async function (keys, values) {
|
module.sortedSetsRanks = async function (keys, values) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
for (let i = 0; i < values.length; i += 1) {
|
for (let i = 0; i < values.length; i += 1) {
|
||||||
batch.zrank(keys[i], String(values[i]));
|
batch.zRank(keys[i], String(values[i]));
|
||||||
}
|
}
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
@@ -152,7 +154,7 @@ module.exports = function (module) {
|
|||||||
module.sortedSetsRevRanks = async function (keys, values) {
|
module.sortedSetsRevRanks = async function (keys, values) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
for (let i = 0; i < values.length; i += 1) {
|
for (let i = 0; i < values.length; i += 1) {
|
||||||
batch.zrevrank(keys[i], String(values[i]));
|
batch.zRevRank(keys[i], String(values[i]));
|
||||||
}
|
}
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
@@ -160,7 +162,7 @@ module.exports = function (module) {
|
|||||||
module.sortedSetRanks = async function (key, values) {
|
module.sortedSetRanks = async function (key, values) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
for (let i = 0; i < values.length; i += 1) {
|
for (let i = 0; i < values.length; i += 1) {
|
||||||
batch.zrank(key, String(values[i]));
|
batch.zRank(key, String(values[i]));
|
||||||
}
|
}
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
@@ -168,7 +170,7 @@ module.exports = function (module) {
|
|||||||
module.sortedSetRevRanks = async function (key, values) {
|
module.sortedSetRevRanks = async function (key, values) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
for (let i = 0; i < values.length; i += 1) {
|
for (let i = 0; i < values.length; i += 1) {
|
||||||
batch.zrevrank(key, String(values[i]));
|
batch.zRevRank(key, String(values[i]));
|
||||||
}
|
}
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
@@ -177,8 +179,7 @@ module.exports = function (module) {
|
|||||||
if (!key || value === undefined) {
|
if (!key || value === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const score = await module.client.zScore(key, String(value));
|
||||||
const score = await module.client.zscore(key, value);
|
|
||||||
return score === null ? score : parseFloat(score);
|
return score === null ? score : parseFloat(score);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,7 +188,7 @@ module.exports = function (module) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(key => batch.zscore(String(key), String(value)));
|
keys.forEach(key => batch.zScore(String(key), String(value)));
|
||||||
const scores = await helpers.execBatch(batch);
|
const scores = await helpers.execBatch(batch);
|
||||||
return scores.map(d => (d === null ? d : parseFloat(d)));
|
return scores.map(d => (d === null ? d : parseFloat(d)));
|
||||||
};
|
};
|
||||||
@@ -197,7 +198,7 @@ module.exports = function (module) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
values.forEach(value => batch.zscore(String(key), String(value)));
|
values.forEach(value => batch.zScore(String(key), String(value)));
|
||||||
const scores = await helpers.execBatch(batch);
|
const scores = await helpers.execBatch(batch);
|
||||||
return scores.map(d => (d === null ? d : parseFloat(d)));
|
return scores.map(d => (d === null ? d : parseFloat(d)));
|
||||||
};
|
};
|
||||||
@@ -211,9 +212,9 @@ module.exports = function (module) {
|
|||||||
if (!values.length) {
|
if (!values.length) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.multi();
|
||||||
values.forEach(v => batch.zscore(key, String(v)));
|
values.forEach(v => batch.zScore(key, String(v)));
|
||||||
const results = await helpers.execBatch(batch);
|
const results = await batch.execAsPipeline();
|
||||||
return results.map(utils.isNumber);
|
return results.map(utils.isNumber);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -221,20 +222,18 @@ module.exports = function (module) {
|
|||||||
if (!Array.isArray(keys) || !keys.length) {
|
if (!Array.isArray(keys) || !keys.length) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.multi();
|
||||||
keys.forEach(k => batch.zscore(k, String(value)));
|
keys.forEach(k => batch.zScore(k, String(value)));
|
||||||
const results = await helpers.execBatch(batch);
|
const results = await batch.execAsPipeline();
|
||||||
return results.map(utils.isNumber);
|
return results.map(utils.isNumber);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetMembers = async function (key) {
|
module.getSortedSetMembers = async function (key) {
|
||||||
return await module.client.zrange(key, 0, -1);
|
return await module.client.zRange(key, 0, -1);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetMembersWithScores = async function (key) {
|
module.getSortedSetMembersWithScores = async function (key) {
|
||||||
return helpers.zsetToObjectArray(
|
return await module.client.zRangeWithScores(key, 0, -1);
|
||||||
await module.client.zrange(key, 0, -1, 'WITHSCORES')
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetsMembers = async function (keys) {
|
module.getSortedSetsMembers = async function (keys) {
|
||||||
@@ -242,7 +241,7 @@ module.exports = function (module) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.zrange(k, 0, -1));
|
keys.forEach(k => batch.zRange(k, 0, -1));
|
||||||
return await helpers.execBatch(batch);
|
return await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -251,65 +250,52 @@ module.exports = function (module) {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.zrange(k, 0, -1, 'WITHSCORES'));
|
keys.forEach(k => batch.zRangeWithScores(k, 0, -1));
|
||||||
const res = await helpers.execBatch(batch);
|
const res = await helpers.execBatch(batch);
|
||||||
return res.map(helpers.zsetToObjectArray);
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetIncrBy = async function (key, increment, value) {
|
module.sortedSetIncrBy = async function (key, increment, value) {
|
||||||
const newValue = await module.client.zincrby(key, increment, value);
|
const newValue = await module.client.zIncrBy(key, increment, String(value));
|
||||||
return parseFloat(newValue);
|
return parseFloat(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetIncrByBulk = async function (data) {
|
module.sortedSetIncrByBulk = async function (data) {
|
||||||
const multi = module.client.multi();
|
const multi = module.client.multi();
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
multi.zincrby(item[0], item[1], item[2]);
|
multi.zIncrBy(item[0], item[1], String(item[2]));
|
||||||
});
|
});
|
||||||
const result = await multi.exec();
|
const result = await multi.exec();
|
||||||
return result.map(item => item && parseFloat(item[1]));
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetRangeByLex = async function (key, min, max, start, count) {
|
module.getSortedSetRangeByLex = async function (key, min, max, start = 0, count = -1) {
|
||||||
return await sortedSetLex('zrangebylex', false, key, min, max, start, count);
|
const { lmin, lmax } = helpers.normalizeLexRange(min, max, false);
|
||||||
|
return await module.client.zRange(key, lmin, lmax, {
|
||||||
|
BY: 'LEX',
|
||||||
|
LIMIT: { offset: start, count: count },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetRevRangeByLex = async function (key, max, min, start, count) {
|
module.getSortedSetRevRangeByLex = async function (key, max, min, start = 0, count = -1) {
|
||||||
return await sortedSetLex('zrevrangebylex', true, key, max, min, start, count);
|
const { lmin, lmax } = helpers.normalizeLexRange(max, min, true);
|
||||||
|
return await module.client.zRange(key, lmin, lmax, {
|
||||||
|
REV: true,
|
||||||
|
BY: 'LEX',
|
||||||
|
LIMIT: { offset: start, count: count },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetRemoveRangeByLex = async function (key, min, max) {
|
module.sortedSetRemoveRangeByLex = async function (key, min, max) {
|
||||||
await sortedSetLex('zremrangebylex', false, key, min, max);
|
const { lmin, lmax } = helpers.normalizeLexRange(min, max, false);
|
||||||
|
await module.client.zRemRangeByLex(key, lmin, lmax);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetLexCount = async function (key, min, max) {
|
module.sortedSetLexCount = async function (key, min, max) {
|
||||||
return await sortedSetLex('zlexcount', false, key, min, max);
|
const { lmin, lmax } = helpers.normalizeLexRange(min, max, false);
|
||||||
|
return await module.client.zLexCount(key, lmin, lmax);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function sortedSetLex(method, reverse, key, min, max, start, count) {
|
|
||||||
let minmin;
|
|
||||||
let maxmax;
|
|
||||||
if (reverse) {
|
|
||||||
minmin = '+';
|
|
||||||
maxmax = '-';
|
|
||||||
} else {
|
|
||||||
minmin = '-';
|
|
||||||
maxmax = '+';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min !== minmin && !min.match(/^[[(]/)) {
|
|
||||||
min = `[${min}`;
|
|
||||||
}
|
|
||||||
if (max !== maxmax && !max.match(/^[[(]/)) {
|
|
||||||
max = `[${max}`;
|
|
||||||
}
|
|
||||||
const args = [key, min, max];
|
|
||||||
if (count) {
|
|
||||||
args.push('LIMIT', start, count);
|
|
||||||
}
|
|
||||||
return await module.client[method](args);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.getSortedSetScan = async function (params) {
|
module.getSortedSetScan = async function (params) {
|
||||||
let cursor = '0';
|
let cursor = '0';
|
||||||
|
|
||||||
@@ -318,20 +304,19 @@ module.exports = function (module) {
|
|||||||
const seen = Object.create(null);
|
const seen = Object.create(null);
|
||||||
do {
|
do {
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
const res = await module.client.zscan(params.key, cursor, 'MATCH', params.match, 'COUNT', 5000);
|
const res = await module.client.zScan(params.key, cursor, { MATCH: params.match, COUNT: 5000 });
|
||||||
cursor = res[0];
|
cursor = res.cursor;
|
||||||
done = cursor === '0';
|
done = cursor === '0';
|
||||||
const data = res[1];
|
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i += 2) {
|
for (let i = 0; i < res.members.length; i ++) {
|
||||||
const value = data[i];
|
const item = res.members[i];
|
||||||
if (!seen[value]) {
|
if (!seen[item.value]) {
|
||||||
seen[value] = 1;
|
seen[item.value] = 1;
|
||||||
|
|
||||||
if (params.withScores) {
|
if (params.withScores) {
|
||||||
returnData.push({ value: value, score: parseFloat(data[i + 1]) });
|
returnData.push({ value: item.value, score: parseFloat(item.score) });
|
||||||
} else {
|
} else {
|
||||||
returnData.push(value);
|
returnData.push(item.value);
|
||||||
}
|
}
|
||||||
if (params.limit && returnData.length >= params.limit) {
|
if (params.limit && returnData.length >= params.limit) {
|
||||||
done = true;
|
done = true;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = function (module) {
|
module.exports = function (module) {
|
||||||
const helpers = require('../helpers');
|
|
||||||
const utils = require('../../../utils');
|
const utils = require('../../../utils');
|
||||||
|
|
||||||
module.sortedSetAdd = async function (key, score, value) {
|
module.sortedSetAdd = async function (key, score, value) {
|
||||||
@@ -14,7 +13,8 @@ module.exports = function (module) {
|
|||||||
if (!utils.isNumber(score)) {
|
if (!utils.isNumber(score)) {
|
||||||
throw new Error(`[[error:invalid-score, ${score}]]`);
|
throw new Error(`[[error:invalid-score, ${score}]]`);
|
||||||
}
|
}
|
||||||
await module.client.zadd(key, score, String(value));
|
|
||||||
|
await module.client.zAdd(key, { score, value: String(value) });
|
||||||
};
|
};
|
||||||
|
|
||||||
async function sortedSetAddMulti(key, scores, values) {
|
async function sortedSetAddMulti(key, scores, values) {
|
||||||
@@ -30,11 +30,8 @@ module.exports = function (module) {
|
|||||||
throw new Error(`[[error:invalid-score, ${scores[i]}]]`);
|
throw new Error(`[[error:invalid-score, ${scores[i]}]]`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const args = [key];
|
const members = scores.map((score, i) => ({ score, value: String(values[i])}));
|
||||||
for (let i = 0; i < scores.length; i += 1) {
|
await module.client.zAdd(key, members);
|
||||||
args.push(scores[i], String(values[i]));
|
|
||||||
}
|
|
||||||
await module.client.zadd(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.sortedSetsAdd = async function (keys, scores, value) {
|
module.sortedSetsAdd = async function (keys, scores, value) {
|
||||||
@@ -51,13 +48,16 @@ module.exports = function (module) {
|
|||||||
throw new Error('[[error:invalid-data]]');
|
throw new Error('[[error:invalid-data]]');
|
||||||
}
|
}
|
||||||
|
|
||||||
const batch = module.client.batch();
|
const batch = module.client.multi();
|
||||||
for (let i = 0; i < keys.length; i += 1) {
|
for (let i = 0; i < keys.length; i += 1) {
|
||||||
if (keys[i]) {
|
if (keys[i]) {
|
||||||
batch.zadd(keys[i], isArrayOfScores ? scores[i] : scores, String(value));
|
batch.zAdd(keys[i], {
|
||||||
|
score: isArrayOfScores ? scores[i] : scores,
|
||||||
|
value: String(value),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await helpers.execBatch(batch);
|
await batch.execAsPipeline();
|
||||||
};
|
};
|
||||||
|
|
||||||
module.sortedSetAddBulk = async function (data) {
|
module.sortedSetAddBulk = async function (data) {
|
||||||
@@ -69,8 +69,8 @@ module.exports = function (module) {
|
|||||||
if (!utils.isNumber(item[1])) {
|
if (!utils.isNumber(item[1])) {
|
||||||
throw new Error(`[[error:invalid-score, ${item[1]}]]`);
|
throw new Error(`[[error:invalid-score, ${item[1]}]]`);
|
||||||
}
|
}
|
||||||
batch.zadd(item[0], item[1], item[2]);
|
batch.zAdd(item[0], { score: item[1], value: String(item[2]) });
|
||||||
});
|
});
|
||||||
await helpers.execBatch(batch);
|
await batch.execAsPipeline();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,52 +8,46 @@ module.exports = function (module) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const tempSetName = `temp_${Date.now()}`;
|
const tempSetName = `temp_${Date.now()}`;
|
||||||
|
|
||||||
const interParams = [tempSetName, keys.length].concat(keys);
|
|
||||||
|
|
||||||
const multi = module.client.multi();
|
const multi = module.client.multi();
|
||||||
multi.zinterstore(interParams);
|
multi.zInterStore(tempSetName, keys);
|
||||||
multi.zcard(tempSetName);
|
multi.zCard(tempSetName);
|
||||||
multi.del(tempSetName);
|
multi.del(tempSetName);
|
||||||
const results = await helpers.execBatch(multi);
|
const results = await helpers.execBatch(multi);
|
||||||
return results[1] || 0;
|
return results[1] || 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetIntersect = async function (params) {
|
module.getSortedSetIntersect = async function (params) {
|
||||||
params.method = 'zrange';
|
params.reverse = false;
|
||||||
return await getSortedSetRevIntersect(params);
|
return await getSortedSetRevIntersect(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetRevIntersect = async function (params) {
|
module.getSortedSetRevIntersect = async function (params) {
|
||||||
params.method = 'zrevrange';
|
params.reverse = true;
|
||||||
return await getSortedSetRevIntersect(params);
|
return await getSortedSetRevIntersect(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getSortedSetRevIntersect(params) {
|
async function getSortedSetRevIntersect(params) {
|
||||||
const { sets } = params;
|
let { sets } = params;
|
||||||
const start = params.hasOwnProperty('start') ? params.start : 0;
|
const start = params.hasOwnProperty('start') ? params.start : 0;
|
||||||
const stop = params.hasOwnProperty('stop') ? params.stop : -1;
|
const stop = params.hasOwnProperty('stop') ? params.stop : -1;
|
||||||
const weights = params.weights || [];
|
const weights = params.weights || [];
|
||||||
|
|
||||||
const tempSetName = `temp_${Date.now()}`;
|
const tempSetName = `temp_${Date.now()}`;
|
||||||
|
|
||||||
let interParams = [tempSetName, sets.length].concat(sets);
|
const interParams = {};
|
||||||
if (weights.length) {
|
if (weights.length) {
|
||||||
interParams = interParams.concat(['WEIGHTS'].concat(weights));
|
sets = sets.map((set, index) => ({ key: set, weight: weights[index] }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.aggregate) {
|
if (params.aggregate) {
|
||||||
interParams = interParams.concat(['AGGREGATE', params.aggregate]);
|
interParams['AGGREGATE'] = params.aggregate.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
const rangeParams = [tempSetName, start, stop];
|
const rangeCmd = params.withScores ? 'zRangeWithScores' : 'zRange';
|
||||||
if (params.withScores) {
|
|
||||||
rangeParams.push('WITHSCORES');
|
|
||||||
}
|
|
||||||
|
|
||||||
const multi = module.client.multi();
|
const multi = module.client.multi();
|
||||||
multi.zinterstore(interParams);
|
multi.zInterStore(tempSetName, sets, interParams);
|
||||||
multi[params.method](rangeParams);
|
multi[rangeCmd](tempSetName, start, stop, { REV: params.reverse});
|
||||||
multi.del(tempSetName);
|
multi.del(tempSetName);
|
||||||
let results = await helpers.execBatch(multi);
|
let results = await helpers.execBatch(multi);
|
||||||
|
|
||||||
@@ -61,6 +55,6 @@ module.exports = function (module) {
|
|||||||
return results ? results[1] : null;
|
return results ? results[1] : null;
|
||||||
}
|
}
|
||||||
results = results[1] || [];
|
results = results[1] || [];
|
||||||
return helpers.zsetToObjectArray(results);
|
return results;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ module.exports = function (module) {
|
|||||||
|
|
||||||
if (Array.isArray(key)) {
|
if (Array.isArray(key)) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
key.forEach(k => batch.zrem(k, value));
|
key.forEach(k => batch.zRem(k, value.map(String)));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
} else {
|
} else {
|
||||||
await module.client.zrem(key, value);
|
await module.client.zRem(key, value.map(String));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ module.exports = function (module) {
|
|||||||
|
|
||||||
module.sortedSetsRemoveRangeByScore = async function (keys, min, max) {
|
module.sortedSetsRemoveRangeByScore = async function (keys, min, max) {
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
keys.forEach(k => batch.zremrangebyscore(k, min, max));
|
keys.forEach(k => batch.zRemRangeByScore(k, min, max));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ module.exports = function (module) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const batch = module.client.batch();
|
const batch = module.client.batch();
|
||||||
data.forEach(item => batch.zrem(item[0], item[1]));
|
data.forEach(item => batch.zRem(item[0], String(item[1])));
|
||||||
await helpers.execBatch(batch);
|
await helpers.execBatch(batch);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,25 +4,20 @@
|
|||||||
module.exports = function (module) {
|
module.exports = function (module) {
|
||||||
const helpers = require('../helpers');
|
const helpers = require('../helpers');
|
||||||
module.sortedSetUnionCard = async function (keys) {
|
module.sortedSetUnionCard = async function (keys) {
|
||||||
const tempSetName = `temp_${Date.now()}`;
|
|
||||||
if (!keys.length) {
|
if (!keys.length) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const multi = module.client.multi();
|
const results = await module.client.zUnion(keys);
|
||||||
multi.zunionstore([tempSetName, keys.length].concat(keys));
|
return results ? results.length : 0;
|
||||||
multi.zcard(tempSetName);
|
|
||||||
multi.del(tempSetName);
|
|
||||||
const results = await helpers.execBatch(multi);
|
|
||||||
return Array.isArray(results) && results.length ? results[1] : 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetUnion = async function (params) {
|
module.getSortedSetUnion = async function (params) {
|
||||||
params.method = 'zrange';
|
params.reverse = false;
|
||||||
return await module.sortedSetUnion(params);
|
return await module.sortedSetUnion(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.getSortedSetRevUnion = async function (params) {
|
module.getSortedSetRevUnion = async function (params) {
|
||||||
params.method = 'zrevrange';
|
params.reverse = true;
|
||||||
return await module.sortedSetUnion(params);
|
return await module.sortedSetUnion(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,21 +27,16 @@ module.exports = function (module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tempSetName = `temp_${Date.now()}`;
|
const tempSetName = `temp_${Date.now()}`;
|
||||||
|
const rangeCmd = params.withScores ? 'zRangeWithScores' : 'zRange';
|
||||||
const rangeParams = [tempSetName, params.start, params.stop];
|
|
||||||
if (params.withScores) {
|
|
||||||
rangeParams.push('WITHSCORES');
|
|
||||||
}
|
|
||||||
|
|
||||||
const multi = module.client.multi();
|
const multi = module.client.multi();
|
||||||
multi.zunionstore([tempSetName, params.sets.length].concat(params.sets));
|
multi.zUnionStore(tempSetName, params.sets);
|
||||||
multi[params.method](rangeParams);
|
multi[rangeCmd](tempSetName, params.start, params.stop, { REV: params.reverse });
|
||||||
multi.del(tempSetName);
|
multi.del(tempSetName);
|
||||||
let results = await helpers.execBatch(multi);
|
let results = await helpers.execBatch(multi);
|
||||||
if (!params.withScores) {
|
if (!params.withScores) {
|
||||||
return results ? results[1] : null;
|
return results ? results[1] : null;
|
||||||
}
|
}
|
||||||
results = results[1] || [];
|
results = results[1] || [];
|
||||||
return helpers.zsetToObjectArray(results);
|
return results;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ module.exports = function (Topics) {
|
|||||||
|
|
||||||
let { content } = postData;
|
let { content } = postData;
|
||||||
// ignore lines that start with `>`
|
// ignore lines that start with `>`
|
||||||
content = content.split('\n').filter(line => !line.trim().startsWith('>')).join('\n');
|
content = (content || '').split('\n').filter(line => !line.trim().startsWith('>')).join('\n');
|
||||||
// Scan post content for topic links
|
// Scan post content for topic links
|
||||||
const matches = [...content.matchAll(backlinkRegex)];
|
const matches = [...content.matchAll(backlinkRegex)];
|
||||||
if (!matches) {
|
if (!matches) {
|
||||||
|
|||||||
@@ -449,7 +449,8 @@ describe('Inbox resolution', () => {
|
|||||||
await activitypub.actors.assert(id);
|
await activitypub.actors.assert(id);
|
||||||
|
|
||||||
const inboxes = await activitypub.resolveInboxes([id]);
|
const inboxes = await activitypub.resolveInboxes([id]);
|
||||||
|
console.log('inboxes', inboxes);
|
||||||
|
console.log('actor', actor);
|
||||||
assert(inboxes && Array.isArray(inboxes));
|
assert(inboxes && Array.isArray(inboxes));
|
||||||
assert.strictEqual(inboxes.length, 1);
|
assert.strictEqual(inboxes.length, 1);
|
||||||
assert.strictEqual(inboxes[0], actor.inbox);
|
assert.strictEqual(inboxes[0], actor.inbox);
|
||||||
|
|||||||
@@ -650,7 +650,7 @@ describe('Notes', () => {
|
|||||||
|
|
||||||
it('should upvote an asserted remote post', async () => {
|
it('should upvote an asserted remote post', async () => {
|
||||||
const { id } = helpers.mocks.note();
|
const { id } = helpers.mocks.note();
|
||||||
await activitypub.notes.assert(0, [id], { skipChecks: true });
|
await activitypub.notes.assert(0, id, { skipChecks: true });
|
||||||
const { activity: like } = helpers.mocks.like({
|
const { activity: like } = helpers.mocks.like({
|
||||||
object: id,
|
object: id,
|
||||||
});
|
});
|
||||||
@@ -672,7 +672,7 @@ describe('Notes', () => {
|
|||||||
it('should update a note\'s content', async () => {
|
it('should update a note\'s content', async () => {
|
||||||
const { id: actor } = helpers.mocks.person();
|
const { id: actor } = helpers.mocks.person();
|
||||||
const { id, note } = helpers.mocks.note({ attributedTo: actor });
|
const { id, note } = helpers.mocks.note({ attributedTo: actor });
|
||||||
await activitypub.notes.assert(0, [id], { skipChecks: true });
|
await activitypub.notes.assert(0, id, { skipChecks: true });
|
||||||
note.content = utils.generateUUID();
|
note.content = utils.generateUUID();
|
||||||
const { activity: update } = helpers.mocks.update({ object: note });
|
const { activity: update } = helpers.mocks.update({ object: note });
|
||||||
const { activity } = helpers.mocks.announce({ object: update });
|
const { activity } = helpers.mocks.announce({ object: update });
|
||||||
|
|||||||
@@ -501,7 +501,9 @@ NUMERIC)-- WsPn&query[cid]=-1&parentCid=0&selectedCids[]=-1&privilege=topics:rea
|
|||||||
['byScoreWithScoresKeys1', 1, 'value1'],
|
['byScoreWithScoresKeys1', 1, 'value1'],
|
||||||
['byScoreWithScoresKeys2', 2, 'value2'],
|
['byScoreWithScoresKeys2', 2, 'value2'],
|
||||||
]);
|
]);
|
||||||
const data = await db.getSortedSetRevRangeByScoreWithScores(['byScoreWithScoresKeys1', 'byScoreWithScoresKeys2'], 0, -1, 5, -5);
|
const data = await db.getSortedSetRevRangeByScoreWithScores([
|
||||||
|
'byScoreWithScoresKeys1', 'byScoreWithScoresKeys2',
|
||||||
|
], 0, -1, 5, -5);
|
||||||
assert.deepStrictEqual(data, [{ value: 'value2', score: 2 }, { value: 'value1', score: 1 }]);
|
assert.deepStrictEqual(data, [{ value: 'value2', score: 2 }, { value: 'value1', score: 1 }]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1144,23 +1146,17 @@ NUMERIC)-- WsPn&query[cid]=-1&parentCid=0&selectedCids[]=-1&privilege=topics:rea
|
|||||||
assert.strictEqual(await db.exists('sorted3'), false);
|
assert.strictEqual(await db.exists('sorted3'), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove multiple values from multiple keys', (done) => {
|
it('should remove multiple values from multiple keys', async () => {
|
||||||
db.sortedSetAdd('multiTest1', [1, 2, 3, 4], ['one', 'two', 'three', 'four'], (err) => {
|
await db.sortedSetAdd('multiTest1', [1, 2, 3, 4], ['one', 'two', 'three', 'four']);
|
||||||
assert.ifError(err);
|
await db.sortedSetAdd('multiTest2', [3, 4, 5, 6], ['three', 'four', 'five', 'six']);
|
||||||
db.sortedSetAdd('multiTest2', [3, 4, 5, 6], ['three', 'four', 'five', 'six'], (err) => {
|
|
||||||
assert.ifError(err);
|
await db.sortedSetRemove(['multiTest1', 'multiTest2'], ['two', 'three', 'four', 'five', 'doesnt exist']);
|
||||||
db.sortedSetRemove(['multiTest1', 'multiTest2'], ['two', 'three', 'four', 'five', 'doesnt exist'], (err) => {
|
|
||||||
assert.ifError(err);
|
const members = await db.getSortedSetsMembers(['multiTest1', 'multiTest2']);
|
||||||
db.getSortedSetsMembers(['multiTest1', 'multiTest2'], (err, members) => {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.equal(members[0].length, 1);
|
assert.equal(members[0].length, 1);
|
||||||
assert.equal(members[1].length, 1);
|
assert.equal(members[1].length, 1);
|
||||||
assert.deepEqual(members, [['one'], ['six']]);
|
assert.deepEqual(members, [['one'], ['six']]);
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove value from multiple keys', async () => {
|
it('should remove value from multiple keys', async () => {
|
||||||
@@ -1171,24 +1167,15 @@ NUMERIC)-- WsPn&query[cid]=-1&parentCid=0&selectedCids[]=-1&privilege=topics:rea
|
|||||||
assert.deepStrictEqual(await db.getSortedSetRange('multiTest4', 0, -1), ['four', 'five', 'six']);
|
assert.deepStrictEqual(await db.getSortedSetRange('multiTest4', 0, -1), ['four', 'five', 'six']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove multiple values from multiple keys', (done) => {
|
it('should remove multiple values from multiple keys', async () => {
|
||||||
db.sortedSetAdd('multiTest5', [1], ['one'], (err) => {
|
await db.sortedSetAdd('multiTest5', [1], ['one']);
|
||||||
assert.ifError(err);
|
await db.sortedSetAdd('multiTest6', [2], ['two']);
|
||||||
db.sortedSetAdd('multiTest6', [2], ['two'], (err) => {
|
await db.sortedSetAdd('multiTest7', [3], [333]);
|
||||||
assert.ifError(err);
|
|
||||||
db.sortedSetAdd('multiTest7', [3], [333], (err) => {
|
await db.sortedSetRemove(['multiTest5', 'multiTest6', 'multiTest7'], ['one', 'two', 333]);
|
||||||
assert.ifError(err);
|
|
||||||
db.sortedSetRemove(['multiTest5', 'multiTest6', 'multiTest7'], ['one', 'two', 333], (err) => {
|
const members = await db.getSortedSetsMembers(['multiTest5', 'multiTest6', 'multiTest7']);
|
||||||
assert.ifError(err);
|
|
||||||
db.getSortedSetsMembers(['multiTest5', 'multiTest6', 'multiTest7'], (err, members) => {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.deepEqual(members, [[], [], []]);
|
assert.deepEqual(members, [[], [], []]);
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not remove anything if values is empty array', (done) => {
|
it('should not remove anything if values is empty array', (done) => {
|
||||||
@@ -1379,7 +1366,10 @@ NUMERIC)-- WsPn&query[cid]=-1&parentCid=0&selectedCids[]=-1&privilege=topics:rea
|
|||||||
weights: [1, 0.5],
|
weights: [1, 0.5],
|
||||||
}, (err, data) => {
|
}, (err, data) => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
assert.deepEqual([{ value: 'value2', score: 4 }, { value: 'value3', score: 5.5 }], data);
|
assert.deepEqual([
|
||||||
|
{ value: 'value2', score: 4 },
|
||||||
|
{ value: 'value3', score: 5.5 },
|
||||||
|
], data);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -171,7 +171,6 @@ before(async function () {
|
|||||||
require('../../src/user').startJobs();
|
require('../../src/user').startJobs();
|
||||||
|
|
||||||
await webserver.listen();
|
await webserver.listen();
|
||||||
|
|
||||||
// Iterate over all of the test suites/contexts
|
// Iterate over all of the test suites/contexts
|
||||||
this.test.parent.suites.forEach((suite) => {
|
this.test.parent.suites.forEach((suite) => {
|
||||||
// Attach an afterAll listener that resets the defaults
|
// Attach an afterAll listener that resets the defaults
|
||||||
|
|||||||
Reference in New Issue
Block a user