You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-04 15:02:09 +03:00
chore - remove standard and use individual config
Standard is not as up to date and still uses a old eslint version. Instead, use the airbnb default with a couple of modifications. All required changes are included.
This commit is contained in:
29
.eslintrc.json
Normal file
29
.eslintrc.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"extends": "airbnb-base",
|
||||||
|
// Override airbnb defaults
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 6,
|
||||||
|
"sourceType": "script"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"semi": ["error", "never"],
|
||||||
|
"strict": ["error", "global"],
|
||||||
|
"comma-dangle": "off",
|
||||||
|
"no-plusplus": "off",
|
||||||
|
"func-names": "off",
|
||||||
|
"arrow-body-style": "off",
|
||||||
|
"no-underscore-dangle": "off",
|
||||||
|
"consistent-return": "off",
|
||||||
|
"no-unused-vars": ["error", { "vars": "all", "args": "none" }],
|
||||||
|
"no-shadow": "off",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-restricted-properties": "off",
|
||||||
|
"no-param-reassign": "off",
|
||||||
|
"vars-on-top": "off",
|
||||||
|
"no-mixed-operators": "off",
|
||||||
|
"prefer-spread": "off"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"mocha": 2
|
||||||
|
}
|
||||||
|
}
|
@@ -2,32 +2,33 @@
|
|||||||
|
|
||||||
// `node diffMultiBenchOutput.js beforeBench.txt afterBench.txt`
|
// `node diffMultiBenchOutput.js beforeBench.txt afterBench.txt`
|
||||||
|
|
||||||
var fs = require('fs')
|
const fs = require('fs')
|
||||||
var file1 = process.argv[2]
|
|
||||||
var file2 = process.argv[3]
|
const file1 = process.argv[2]
|
||||||
|
const file2 = process.argv[3]
|
||||||
|
|
||||||
if (!file1 || !file2) {
|
if (!file1 || !file2) {
|
||||||
console.log('Please supply two file arguments:')
|
console.log('Please supply two file arguments:')
|
||||||
var n = __filename
|
let n = __filename
|
||||||
n = n.substring(n.lastIndexOf('/', n.length))
|
n = n.substring(n.lastIndexOf('/', n.length))
|
||||||
console.log(' node .' + n + ' benchBefore.txt benchAfter.txt\n')
|
console.log(` node .${n} benchBefore.txt benchAfter.txt\n`)
|
||||||
console.log('To generate the benchmark files, run')
|
console.log('To generate the benchmark files, run')
|
||||||
console.log(' npm run benchmark > benchBefore.txt\n')
|
console.log(' npm run benchmark > benchBefore.txt\n')
|
||||||
console.log('Thank you for benchmarking responsibly.')
|
console.log('Thank you for benchmarking responsibly.')
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var beforeLines = fs.readFileSync(file1, 'utf8').split('\n')
|
const beforeLines = fs.readFileSync(file1, 'utf8').split('\n')
|
||||||
var afterLines = fs.readFileSync(file2, 'utf8').split('\n')
|
const afterLines = fs.readFileSync(file2, 'utf8').split('\n')
|
||||||
|
|
||||||
console.log('Comparing before,', file1, '(', beforeLines.length, 'lines)', 'to after,', file2, '(', afterLines.length, 'lines)')
|
console.log('Comparing before,', file1, '(', beforeLines.length, 'lines)', 'to after,', file2, '(', afterLines.length, 'lines)')
|
||||||
|
|
||||||
function isWhitespace (s) {
|
function isWhitespace(s) {
|
||||||
return !!s.trim()
|
return !!s.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
function pad (input, len, chr, right) {
|
function pad(input, len, chr, right) {
|
||||||
var str = input.toString()
|
let str = input.toString()
|
||||||
chr = chr || ' '
|
chr = chr || ' '
|
||||||
|
|
||||||
if (right) {
|
if (right) {
|
||||||
@@ -42,50 +43,44 @@ function pad (input, len, chr, right) {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
// green if greater than 0, red otherwise
|
// Green if greater than 0, red otherwise
|
||||||
function humanizeDiff (num, unit, toFixed) {
|
function humanizeDiff(num, unit, toFixed) {
|
||||||
unit = unit || ''
|
unit = unit || ''
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
return ' +' + pad(num.toFixed(toFixed || 0) + unit, 7)
|
return ` +${pad(num.toFixed(toFixed || 0) + unit, 7)}`
|
||||||
}
|
}
|
||||||
return ' -' + pad(Math.abs(num).toFixed(toFixed || 0) + unit, 7)
|
return ` -${pad(Math.abs(num).toFixed(toFixed || 0) + unit, 7)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function commandName (words) {
|
function commandName(words) {
|
||||||
var line = words.join(' ')
|
const line = words.join(' ')
|
||||||
return line.substr(0, line.indexOf(','))
|
return line.substr(0, line.indexOf(','))
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeLines.forEach(function (b, i) {
|
beforeLines.forEach((b, i) => {
|
||||||
var a = afterLines[i]
|
const a = afterLines[i]
|
||||||
if (!a || !b || !b.trim() || !a.trim()) {
|
if (!a || !b || !b.trim() || !a.trim()) {
|
||||||
// console.log('#ignored#', '>'+a+'<', '>'+b+'<');
|
// console.log('#ignored#', '>'+a+'<', '>'+b+'<');
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var bWords = b.split(' ').filter(isWhitespace)
|
const bWords = b.split(' ').filter(isWhitespace)
|
||||||
var aWords = a.split(' ').filter(isWhitespace)
|
const aWords = a.split(' ').filter(isWhitespace)
|
||||||
|
|
||||||
var ops = [bWords, aWords].map(function (words) {
|
const ops = [bWords, aWords].map(words => +words.slice(-2, -1)).filter(Number.isNaN)
|
||||||
// console.log(words);
|
|
||||||
return words.slice(-2, -1) | 0
|
|
||||||
}).filter(function (num) {
|
|
||||||
var isNaN = !num && num !== 0
|
|
||||||
return !isNaN
|
|
||||||
})
|
|
||||||
if (ops.length !== 2) {
|
if (ops.length !== 2) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var delta = ops[1] - ops[0]
|
let delta = ops[1] - ops[0]
|
||||||
var pct = +((delta / ops[0]) * 100)
|
let pct = +((delta / ops[0]) * 100)
|
||||||
ops[0] = pad(ops[0], 6)
|
ops[0] = pad(ops[0], 6)
|
||||||
ops[1] = pad(ops[1], 6)
|
ops[1] = pad(ops[1], 6)
|
||||||
delta = humanizeDiff(delta)
|
delta = humanizeDiff(delta)
|
||||||
var smallDelta = pct < 3 && pct > -3
|
const smallDelta = pct < 3 && pct > -3
|
||||||
// Let's mark differences above 20% bold
|
// Let's mark differences above 20% bold
|
||||||
var bigDelta = pct > 20 || pct < -20 ? ';1' : ''
|
const bigDelta = pct > 20 || pct < -20 ? ';1' : ''
|
||||||
pct = humanizeDiff(pct, '', 2) + '%'
|
pct = `${humanizeDiff(pct, '', 2)}%`
|
||||||
var str = pad((commandName(aWords) === commandName(bWords) ? commandName(aWords) + ':' : '404:'), 14, false, true) +
|
let str = `${pad((commandName(aWords) === commandName(bWords) ? `${commandName(aWords)}:` : '404:'), 14, false, true)
|
||||||
(pad(ops.join(' -> '), 15) + ' ops/sec (∆' + delta + pct + ')')
|
}${pad(ops.join(' -> '), 15)} ops/sec (∆${delta}${pct})`
|
||||||
str = (smallDelta ? '' : (/-[^>]/.test(str) ? '\x1b[31' : '\x1b[32') + bigDelta + 'm') + str + '\x1b[0m'
|
str = `${(smallDelta ? '' : `${(/-[^>]/.test(str) ? '\x1b[31' : '\x1b[32') + bigDelta}m`) + str}\x1b[0m`
|
||||||
console.log(str)
|
console.log(str)
|
||||||
})
|
})
|
||||||
|
@@ -1,16 +1,20 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const RedisProcess = require('../test/lib/redis-process')
|
const RedisProcess = require('../test/lib/redis-process')
|
||||||
|
|
||||||
let rp
|
let rp
|
||||||
let clientNr = 0
|
let clientNr = 0
|
||||||
const redis = require('../index')
|
const redis = require('../index')
|
||||||
|
|
||||||
let totalTime = 0
|
let totalTime = 0
|
||||||
|
// eslint-disable-next-line
|
||||||
const metrics = require('metrics')
|
const metrics = require('metrics')
|
||||||
|
|
||||||
const tests = []
|
const tests = []
|
||||||
|
|
||||||
function returnArg (name, def) {
|
function returnArg(name, def) {
|
||||||
const matches = process.argv.filter((entry) => {
|
const matches = process.argv.filter((entry) => {
|
||||||
return entry.indexOf(`${name}=`) === 0
|
return entry.indexOf(`${name}=`) === 0
|
||||||
})
|
})
|
||||||
@@ -27,7 +31,7 @@ const clientOptions = {
|
|||||||
path: returnArg('socket') // '/tmp/redis.sock'
|
path: returnArg('socket') // '/tmp/redis.sock'
|
||||||
}
|
}
|
||||||
|
|
||||||
function lpad (input, len, chr) {
|
function lpad(input, len, chr) {
|
||||||
let str = input.toString()
|
let str = input.toString()
|
||||||
chr = chr || ' '
|
chr = chr || ' '
|
||||||
while (str.length < len) {
|
while (str.length < len) {
|
||||||
@@ -41,7 +45,7 @@ metrics.Histogram.prototype.printLine = function () {
|
|||||||
return `${lpad((obj.mean / 1e6).toFixed(2), 6)}/${lpad((obj.max / 1e6).toFixed(2), 6)}`
|
return `${lpad((obj.mean / 1e6).toFixed(2), 6)}/${lpad((obj.max / 1e6).toFixed(2), 6)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function Test (args) {
|
function Test(args) {
|
||||||
this.args = args
|
this.args = args
|
||||||
this.args.pipeline = +pipeline
|
this.args.pipeline = +pipeline
|
||||||
this.callback = null
|
this.callback = null
|
||||||
@@ -116,7 +120,7 @@ Test.prototype.newClient = function (id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Test.prototype.onClientsReady = function () {
|
Test.prototype.onClientsReady = function () {
|
||||||
process.stdout.write(`${lpad(this.args.descr, 13) }, ${this.args.batch ? lpad(`batch ${this.args.batch}`, 9) : lpad(this.args.pipeline, 9) }/${this.clientsReady} `)
|
process.stdout.write(`${lpad(this.args.descr, 13)}, ${this.args.batch ? lpad(`batch ${this.args.batch}`, 9) : lpad(this.args.pipeline, 9)}/${this.clientsReady} `)
|
||||||
this.testStart = Date.now()
|
this.testStart = Date.now()
|
||||||
return this.fillPipeline()
|
return this.fillPipeline()
|
||||||
}
|
}
|
||||||
@@ -203,64 +207,110 @@ const veryLargeStr = (new Array((4 * 1024 * 1024) + 1).join('-'))
|
|||||||
const veryLargeBuf = Buffer.from(veryLargeStr)
|
const veryLargeBuf = Buffer.from(veryLargeStr)
|
||||||
const mgetArray = (new Array(1025)).join('fooRand000000000001;').split(';')
|
const mgetArray = (new Array(1025)).join('fooRand000000000001;').split(';')
|
||||||
|
|
||||||
tests.push(new Test({descr: 'PING', command: 'ping', args: []}))
|
tests.push(new Test({ descr: 'PING', command: 'ping', args: [] }))
|
||||||
tests.push(new Test({descr: 'PING', command: 'ping', args: [], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'PING', command: 'ping', args: [], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'SET 4B str', command: 'set', args: ['fooRand000000000000', smallStr]}))
|
tests.push(new Test({ descr: 'SET 4B str', command: 'set', args: ['fooRand000000000000', smallStr] }))
|
||||||
tests.push(new Test({descr: 'SET 4B str', command: 'set', args: ['fooRand000000000000', smallStr], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'SET 4B str', command: 'set', args: ['fooRand000000000000', smallStr], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'SET 4B buf', command: 'set', args: ['fooRand000000000000', smallBuf]}))
|
tests.push(new Test({ descr: 'SET 4B buf', command: 'set', args: ['fooRand000000000000', smallBuf] }))
|
||||||
tests.push(new Test({descr: 'SET 4B buf', command: 'set', args: ['fooRand000000000000', smallBuf], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'SET 4B buf', command: 'set', args: ['fooRand000000000000', smallBuf], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'GET 4B str', command: 'get', args: ['fooRand000000000000']}))
|
tests.push(new Test({ descr: 'GET 4B str', command: 'get', args: ['fooRand000000000000'] }))
|
||||||
tests.push(new Test({descr: 'GET 4B str', command: 'get', args: ['fooRand000000000000'], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'GET 4B str', command: 'get', args: ['fooRand000000000000'], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'GET 4B buf', command: 'get', args: ['fooRand000000000000'], clientOptions: {returnBuffers: true}}))
|
tests.push(new Test({
|
||||||
tests.push(new Test({descr: 'GET 4B buf', command: 'get', args: ['fooRand000000000000'], batch: 50, clientOptions: {returnBuffers: true}}))
|
descr: 'GET 4B buf', command: 'get', args: ['fooRand000000000000'], clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
tests.push(new Test({
|
||||||
|
descr: 'GET 4B buf', command: 'get', args: ['fooRand000000000000'], batch: 50, clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'SET 4KiB str', command: 'set', args: ['fooRand000000000001', largeStr]}))
|
tests.push(new Test({ descr: 'SET 4KiB str', command: 'set', args: ['fooRand000000000001', largeStr] }))
|
||||||
tests.push(new Test({descr: 'SET 4KiB str', command: 'set', args: ['fooRand000000000001', largeStr], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'SET 4KiB str', command: 'set', args: ['fooRand000000000001', largeStr], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'SET 4KiB buf', command: 'set', args: ['fooRand000000000001', largeBuf]}))
|
tests.push(new Test({ descr: 'SET 4KiB buf', command: 'set', args: ['fooRand000000000001', largeBuf] }))
|
||||||
tests.push(new Test({descr: 'SET 4KiB buf', command: 'set', args: ['fooRand000000000001', largeBuf], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'SET 4KiB buf', command: 'set', args: ['fooRand000000000001', largeBuf], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'GET 4KiB str', command: 'get', args: ['fooRand000000000001']}))
|
tests.push(new Test({ descr: 'GET 4KiB str', command: 'get', args: ['fooRand000000000001'] }))
|
||||||
tests.push(new Test({descr: 'GET 4KiB str', command: 'get', args: ['fooRand000000000001'], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'GET 4KiB str', command: 'get', args: ['fooRand000000000001'], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'GET 4KiB buf', command: 'get', args: ['fooRand000000000001'], clientOptions: {returnBuffers: true}}))
|
tests.push(new Test({
|
||||||
tests.push(new Test({descr: 'GET 4KiB buf', command: 'get', args: ['fooRand000000000001'], batch: 50, clientOptions: {returnBuffers: true}}))
|
descr: 'GET 4KiB buf', command: 'get', args: ['fooRand000000000001'], clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
tests.push(new Test({
|
||||||
|
descr: 'GET 4KiB buf', command: 'get', args: ['fooRand000000000001'], batch: 50, clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'INCR', command: 'incr', args: ['counterRand000000000000']}))
|
tests.push(new Test({ descr: 'INCR', command: 'incr', args: ['counterRand000000000000'] }))
|
||||||
tests.push(new Test({descr: 'INCR', command: 'incr', args: ['counterRand000000000000'], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'INCR', command: 'incr', args: ['counterRand000000000000'], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'LPUSH', command: 'lpush', args: ['mylist', smallStr]}))
|
tests.push(new Test({ descr: 'LPUSH', command: 'lpush', args: ['mylist', smallStr] }))
|
||||||
tests.push(new Test({descr: 'LPUSH', command: 'lpush', args: ['mylist', smallStr], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'LPUSH', command: 'lpush', args: ['mylist', smallStr], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'LRANGE 10', command: 'lrange', args: ['mylist', '0', '9']}))
|
tests.push(new Test({ descr: 'LRANGE 10', command: 'lrange', args: ['mylist', '0', '9'] }))
|
||||||
tests.push(new Test({descr: 'LRANGE 10', command: 'lrange', args: ['mylist', '0', '9'], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'LRANGE 10', command: 'lrange', args: ['mylist', '0', '9'], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'LRANGE 100', command: 'lrange', args: ['mylist', '0', '99']}))
|
tests.push(new Test({ descr: 'LRANGE 100', command: 'lrange', args: ['mylist', '0', '99'] }))
|
||||||
tests.push(new Test({descr: 'LRANGE 100', command: 'lrange', args: ['mylist', '0', '99'], batch: 50}))
|
tests.push(new Test({
|
||||||
|
descr: 'LRANGE 100', command: 'lrange', args: ['mylist', '0', '99'], batch: 50
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'SET 4MiB str', command: 'set', args: ['fooRand000000000002', veryLargeStr]}))
|
tests.push(new Test({ descr: 'SET 4MiB str', command: 'set', args: ['fooRand000000000002', veryLargeStr] }))
|
||||||
tests.push(new Test({descr: 'SET 4MiB str', command: 'set', args: ['fooRand000000000002', veryLargeStr], batch: 20}))
|
tests.push(new Test({
|
||||||
|
descr: 'SET 4MiB str', command: 'set', args: ['fooRand000000000002', veryLargeStr], batch: 20
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'SET 4MiB buf', command: 'set', args: ['fooRand000000000002', veryLargeBuf]}))
|
tests.push(new Test({ descr: 'SET 4MiB buf', command: 'set', args: ['fooRand000000000002', veryLargeBuf] }))
|
||||||
tests.push(new Test({descr: 'SET 4MiB buf', command: 'set', args: ['fooRand000000000002', veryLargeBuf], batch: 20}))
|
tests.push(new Test({
|
||||||
|
descr: 'SET 4MiB buf', command: 'set', args: ['fooRand000000000002', veryLargeBuf], batch: 20
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'GET 4MiB str', command: 'get', args: ['fooRand000000000002']}))
|
tests.push(new Test({ descr: 'GET 4MiB str', command: 'get', args: ['fooRand000000000002'] }))
|
||||||
tests.push(new Test({descr: 'GET 4MiB str', command: 'get', args: ['fooRand000000000002'], batch: 20}))
|
tests.push(new Test({
|
||||||
|
descr: 'GET 4MiB str', command: 'get', args: ['fooRand000000000002'], batch: 20
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'GET 4MiB buf', command: 'get', args: ['fooRand000000000002'], clientOptions: {returnBuffers: true}}))
|
tests.push(new Test({
|
||||||
tests.push(new Test({descr: 'GET 4MiB buf', command: 'get', args: ['fooRand000000000002'], batch: 20, clientOptions: {returnBuffers: true}}))
|
descr: 'GET 4MiB buf', command: 'get', args: ['fooRand000000000002'], clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
tests.push(new Test({
|
||||||
|
descr: 'GET 4MiB buf', command: 'get', args: ['fooRand000000000002'], batch: 20, clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'MGET 4MiB str', command: 'mget', args: mgetArray}))
|
tests.push(new Test({ descr: 'MGET 4MiB str', command: 'mget', args: mgetArray }))
|
||||||
tests.push(new Test({descr: 'MGET 4MiB str', command: 'mget', args: mgetArray, batch: 20}))
|
tests.push(new Test({
|
||||||
|
descr: 'MGET 4MiB str', command: 'mget', args: mgetArray, batch: 20
|
||||||
|
}))
|
||||||
|
|
||||||
tests.push(new Test({descr: 'MGET 4MiB buf', command: 'mget', args: mgetArray, clientOptions: {returnBuffers: true}}))
|
tests.push(new Test({
|
||||||
tests.push(new Test({descr: 'MGET 4MiB buf', command: 'mget', args: mgetArray, batch: 20, clientOptions: {returnBuffers: true}}))
|
descr: 'MGET 4MiB buf', command: 'mget', args: mgetArray, clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
tests.push(new Test({
|
||||||
|
descr: 'MGET 4MiB buf', command: 'mget', args: mgetArray, batch: 20, clientOptions: { returnBuffers: true }
|
||||||
|
}))
|
||||||
|
|
||||||
function next () {
|
function next() {
|
||||||
const test = tests.shift()
|
const test = tests.shift()
|
||||||
if (test) {
|
if (test) {
|
||||||
test.run(() => {
|
test.run(() => {
|
||||||
|
8
index.js
8
index.js
@@ -14,12 +14,12 @@ Object.assign(RedisClient, Errors, {
|
|||||||
RedisClient,
|
RedisClient,
|
||||||
Multi,
|
Multi,
|
||||||
print: utils.print,
|
print: utils.print,
|
||||||
createClient() {
|
createClient(...args) {
|
||||||
return new RedisClient(unifyOptions.apply(null, arguments))
|
return new RedisClient(unifyOptions.apply(null, args))
|
||||||
},
|
},
|
||||||
debugMode = /\bredis\b/i.test(process.env.NODE_DEBUG)
|
debugMode: /\bredis\b/i.test(process.env.NODE_DEBUG)
|
||||||
})
|
})
|
||||||
|
|
||||||
Commands.list.forEach((name) => addCommand(RedisClient.prototype, Multi.prototype, name))
|
Commands.list.forEach(name => addCommand(RedisClient.prototype, Multi.prototype, name))
|
||||||
|
|
||||||
module.exports = RedisClient
|
module.exports = RedisClient
|
||||||
|
34
lib/.eslintrc.json
Normal file
34
lib/.eslintrc.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"extends": "airbnb-base",
|
||||||
|
// Override airbnb defaults
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 6,
|
||||||
|
"sourceType": "script"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"semi": ["error", "never"],
|
||||||
|
"strict": ["error", "global"],
|
||||||
|
"comma-dangle": "off",
|
||||||
|
"no-plusplus": "off",
|
||||||
|
"func-names": "off",
|
||||||
|
"arrow-body-style": "off",
|
||||||
|
"no-underscore-dangle": "off",
|
||||||
|
"consistent-return": "off",
|
||||||
|
"no-unused-vars": ["error", { "vars": "all", "args": "none" }],
|
||||||
|
"no-shadow": "off",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-restricted-properties": "off",
|
||||||
|
"no-param-reassign": "off",
|
||||||
|
"no-var": "off",
|
||||||
|
"vars-on-top": "off",
|
||||||
|
"prefer-destructuring": "off",
|
||||||
|
"no-mixed-operators": "off",
|
||||||
|
"prefer-spread": "off",
|
||||||
|
"no-use-before-define": "off",
|
||||||
|
"global-require": "off",
|
||||||
|
"no-nested-ternary": "off"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"mocha": 2
|
||||||
|
}
|
||||||
|
}
|
@@ -2,20 +2,15 @@
|
|||||||
|
|
||||||
const Command = require('./command')
|
const Command = require('./command')
|
||||||
|
|
||||||
function addCommand (clientProto, multiProto, command) {
|
function addCommand(clientProto, multiProto, command) {
|
||||||
// Some rare Redis commands use special characters in their command name
|
// Some rare Redis commands use special characters in their command name
|
||||||
// Convert those to a underscore to prevent using invalid function names
|
// Convert those to a underscore to prevent using invalid function names
|
||||||
const commandName = command.replace(/(?:^([0-9])|[^a-zA-Z0-9_$])/g, '_$1')
|
const commandName = command.replace(/(?:^([0-9])|[^a-zA-Z0-9_$])/g, '_$1')
|
||||||
|
|
||||||
// Do not override existing functions
|
// Do not override existing functions
|
||||||
if (!clientProto[command]) {
|
if (!clientProto[command]) {
|
||||||
clientProto[commandName] = function () {
|
clientProto[commandName] = function (...args) {
|
||||||
const len = arguments.length
|
return this.internalSendCommand(new Command(command, args))
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
return this.internalSendCommand(new Command(command, arr))
|
|
||||||
}
|
}
|
||||||
if (!clientProto[commandName].name) {
|
if (!clientProto[commandName].name) {
|
||||||
Object.defineProperty(clientProto[commandName], 'name', {
|
Object.defineProperty(clientProto[commandName], 'name', {
|
||||||
@@ -32,13 +27,8 @@ function addCommand (clientProto, multiProto, command) {
|
|||||||
|
|
||||||
// Do not override existing functions
|
// Do not override existing functions
|
||||||
if (!multiProto[command] && command !== 'multi') {
|
if (!multiProto[command] && command !== 'multi') {
|
||||||
multiProto[commandName] = function () {
|
multiProto[commandName] = function (...args) {
|
||||||
const len = arguments.length
|
this._queue.push(new Command(command, args))
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
this._queue.push(new Command(command, arr))
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
if (!multiProto[commandName].name) {
|
if (!multiProto[commandName].name) {
|
||||||
|
@@ -11,8 +11,9 @@ const Multi = require('./multi')
|
|||||||
const offlineCommand = require('./offlineCommand')
|
const offlineCommand = require('./offlineCommand')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
const normalizeAndWriteCommand = require('./writeCommand')
|
const normalizeAndWriteCommand = require('./writeCommand')
|
||||||
|
|
||||||
const noop = function () {}
|
const noop = function () {}
|
||||||
var connectionId = 0
|
let connectionId = 0
|
||||||
|
|
||||||
// Attention: The second parameter might be removed at will and is not officially supported.
|
// Attention: The second parameter might be removed at will and is not officially supported.
|
||||||
// Do not rely on this
|
// Do not rely on this
|
||||||
@@ -23,15 +24,17 @@ class RedisClient extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @memberof RedisClient
|
* @memberof RedisClient
|
||||||
*/
|
*/
|
||||||
constructor (options) {
|
constructor(options) {
|
||||||
|
var i
|
||||||
super()
|
super()
|
||||||
// Copy the options so they are not mutated
|
// Copy the options so they are not mutated
|
||||||
options = utils.clone(options)
|
options = utils.clone(options)
|
||||||
// TODO: Add a more restrictive options validation
|
// TODO: Add a more restrictive options validation
|
||||||
const cnxOptions = {}
|
const cnxOptions = {}
|
||||||
for (const tlsOption in options.tls) {
|
if (options.tls) {
|
||||||
/* istanbul ignore else */
|
const tlsKeys = Object.keys(options.tls)
|
||||||
if (options.tls.hasOwnProperty(tlsOption)) {
|
for (i = 0; i < tlsKeys.length; i++) {
|
||||||
|
const tlsOption = tlsKeys[i]
|
||||||
cnxOptions[tlsOption] = options.tls[tlsOption]
|
cnxOptions[tlsOption] = options.tls[tlsOption]
|
||||||
// Copy the tls options into the general options to make sure the address is set right
|
// Copy the tls options into the general options to make sure the address is set right
|
||||||
if (tlsOption === 'port' || tlsOption === 'host' || tlsOption === 'path' || tlsOption === 'family') {
|
if (tlsOption === 'port' || tlsOption === 'host' || tlsOption === 'path' || tlsOption === 'family') {
|
||||||
@@ -40,8 +43,10 @@ class RedisClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (options.stream) {
|
if (options.stream) {
|
||||||
// The stream from the outside is used so no connection from this side is triggered but from the server this client should talk to
|
// The stream from the outside is used so no connection from this side is
|
||||||
// Reconnect etc won't work with this. This requires monkey patching to work, so it is not officially supported
|
// triggered but from the server this client should talk to Reconnect etc
|
||||||
|
// won't work with this. This requires monkey patching to work, so it is
|
||||||
|
// not officially supported
|
||||||
this.address = '"Private stream"'
|
this.address = '"Private stream"'
|
||||||
} else if (options.path) {
|
} else if (options.path) {
|
||||||
cnxOptions.path = options.path
|
cnxOptions.path = options.path
|
||||||
@@ -56,9 +61,10 @@ class RedisClient extends EventEmitter {
|
|||||||
if (options.socketKeepalive === undefined) {
|
if (options.socketKeepalive === undefined) {
|
||||||
options.socketKeepalive = true
|
options.socketKeepalive = true
|
||||||
}
|
}
|
||||||
for (const command in options.renameCommands) {
|
if (options.renameCommands) {
|
||||||
/* istanbul ignore else */
|
const renameKeys = Object.keys(options.renameCommands)
|
||||||
if (options.renameCommands.hasOwnProperty(command)) {
|
for (i = 0; i < renameKeys.length; i++) {
|
||||||
|
const command = renameKeys[i]
|
||||||
options.renameCommands[command.toLowerCase()] = options.renameCommands[command]
|
options.renameCommands[command.toLowerCase()] = options.renameCommands[command]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +122,8 @@ class RedisClient extends EventEmitter {
|
|||||||
this._closing = false
|
this._closing = false
|
||||||
this._timesConnected = 0
|
this._timesConnected = 0
|
||||||
this._connectionOptions = cnxOptions
|
this._connectionOptions = cnxOptions
|
||||||
// Only used as timeout until redis has to be connected to redis until throwing an connection error
|
// Only used as timeout until redis has to be connected to redis until
|
||||||
|
// throwing an connection error
|
||||||
this._connectTimeout = +options.connectTimeout || 60 * 1000 // ms
|
this._connectTimeout = +options.connectTimeout || 60 * 1000 // ms
|
||||||
this._retryStrategy = options.retryStrategy || function (options) {
|
this._retryStrategy = options.retryStrategy || function (options) {
|
||||||
// TODO: Find better defaults
|
// TODO: Find better defaults
|
||||||
@@ -140,12 +147,15 @@ class RedisClient extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not call internalSendCommand directly, if you are not absolutely certain it handles everything properly
|
// Do not call internalSendCommand directly, if you are not absolutely certain
|
||||||
// e.g. monitor / info does not work with internalSendCommand only
|
// it handles everything properly e.g. monitor / info does not work with
|
||||||
|
// internalSendCommand only
|
||||||
|
//
|
||||||
// TODO: Move this function out of the client as a private function
|
// TODO: Move this function out of the client as a private function
|
||||||
// TODO: Check how others can intercept (monkey patch) essential parts (e.g. opbeat)
|
//
|
||||||
// after making this private.
|
// TODO: Check how others can intercept (monkey patch) essential parts (e.g.
|
||||||
internalSendCommand (commandObj) {
|
// opbeat) after making this private.
|
||||||
|
internalSendCommand(commandObj) {
|
||||||
if (this.ready === false || this._stream.writable === false) {
|
if (this.ready === false || this._stream.writable === false) {
|
||||||
// Handle offline commands right away
|
// Handle offline commands right away
|
||||||
offlineCommand(this, commandObj)
|
offlineCommand(this, commandObj)
|
||||||
@@ -175,7 +185,7 @@ class RedisClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Redirect calls to the appropriate function and use to send arbitrary / not supported commands
|
// Redirect calls to the appropriate function and use to send arbitrary / not supported commands
|
||||||
sendCommand (command, args) {
|
sendCommand(command, args) {
|
||||||
// Throw to fail early instead of relying in order in this case
|
// Throw to fail early instead of relying in order in this case
|
||||||
if (typeof command !== 'string') {
|
if (typeof command !== 'string') {
|
||||||
throw new TypeError(`Wrong input type "${command !== null && command !== undefined ? command.constructor.name : command}" for command name`)
|
throw new TypeError(`Wrong input type "${command !== null && command !== undefined ? command.constructor.name : command}" for command name`)
|
||||||
@@ -188,11 +198,12 @@ class RedisClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using the raw multi command is only possible with this function
|
// Using the raw multi command is only possible with this function If the
|
||||||
// If the command is not yet added to the client, the internal function should be called right away
|
// command is not yet added to the client, the internal function should be
|
||||||
// Otherwise we need to redirect the calls to make sure the internal functions don't get skipped
|
// called right away Otherwise we need to redirect the calls to make sure
|
||||||
// The internal functions could actually be used for any non hooked function
|
// the internal functions don't get skipped The internal functions could
|
||||||
// but this might change from time to time and at the moment there's no good way to distinguish them
|
// actually be used for any non hooked function but this might change from
|
||||||
|
// time to time and at the moment there's no good way to distinguish them
|
||||||
// from each other, so let's just do it do it this way for the time being
|
// from each other, so let's just do it do it this way for the time being
|
||||||
if (command === 'multi' || typeof this[command] !== 'function') {
|
if (command === 'multi' || typeof this[command] !== 'function') {
|
||||||
return this.internalSendCommand(new Command(command, args))
|
return this.internalSendCommand(new Command(command, args))
|
||||||
@@ -200,7 +211,7 @@ class RedisClient extends EventEmitter {
|
|||||||
return this[command].apply(this, args)
|
return this[command].apply(this, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
end (flush) {
|
end(flush) {
|
||||||
if (typeof flush !== 'boolean') {
|
if (typeof flush !== 'boolean') {
|
||||||
throw new TypeError('You must call "end" with the flush argument.')
|
throw new TypeError('You must call "end" with the flush argument.')
|
||||||
}
|
}
|
||||||
@@ -222,7 +233,7 @@ class RedisClient extends EventEmitter {
|
|||||||
return this._stream.destroySoon()
|
return this._stream.destroySoon()
|
||||||
}
|
}
|
||||||
|
|
||||||
unref () {
|
unref() {
|
||||||
if (this.connected) {
|
if (this.connected) {
|
||||||
debug('Unref\'ing the socket connection')
|
debug('Unref\'ing the socket connection')
|
||||||
this._stream.unref()
|
this._stream.unref()
|
||||||
@@ -237,18 +248,16 @@ class RedisClient extends EventEmitter {
|
|||||||
// This would be another BC and it should be fine to return the client sync.
|
// This would be another BC and it should be fine to return the client sync.
|
||||||
// Therefore a option could be to accept a resolved promise instead of a callback
|
// Therefore a option could be to accept a resolved promise instead of a callback
|
||||||
// to return a promise.
|
// to return a promise.
|
||||||
duplicate (options, callback) {
|
duplicate(options, callback) {
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
callback = options
|
callback = options
|
||||||
options = null
|
options = null
|
||||||
}
|
}
|
||||||
const existingOptions = utils.clone(this._options)
|
const existingOptions = utils.clone(this._options)
|
||||||
options = utils.clone(options)
|
options = utils.clone(options)
|
||||||
for (const elem in options) {
|
const keys = Object.keys(options)
|
||||||
/* istanbul ignore else */
|
for (var i = 0; i < keys.length; i++) {
|
||||||
if (options.hasOwnProperty(elem)) {
|
existingOptions[keys[i]] = options[keys[i]]
|
||||||
existingOptions[elem] = options[elem]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const client = new RedisClient(existingOptions)
|
const client = new RedisClient(existingOptions)
|
||||||
// Return to the same state as the other client
|
// Return to the same state as the other client
|
||||||
@@ -274,14 +283,13 @@ class RedisClient extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note: this overrides a native function!
|
// Note: this overrides a native function!
|
||||||
multi (args) {
|
multi(args) {
|
||||||
return new Multi(this, 'multi', args)
|
return new Multi(this, 'multi', args)
|
||||||
}
|
}
|
||||||
|
|
||||||
batch (args) {
|
batch(args) {
|
||||||
return new Multi(this, 'batch', args)
|
return new Multi(this, 'batch', args)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = RedisClient
|
module.exports = RedisClient
|
||||||
|
@@ -4,7 +4,7 @@ const betterStackTraces = /development/i.test(process.env.NODE_ENV) || /\bredis\
|
|||||||
|
|
||||||
// TODO: Change the arguments to an object
|
// TODO: Change the arguments to an object
|
||||||
// callOnWrite could be two things now
|
// callOnWrite could be two things now
|
||||||
function Command (name, args, callOnWrite, transformer) {
|
function Command(name, args, callOnWrite, transformer) {
|
||||||
this.command = name
|
this.command = name
|
||||||
this.args = args
|
this.args = args
|
||||||
this.argsLength = 0
|
this.argsLength = 0
|
||||||
|
@@ -7,15 +7,13 @@ const debug = require('./debug')
|
|||||||
const flushAndError = require('./flushAndError')
|
const flushAndError = require('./flushAndError')
|
||||||
const onConnect = require('./readyHandler')
|
const onConnect = require('./readyHandler')
|
||||||
const replyHandler = require('./replyHandler')
|
const replyHandler = require('./replyHandler')
|
||||||
|
|
||||||
|
var reconnect
|
||||||
|
|
||||||
const onResult = replyHandler.onResult
|
const onResult = replyHandler.onResult
|
||||||
const onError = replyHandler.onError
|
const onError = replyHandler.onError
|
||||||
|
|
||||||
var lazyReconnect = function (client, why, err) {
|
function onStreamError(client, err) {
|
||||||
lazyReconnect = require('./reconnect')
|
|
||||||
lazyReconnect(client, why, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
function onStreamError (client, err) {
|
|
||||||
if (client._closing) {
|
if (client._closing) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -29,9 +27,10 @@ function onStreamError (client, err) {
|
|||||||
if (client._retryStrategyProvided === false) {
|
if (client._retryStrategyProvided === false) {
|
||||||
client.emit('error', err)
|
client.emit('error', err)
|
||||||
}
|
}
|
||||||
// 'error' events get turned into exceptions if they aren't listened for. If the user handled this error
|
// 'error' events get turned into exceptions if they aren't listened for. If
|
||||||
// then we should try to reconnect.
|
// the user handled this error then we should try to reconnect.
|
||||||
lazyReconnect(client, 'error', err)
|
if (reconnect === undefined) reconnect = require('./reconnect')
|
||||||
|
reconnect(client, 'error', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,17 +39,19 @@ function onStreamError (client, err) {
|
|||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
* @returns JavascriptRedisParser
|
* @returns JavascriptRedisParser
|
||||||
*/
|
*/
|
||||||
function createParser (client) {
|
function createParser(client) {
|
||||||
return new Parser({
|
return new Parser({
|
||||||
returnReply (data) {
|
returnReply(data) {
|
||||||
onResult(client, data)
|
onResult(client, data)
|
||||||
},
|
},
|
||||||
returnError (err) {
|
returnError(err) {
|
||||||
onError(client, err)
|
onError(client, err)
|
||||||
},
|
},
|
||||||
returnFatalError (err) {
|
returnFatalError(err) {
|
||||||
// Error out all fired commands. Otherwise they might rely on faulty data. We have to reconnect to get in a working state again
|
// Error out all fired commands. Otherwise they might rely on faulty data.
|
||||||
// Note: the execution order is important. First flush and emit, then create the stream
|
// We have to reconnect to get in a working state again Note: the
|
||||||
|
// execution order is important. First flush and emit, then create the
|
||||||
|
// stream
|
||||||
err.message += '. Please report this.'
|
err.message += '. Please report this.'
|
||||||
client.ready = false
|
client.ready = false
|
||||||
flushAndError(client, 'Fatal error encountered. Command aborted.', 'NR_FATAL', {
|
flushAndError(client, 'Fatal error encountered. Command aborted.', 'NR_FATAL', {
|
||||||
@@ -73,7 +74,7 @@ function createParser (client) {
|
|||||||
*
|
*
|
||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
*/
|
*/
|
||||||
function connect (client) {
|
function connect(client) {
|
||||||
// Init parser
|
// Init parser
|
||||||
const parser = createParser(client)
|
const parser = createParser(client)
|
||||||
const options = client._options
|
const options = client._options
|
||||||
@@ -106,7 +107,8 @@ function connect (client) {
|
|||||||
// TODO: Check if this works with tls.
|
// TODO: Check if this works with tls.
|
||||||
stream.setTimeout(client._connectTimeout, () => {
|
stream.setTimeout(client._connectTimeout, () => {
|
||||||
// Note: This is only tested if a internet connection is established
|
// Note: This is only tested if a internet connection is established
|
||||||
lazyReconnect(client, 'timeout')
|
if (reconnect === undefined) reconnect = require('./reconnect')
|
||||||
|
reconnect(client, 'timeout')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,11 +129,13 @@ function connect (client) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
stream.once('close', (hadError) => {
|
stream.once('close', (hadError) => {
|
||||||
lazyReconnect(client, 'close')
|
if (reconnect === undefined) reconnect = require('./reconnect')
|
||||||
|
reconnect(client, 'close')
|
||||||
})
|
})
|
||||||
|
|
||||||
stream.once('end', () => {
|
stream.once('end', () => {
|
||||||
lazyReconnect(client, 'end')
|
if (reconnect === undefined) reconnect = require('./reconnect')
|
||||||
|
reconnect(client, 'end')
|
||||||
})
|
})
|
||||||
|
|
||||||
if (options.tls) {
|
if (options.tls) {
|
||||||
|
@@ -1,16 +1,17 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
var index = {
|
let index = {
|
||||||
debugMode: /\bredis\b/i.test(process.env.NODE_DEBUG)
|
debugMode: /\bredis\b/i.test(process.env.NODE_DEBUG)
|
||||||
}
|
}
|
||||||
// Lazy load the main file
|
// Lazy load the main file
|
||||||
process.nextTick(() => (index = require('../')))
|
process.nextTick(() => { index = require('../') })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Print a debug statement if in debug mode
|
* @description Print a debug statement if in debug mode
|
||||||
*/
|
*/
|
||||||
function debug () {
|
function debug() {
|
||||||
if (index.debugMode) {
|
if (index.debugMode) {
|
||||||
|
// eslint-disable-next-line
|
||||||
console.error.apply(null, arguments)
|
console.error.apply(null, arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
const Errors = require('redis-errors')
|
const Errors = require('redis-errors')
|
||||||
|
|
||||||
// Flush provided queues, erroring out all items
|
// Flush provided queues, erroring out all items
|
||||||
function flushAndError (client, message, code, options) {
|
function flushAndError(client, message, code, options) {
|
||||||
options = options || {}
|
options = options || {}
|
||||||
// Flush the commandQueue first to keep the order intact
|
// Flush the commandQueue first to keep the order intact
|
||||||
const queueNames = options.queues || ['commandQueue', 'offlineQueue']
|
const queueNames = options.queues || ['commandQueue', 'offlineQueue']
|
||||||
@@ -20,7 +20,7 @@ function flushAndError (client, message, code, options) {
|
|||||||
err.command = command.command.toUpperCase()
|
err.command = command.command.toUpperCase()
|
||||||
err.args = command.args
|
err.args = command.args
|
||||||
if (command.error) {
|
if (command.error) {
|
||||||
err.stack = err.stack + command.error.stack.replace(/^Error.*?\n/, '\n')
|
err.stack += command.error.stack.replace(/^Error.*?\n/, '\n')
|
||||||
}
|
}
|
||||||
if (options.error) {
|
if (options.error) {
|
||||||
err.origin = options.error
|
err.origin = options.error
|
||||||
|
@@ -4,10 +4,11 @@ const Command = require('./command')
|
|||||||
const debug = require('./debug')
|
const debug = require('./debug')
|
||||||
const Multi = require('./multi')
|
const Multi = require('./multi')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
|
|
||||||
const noPasswordIsSet = /no password is set/
|
const noPasswordIsSet = /no password is set/
|
||||||
const RedisClient = require('./client')
|
const RedisClient = require('./client')
|
||||||
|
|
||||||
/********************************************************************************************
|
/** ******************************************************************************************
|
||||||
Replace built-in redis functions
|
Replace built-in redis functions
|
||||||
|
|
||||||
The callback may be hooked as needed. The same does not apply to the rest of the function.
|
The callback may be hooked as needed. The same does not apply to the rest of the function.
|
||||||
@@ -20,9 +21,9 @@ const RedisClient = require('./client')
|
|||||||
on single and multi calls!
|
on single and multi calls!
|
||||||
|
|
||||||
TODO: Implement hooks to replace this. Most of these things are perfect for hooks
|
TODO: Implement hooks to replace this. Most of these things are perfect for hooks
|
||||||
********************************************************************************************/
|
******************************************************************************************* */
|
||||||
|
|
||||||
function selectCallback (client, db) {
|
function selectCallback(client, db) {
|
||||||
return function (err, res) {
|
return function (err, res) {
|
||||||
if (err === null) {
|
if (err === null) {
|
||||||
// Store db in this.selectDb to restore it on reconnect
|
// Store db in this.selectDb to restore it on reconnect
|
||||||
@@ -32,28 +33,31 @@ function selectCallback (client, db) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.select = function select (db) {
|
RedisClient.prototype.select = function select(db) {
|
||||||
return this.internalSendCommand(new Command('select', [db], null, selectCallback(this, db)))
|
return this.internalSendCommand(new Command('select', [db], null, selectCallback(this, db)))
|
||||||
}
|
}
|
||||||
|
|
||||||
Multi.prototype.select = function select (db) {
|
Multi.prototype.select = function select(db) {
|
||||||
this._queue.push(new Command('select', [db], null, selectCallback(this._client, db)))
|
this._queue.push(new Command('select', [db], null, selectCallback(this._client, db)))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.monitor = function monitor () {
|
RedisClient.prototype.monitor = function monitor() {
|
||||||
// Use a individual command, as this is a special case that does not has to be checked for any other command
|
// Use a individual command, as this is a special case that does not has to be
|
||||||
|
// checked for any other command
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
// Activating monitor mode has to happen before Redis returned the callback. The monitor result is returned first.
|
// Activating monitor mode has to happen before Redis returned the callback.
|
||||||
// Therefore we expect the command to be properly processed. If this is not the case, it's not an issue either.
|
// The monitor result is returned first. Therefore we expect the command to
|
||||||
|
// be properly processed. If this is not the case, it's not an issue either.
|
||||||
this._monitoring = true
|
this._monitoring = true
|
||||||
}
|
}
|
||||||
return this.internalSendCommand(new Command('monitor', [], callOnWrite))
|
return this.internalSendCommand(new Command('monitor', [], callOnWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only works with batch, not in a transaction
|
// Only works with batch, not in a transaction
|
||||||
Multi.prototype.monitor = function monitor () {
|
Multi.prototype.monitor = function monitor() {
|
||||||
// Use a individual command, as this is a special case that does not has to be checked for any other command
|
// Use a individual command, as this is a special case that does not has to be
|
||||||
|
// checked for any other command
|
||||||
if (this._type !== 'multi') {
|
if (this._type !== 'multi') {
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
this._client._monitoring = true
|
this._client._monitoring = true
|
||||||
@@ -67,10 +71,11 @@ Multi.prototype.monitor = function monitor () {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
function quitCallback (client) {
|
function quitCallback(client) {
|
||||||
return function (err, res) {
|
return function (err, res) {
|
||||||
if (client._stream.writable) {
|
if (client._stream.writable) {
|
||||||
// If the socket is still alive, destroy it. This could happen if quit got a NR_CLOSED error code
|
// If the socket is still alive, destroy it. This could happen if quit got
|
||||||
|
// a NR_CLOSED error code
|
||||||
client._stream.destroy()
|
client._stream.destroy()
|
||||||
}
|
}
|
||||||
if (err && err.code === 'NR_CLOSED') {
|
if (err && err.code === 'NR_CLOSED') {
|
||||||
@@ -85,10 +90,11 @@ function quitCallback (client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.quit = function quit () {
|
RedisClient.prototype.quit = function quit() {
|
||||||
// TODO: Consider this for v.3
|
// TODO: Consider this for v.3
|
||||||
// Allow the quit command to be fired as soon as possible to prevent it landing in the offline queue.
|
//
|
||||||
// this.ready = this.offlineQueue.length === 0;
|
// Allow the quit command to be fired as soon as possible to prevent it
|
||||||
|
// landing in the offline queue. this.ready = this.offlineQueue.length === 0;
|
||||||
const backpressureIndicator = this.internalSendCommand(new Command('quit', [], null, quitCallback(this)))
|
const backpressureIndicator = this.internalSendCommand(new Command('quit', [], null, quitCallback(this)))
|
||||||
// Calling quit should always end the connection, no matter if there's a connection or not
|
// Calling quit should always end the connection, no matter if there's a connection or not
|
||||||
this._closing = true
|
this._closing = true
|
||||||
@@ -97,7 +103,7 @@ RedisClient.prototype.quit = function quit () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only works with batch, not in a transaction
|
// Only works with batch, not in a transaction
|
||||||
Multi.prototype.quit = function quit () {
|
Multi.prototype.quit = function quit() {
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
// If called in a multi context, we expect redis is available
|
// If called in a multi context, we expect redis is available
|
||||||
this._client._closing = true
|
this._client._closing = true
|
||||||
@@ -113,7 +119,7 @@ Multi.prototype.quit = function quit () {
|
|||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
* @returns {function}
|
* @returns {function}
|
||||||
*/
|
*/
|
||||||
function infoCallback (client) {
|
function infoCallback(client) {
|
||||||
return function (err, res) {
|
return function (err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return err
|
return err
|
||||||
@@ -125,7 +131,7 @@ function infoCallback (client) {
|
|||||||
|
|
||||||
const obj = {}
|
const obj = {}
|
||||||
const lines = res.split('\r\n')
|
const lines = res.split('\r\n')
|
||||||
var topic = ''
|
let topic = ''
|
||||||
|
|
||||||
while (lines.length) {
|
while (lines.length) {
|
||||||
const parts = lines.shift().split(':')
|
const parts = lines.shift().split(':')
|
||||||
@@ -170,18 +176,18 @@ function infoCallback (client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store info in this.serverInfo after each call
|
// Store info in this.serverInfo after each call
|
||||||
RedisClient.prototype.info = function info (section) {
|
RedisClient.prototype.info = function info(section) {
|
||||||
const args = section ? [section] : []
|
const args = section ? [section] : []
|
||||||
return this.internalSendCommand(new Command('info', args, null, infoCallback(this)))
|
return this.internalSendCommand(new Command('info', args, null, infoCallback(this)))
|
||||||
}
|
}
|
||||||
|
|
||||||
Multi.prototype.info = function info (section) {
|
Multi.prototype.info = function info(section) {
|
||||||
const args = section ? [section] : []
|
const args = section ? [section] : []
|
||||||
this._queue.push(new Command('info', args, null, infoCallback(this._client)))
|
this._queue.push(new Command('info', args, null, infoCallback(this._client)))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
function authCallback (client, pass) {
|
function authCallback(client, pass) {
|
||||||
return function (err, res) {
|
return function (err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (noPasswordIsSet.test(err.message)) {
|
if (noPasswordIsSet.test(err.message)) {
|
||||||
@@ -194,7 +200,7 @@ function authCallback (client, pass) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.auth = function auth (pass) {
|
RedisClient.prototype.auth = function auth(pass) {
|
||||||
debug('Sending auth to %s id %s', this.address, this.connectionId)
|
debug('Sending auth to %s id %s', this.address, this.connectionId)
|
||||||
|
|
||||||
// Stash auth for connect and reconnect.
|
// Stash auth for connect and reconnect.
|
||||||
@@ -207,7 +213,7 @@ RedisClient.prototype.auth = function auth (pass) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only works with batch, not in a transaction
|
// Only works with batch, not in a transaction
|
||||||
Multi.prototype.auth = function auth (pass) {
|
Multi.prototype.auth = function auth(pass) {
|
||||||
debug('Sending auth to %s id %s', this.address, this.connectionId)
|
debug('Sending auth to %s id %s', this.address, this.connectionId)
|
||||||
|
|
||||||
// Stash auth for connect and reconnect.
|
// Stash auth for connect and reconnect.
|
||||||
@@ -216,12 +222,7 @@ Multi.prototype.auth = function auth (pass) {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.client = function client () {
|
RedisClient.prototype.client = function client(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
var callOnWrite
|
var callOnWrite
|
||||||
// CLIENT REPLY ON|OFF|SKIP
|
// CLIENT REPLY ON|OFF|SKIP
|
||||||
if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
|
if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
|
||||||
@@ -235,12 +236,7 @@ RedisClient.prototype.client = function client () {
|
|||||||
return this.internalSendCommand(new Command('client', arr, callOnWrite))
|
return this.internalSendCommand(new Command('client', arr, callOnWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
Multi.prototype.client = function client () {
|
Multi.prototype.client = function client(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
var callOnWrite
|
var callOnWrite
|
||||||
// CLIENT REPLY ON|OFF|SKIP
|
// CLIENT REPLY ON|OFF|SKIP
|
||||||
if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
|
if (arr.length === 2 && arr[0].toString().toUpperCase() === 'REPLY') {
|
||||||
@@ -255,24 +251,14 @@ Multi.prototype.client = function client () {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.subscribe = function subscribe () {
|
RedisClient.prototype.subscribe = function subscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
return this.internalSendCommand(new Command('subscribe', arr, callOnWrite))
|
return this.internalSendCommand(new Command('subscribe', arr, callOnWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
Multi.prototype.subscribe = function subscribe () {
|
Multi.prototype.subscribe = function subscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
@@ -280,51 +266,33 @@ Multi.prototype.subscribe = function subscribe () {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.unsubscribe = function unsubscribe () {
|
RedisClient.prototype.unsubscribe = function unsubscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
// Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
|
// Pub sub has to be activated even if not in pub sub mode, as the return
|
||||||
|
// value is manipulated in the callback
|
||||||
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
return this.internalSendCommand(new Command('unsubscribe', arr, callOnWrite))
|
return this.internalSendCommand(new Command('unsubscribe', arr, callOnWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
Multi.prototype.unsubscribe = function unsubscribe () {
|
Multi.prototype.unsubscribe = function unsubscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
// Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
|
// Pub sub has to be activated even if not in pub sub mode, as the return
|
||||||
|
// value is manipulated in the callback
|
||||||
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
this._queue.push(new Command('unsubscribe', arr, callOnWrite))
|
this._queue.push(new Command('unsubscribe', arr, callOnWrite))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.psubscribe = function psubscribe () {
|
RedisClient.prototype.psubscribe = function psubscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
return this.internalSendCommand(new Command('psubscribe', arr, callOnWrite))
|
return this.internalSendCommand(new Command('psubscribe', arr, callOnWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
Multi.prototype.psubscribe = function psubscribe () {
|
Multi.prototype.psubscribe = function psubscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
@@ -332,27 +300,19 @@ Multi.prototype.psubscribe = function psubscribe () {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisClient.prototype.punsubscribe = function punsubscribe () {
|
RedisClient.prototype.punsubscribe = function punsubscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
// Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
|
// Pub sub has to be activated even if not in pub sub mode, as the return
|
||||||
|
// value is manipulated in the callback
|
||||||
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
this._pubSubMode = this._pubSubMode || this.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
return this.internalSendCommand(new Command('punsubscribe', arr, callOnWrite))
|
return this.internalSendCommand(new Command('punsubscribe', arr, callOnWrite))
|
||||||
}
|
}
|
||||||
|
|
||||||
Multi.prototype.punsubscribe = function punsubscribe () {
|
Multi.prototype.punsubscribe = function punsubscribe(...arr) {
|
||||||
const len = arguments.length
|
|
||||||
const arr = new Array(len)
|
|
||||||
for (var i = 0; i < len; i += 1) {
|
|
||||||
arr[i] = arguments[i]
|
|
||||||
}
|
|
||||||
const callOnWrite = () => {
|
const callOnWrite = () => {
|
||||||
// Pub sub has to be activated even if not in pub sub mode, as the return value is manipulated in the callback
|
// Pub sub has to be activated even if not in pub sub mode, as the return
|
||||||
|
// value is manipulated in the callback
|
||||||
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
this._client._pubSubMode = this._client._pubSubMode || this._client.commandQueue.length + 1
|
||||||
}
|
}
|
||||||
this._queue.push(new Command('punsubscribe', arr, callOnWrite))
|
this._queue.push(new Command('punsubscribe', arr, callOnWrite))
|
||||||
|
45
lib/multi.js
45
lib/multi.js
@@ -4,6 +4,7 @@ const Queue = require('denque')
|
|||||||
const Errors = require('redis-errors')
|
const Errors = require('redis-errors')
|
||||||
const Command = require('./command')
|
const Command = require('./command')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
|
|
||||||
const handleReply = utils.handleReply
|
const handleReply = utils.handleReply
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,7 +16,7 @@ const handleReply = utils.handleReply
|
|||||||
* @param {number} index Command index in the Multi queue
|
* @param {number} index Command index in the Multi queue
|
||||||
* @returns *
|
* @returns *
|
||||||
*/
|
*/
|
||||||
function pipelineTransactionCommand (multi, command, index) {
|
function pipelineTransactionCommand(multi, command, index) {
|
||||||
// Queueing is done first, then the commands are executed
|
// Queueing is done first, then the commands are executed
|
||||||
const tmp = command.callback
|
const tmp = command.callback
|
||||||
command.callback = function (err, reply) {
|
command.callback = function (err, reply) {
|
||||||
@@ -37,7 +38,7 @@ function pipelineTransactionCommand (multi, command, index) {
|
|||||||
* @param {any[]} replies
|
* @param {any[]} replies
|
||||||
* @returns any[]
|
* @returns any[]
|
||||||
*/
|
*/
|
||||||
function multiCallback (multi, replies) {
|
function multiCallback(multi, replies) {
|
||||||
if (replies) {
|
if (replies) {
|
||||||
var i = 0
|
var i = 0
|
||||||
const queue = multi._queue
|
const queue = multi._queue
|
||||||
@@ -70,13 +71,11 @@ function multiCallback (multi, replies) {
|
|||||||
* @param {Multi} multi
|
* @param {Multi} multi
|
||||||
* @returns Promise<any[]>
|
* @returns Promise<any[]>
|
||||||
*/
|
*/
|
||||||
function execTransaction (multi) {
|
function execTransaction(multi) {
|
||||||
const client = multi._client
|
const client = multi._client
|
||||||
const queue = multi._queue
|
const queue = multi._queue
|
||||||
if (multi._monitoring || client._monitoring) {
|
if (multi._monitoring || client._monitoring) {
|
||||||
const err = new RangeError(
|
const err = new RangeError('Using transaction with a client that is in monitor mode does not work due to faulty return values of Redis.')
|
||||||
'Using transaction with a client that is in monitor mode does not work due to faulty return values of Redis.'
|
|
||||||
)
|
|
||||||
err.command = 'EXEC'
|
err.command = 'EXEC'
|
||||||
err.code = 'EXECABORT'
|
err.code = 'EXECABORT'
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -89,16 +88,19 @@ function execTransaction (multi) {
|
|||||||
// Silently ignore this error. We'll receive the error for the exec as well
|
// Silently ignore this error. We'll receive the error for the exec as well
|
||||||
const promises = [client.internalSendCommand(new Command('multi', [])).catch(() => {})]
|
const promises = [client.internalSendCommand(new Command('multi', [])).catch(() => {})]
|
||||||
// Drain queue, callback will catch 'QUEUED' or error
|
// Drain queue, callback will catch 'QUEUED' or error
|
||||||
for (var index = 0; index < len; index++) {
|
for (let index = 0; index < len; index++) {
|
||||||
// The commands may not be shifted off, since they are needed in the result handler
|
// The commands may not be shifted off, since they are needed in the result handler
|
||||||
promises.push(pipelineTransactionCommand(multi, queue.peekAt(index), index).catch((e) => e))
|
promises.push(pipelineTransactionCommand(multi, queue.peekAt(index), index).catch(e => e))
|
||||||
}
|
}
|
||||||
|
|
||||||
const main = client.internalSendCommand(new Command('exec', []))
|
const main = client.internalSendCommand(new Command('exec', []))
|
||||||
return Promise.all(promises).then(() => main.then((replies) => multiCallback(multi, replies)).catch((err) => {
|
return Promise.all(promises)
|
||||||
err.errors = multi._errors
|
.then(() => main
|
||||||
return Promise.reject(err)
|
.then(replies => multiCallback(multi, replies))
|
||||||
}))
|
.catch((err) => {
|
||||||
|
err.errors = multi._errors
|
||||||
|
return Promise.reject(err)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +109,7 @@ function execTransaction (multi) {
|
|||||||
* @param {Multi} multi
|
* @param {Multi} multi
|
||||||
* @returns Promise<any[]>
|
* @returns Promise<any[]>
|
||||||
*/
|
*/
|
||||||
function execBatch (multi) {
|
function execBatch(multi) {
|
||||||
const client = multi._client
|
const client = multi._client
|
||||||
const queue = multi._queue
|
const queue = multi._queue
|
||||||
if (queue.length === 0) {
|
if (queue.length === 0) {
|
||||||
@@ -119,13 +121,14 @@ function execBatch (multi) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
var error = false
|
var error = false
|
||||||
|
function setError(err) {
|
||||||
|
error = true
|
||||||
|
return err
|
||||||
|
}
|
||||||
const promises = []
|
const promises = []
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const command = queue.shift()
|
const command = queue.shift()
|
||||||
promises.push(client.internalSendCommand(command).catch((e) => {
|
promises.push(client.internalSendCommand(command).catch(setError))
|
||||||
error = true
|
|
||||||
return e
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
return Promise.all(promises).then((res) => {
|
return Promise.all(promises).then((res) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -147,14 +150,14 @@ class Multi {
|
|||||||
*
|
*
|
||||||
* @memberof Multi
|
* @memberof Multi
|
||||||
*/
|
*/
|
||||||
constructor (client, type, args) {
|
constructor(client, type, args) {
|
||||||
this._client = client
|
this._client = client
|
||||||
this._type = type
|
this._type = type
|
||||||
this._queue = new Queue()
|
this._queue = new Queue()
|
||||||
// Either undefined or an array. Fail hard if it's not an array
|
// Either undefined or an array. Fail hard if it's not an array
|
||||||
if (args) {
|
if (args) {
|
||||||
// Legacy support for passing in an array of arguments
|
// Legacy support for passing in an array of arguments
|
||||||
for (var i = 0; i < args.length; i++) {
|
for (let i = 0; i < args.length; i++) {
|
||||||
const command = args[i][0]
|
const command = args[i][0]
|
||||||
const tmpArgs = args[i].slice(1)
|
const tmpArgs = args[i].slice(1)
|
||||||
if (Array.isArray(command)) {
|
if (Array.isArray(command)) {
|
||||||
@@ -173,7 +176,7 @@ class Multi {
|
|||||||
*
|
*
|
||||||
* @memberof Multi
|
* @memberof Multi
|
||||||
*/
|
*/
|
||||||
execAtomic () {
|
execAtomic() {
|
||||||
if (this._queue.length < 2) {
|
if (this._queue.length < 2) {
|
||||||
return this.execBatch()
|
return this.execBatch()
|
||||||
}
|
}
|
||||||
@@ -187,7 +190,7 @@ class Multi {
|
|||||||
*
|
*
|
||||||
* @memberof Multi
|
* @memberof Multi
|
||||||
*/
|
*/
|
||||||
exec () {
|
exec() {
|
||||||
if (this._type === 'batch') {
|
if (this._type === 'batch') {
|
||||||
return execBatch(this)
|
return execBatch(this)
|
||||||
}
|
}
|
||||||
|
@@ -4,14 +4,14 @@ const Errors = require('redis-errors')
|
|||||||
const debug = require('./debug')
|
const debug = require('./debug')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
|
|
||||||
function offlineCommand (client, command) {
|
function offlineCommand(client, command) {
|
||||||
const commandName = command.command.toUpperCase()
|
const commandName = command.command.toUpperCase()
|
||||||
if (client._closing || client._options.enableOfflineQueue === false) {
|
if (client._closing || client._options.enableOfflineQueue === false) {
|
||||||
const msg = client._closing === true
|
const msg = client._closing === true
|
||||||
? 'The connection is already closed.'
|
? 'The connection is already closed.'
|
||||||
: client._stream.writable === true
|
: client._stream.writable === true
|
||||||
? 'The connection is not yet established and the offline queue is deactivated.'
|
? 'The connection is not yet established and the offline queue is deactivated.'
|
||||||
: 'Stream not writeable.'
|
: 'Stream not writeable.'
|
||||||
const err = new Errors.AbortError(`${commandName} can't be processed. ${msg}`)
|
const err = new Errors.AbortError(`${commandName} can't be processed. ${msg}`)
|
||||||
err.code = 'NR_CLOSED'
|
err.code = 'NR_CLOSED'
|
||||||
err.command = commandName
|
err.command = commandName
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('./debug')
|
const debug = require('./debug')
|
||||||
|
|
||||||
const SUBSCRIBE_COMMANDS = {
|
const SUBSCRIBE_COMMANDS = {
|
||||||
subscribe: true,
|
subscribe: true,
|
||||||
unsubscribe: true,
|
unsubscribe: true,
|
||||||
@@ -8,17 +9,22 @@ const SUBSCRIBE_COMMANDS = {
|
|||||||
punsubscribe: true
|
punsubscribe: true
|
||||||
}
|
}
|
||||||
|
|
||||||
function subscribeUnsubscribe (client, reply, type) {
|
function subscribeUnsubscribe(client, reply, type) {
|
||||||
// Subscribe commands take an optional callback and also emit an event, but only the Last_ response is included in the callback
|
// Subscribe commands take an optional callback and also emit an event, but
|
||||||
// The pub sub commands return each argument in a separate return value and have to be handled that way
|
// only the Last_ response is included in the callback The pub sub commands
|
||||||
|
// return each argument in a separate return value and have to be handled that
|
||||||
|
// way
|
||||||
const commandObj = client.commandQueue.peekAt(0)
|
const commandObj = client.commandQueue.peekAt(0)
|
||||||
const buffer = client._options.returnBuffers || client._options.detectBuffers && commandObj.bufferArgs
|
const buffer = client._options.returnBuffers ||
|
||||||
|
client._options.detectBuffers && commandObj.bufferArgs
|
||||||
const channel = (buffer || reply[1] === null) ? reply[1] : reply[1].toString()
|
const channel = (buffer || reply[1] === null) ? reply[1] : reply[1].toString()
|
||||||
const count = +reply[2] // Return the channel counter as number no matter if `stringNumbers` is activated or not
|
// Return the channel counter as number no matter if `stringNumbers` is activated or not
|
||||||
|
const count = +reply[2]
|
||||||
debug(type, channel)
|
debug(type, channel)
|
||||||
|
|
||||||
// Emit first, then return the callback
|
// Emit first, then return the callback
|
||||||
if (channel !== null) { // Do not emit or "unsubscribe" something if there was no channel to unsubscribe from
|
// Do not emit or "unsubscribe" something if there was no channel to unsubscribe from
|
||||||
|
if (channel !== null) {
|
||||||
if (type === 'subscribe' || type === 'psubscribe') {
|
if (type === 'subscribe' || type === 'psubscribe') {
|
||||||
client._subscriptionSet[`${type}_${channel}`] = channel
|
client._subscriptionSet[`${type}_${channel}`] = channel
|
||||||
} else {
|
} else {
|
||||||
@@ -29,10 +35,13 @@ function subscribeUnsubscribe (client, reply, type) {
|
|||||||
client._subscribeChannels.push(channel)
|
client._subscribeChannels.push(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandObj.argsLength === 1 || client._subCommandsLeft === 1 || commandObj.argsLength === 0 && (count === 0 || channel === null)) {
|
if (commandObj.argsLength === 1 ||
|
||||||
|
client._subCommandsLeft === 1 ||
|
||||||
|
commandObj.argsLength === 0 && (count === 0 || channel === null)) {
|
||||||
if (count === 0) { // Unsubscribed from all channels
|
if (count === 0) { // Unsubscribed from all channels
|
||||||
client._pubSubMode = 0 // Deactivating pub sub mode
|
client._pubSubMode = 0 // Deactivating pub sub mode
|
||||||
// This should be a rare case and therefore handling it this way should be good performance wise for the general case
|
// This should be a rare case and therefore handling it this way should be
|
||||||
|
// good performance wise for the general case
|
||||||
for (var i = 1; i < client.commandQueue.length; i++) {
|
for (var i = 1; i < client.commandQueue.length; i++) {
|
||||||
const runningCommand = client.commandQueue.peekAt(i)
|
const runningCommand = client.commandQueue.peekAt(i)
|
||||||
if (SUBSCRIBE_COMMANDS[runningCommand.command]) {
|
if (SUBSCRIBE_COMMANDS[runningCommand.command]) {
|
||||||
@@ -45,16 +54,14 @@ function subscribeUnsubscribe (client, reply, type) {
|
|||||||
commandObj.callback(null, [count, client._subscribeChannels])
|
commandObj.callback(null, [count, client._subscribeChannels])
|
||||||
client._subscribeChannels = []
|
client._subscribeChannels = []
|
||||||
client._subCommandsLeft = 0
|
client._subCommandsLeft = 0
|
||||||
|
} else if (client._subCommandsLeft !== 0) {
|
||||||
|
client._subCommandsLeft--
|
||||||
} else {
|
} else {
|
||||||
if (client._subCommandsLeft !== 0) {
|
client._subCommandsLeft = commandObj.argsLength ? commandObj.argsLength - 1 : count
|
||||||
client._subCommandsLeft--
|
|
||||||
} else {
|
|
||||||
client._subCommandsLeft = commandObj.argsLength ? commandObj.argsLength - 1 : count
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnPubSub (client, reply) {
|
function returnPubSub(client, reply) {
|
||||||
const type = reply[0].toString()
|
const type = reply[0].toString()
|
||||||
if (type === 'message') { // Channel, message
|
if (type === 'message') { // Channel, message
|
||||||
if (typeof reply[1] !== 'string') {
|
if (typeof reply[1] !== 'string') {
|
||||||
|
@@ -4,7 +4,7 @@ const Command = require('./command')
|
|||||||
const debug = require('./debug')
|
const debug = require('./debug')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
|
|
||||||
function onConnect (client) {
|
function onConnect(client) {
|
||||||
debug('Stream connected %s id %s', client.address, client.connectionId)
|
debug('Stream connected %s id %s', client.address, client.connectionId)
|
||||||
|
|
||||||
// TODO: Check if the clients prototype and the clients instance have
|
// TODO: Check if the clients prototype and the clients instance have
|
||||||
@@ -30,7 +30,7 @@ function onConnect (client) {
|
|||||||
*
|
*
|
||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
*/
|
*/
|
||||||
function sendOfflineQueue (client) {
|
function sendOfflineQueue(client) {
|
||||||
const queue = client.offlineQueue
|
const queue = client.offlineQueue
|
||||||
while (queue.length) {
|
while (queue.length) {
|
||||||
const command = queue.shift()
|
const command = queue.shift()
|
||||||
@@ -47,7 +47,7 @@ function sendOfflineQueue (client) {
|
|||||||
*
|
*
|
||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
*/
|
*/
|
||||||
function readyHandler (client) {
|
function readyHandler(client) {
|
||||||
debug('readyHandler called %s id %s', client.address, client.connectionId)
|
debug('readyHandler called %s id %s', client.address, client.connectionId)
|
||||||
client.ready = true
|
client.ready = true
|
||||||
|
|
||||||
@@ -79,16 +79,16 @@ function readyHandler (client) {
|
|||||||
// }
|
// }
|
||||||
if (!client._options.disableResubscribing && callbackCount) {
|
if (!client._options.disableResubscribing && callbackCount) {
|
||||||
debug('Sending pub/sub commands')
|
debug('Sending pub/sub commands')
|
||||||
for (const key in client._subscriptionSet) {
|
const keys = Object.keys(client._subscriptionSet)
|
||||||
if (client._subscriptionSet.hasOwnProperty(key)) {
|
for (var i = 0; i < keys.length; i++) {
|
||||||
const command = key.slice(0, key.indexOf('_'))
|
const key = keys[i]
|
||||||
const args = client._subscriptionSet[key]
|
const command = key.slice(0, key.indexOf('_'))
|
||||||
client[command]([args]).catch((err) => {
|
const args = client._subscriptionSet[key]
|
||||||
if (!client._closing) {
|
client[command]([args]).catch((err) => {
|
||||||
process.nextTick(client.emit, 'error', err)
|
if (!client._closing) {
|
||||||
}
|
process.nextTick(client.emit, 'error', err)
|
||||||
})
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendOfflineQueue(client)
|
sendOfflineQueue(client)
|
||||||
@@ -100,7 +100,7 @@ function readyHandler (client) {
|
|||||||
*
|
*
|
||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
*/
|
*/
|
||||||
function readyCheck (client) {
|
function readyCheck(client) {
|
||||||
debug('Checking server ready state...')
|
debug('Checking server ready state...')
|
||||||
// Always fire client info command as first command even if other commands are already queued up
|
// Always fire client info command as first command even if other commands are already queued up
|
||||||
client.ready = true
|
client.ready = true
|
||||||
@@ -112,7 +112,9 @@ function readyCheck (client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const persistence = client.serverInfo.persistence
|
const persistence = client.serverInfo.persistence
|
||||||
if (persistence === undefined || persistence.loading === undefined || persistence.loading === 0) {
|
if (persistence === undefined ||
|
||||||
|
persistence.loading === undefined ||
|
||||||
|
persistence.loading === 0) {
|
||||||
// If the master_link_status exists but the link is not up, try again after 50 ms
|
// If the master_link_status exists but the link is not up, try again after 50 ms
|
||||||
const replication = client.serverInfo.replication
|
const replication = client.serverInfo.replication
|
||||||
if (replication && typeof replication.master_link_status === 'string' && replication.master_link_status !== 'up') {
|
if (replication && typeof replication.master_link_status === 'string' && replication.master_link_status !== 'up') {
|
||||||
@@ -125,12 +127,12 @@ function readyCheck (client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var retryTime = +persistence.loading_eta_seconds * 1000
|
let retryTime = +persistence.loading_eta_seconds * 1000
|
||||||
if (retryTime > 1000) {
|
if (retryTime > 1000) {
|
||||||
retryTime = 1000
|
retryTime = 1000
|
||||||
}
|
}
|
||||||
debug('Redis server still loading, trying again in %s', retryTime)
|
debug('Redis server still loading, trying again in %s', retryTime)
|
||||||
setTimeout((client) => readyCheck(client), retryTime, client)
|
setTimeout(client => readyCheck(client), retryTime, client)
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
if (client._closing) {
|
if (client._closing) {
|
||||||
return
|
return
|
||||||
@@ -142,7 +144,6 @@ function readyCheck (client) {
|
|||||||
}
|
}
|
||||||
err.message = `Ready check failed: ${err.message}`
|
err.message = `Ready check failed: ${err.message}`
|
||||||
client.emit('error', err)
|
client.emit('error', err)
|
||||||
return
|
|
||||||
})
|
})
|
||||||
client.ready = false
|
client.ready = false
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ const flushAndError = require('./flushAndError')
|
|||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
* @param {Error} [error]
|
* @param {Error} [error]
|
||||||
*/
|
*/
|
||||||
function retryConnection (client, error) {
|
function retryConnection(client, error) {
|
||||||
debug('Retrying connection...')
|
debug('Retrying connection...')
|
||||||
|
|
||||||
const reconnectParams = {
|
const reconnectParams = {
|
||||||
@@ -36,7 +36,7 @@ function retryConnection (client, error) {
|
|||||||
* @param {string} why
|
* @param {string} why
|
||||||
* @param {Error} [error]
|
* @param {Error} [error]
|
||||||
*/
|
*/
|
||||||
function reconnect (client, why, error) {
|
function reconnect(client, why, error) {
|
||||||
// If a retry is already in progress, just let that happen
|
// If a retry is already in progress, just let that happen
|
||||||
if (client.retryTimer) {
|
if (client.retryTimer) {
|
||||||
return
|
return
|
||||||
@@ -112,7 +112,12 @@ function reconnect (client, why, error) {
|
|||||||
|
|
||||||
debug('Retry connection in %s ms', client.retryDelay)
|
debug('Retry connection in %s ms', client.retryDelay)
|
||||||
|
|
||||||
client.retryTimer = setTimeout((client, error) => retryConnection(client, error), client.retryDelay, client, error)
|
client.retryTimer = setTimeout(
|
||||||
|
(client, error) => retryConnection(client, error),
|
||||||
|
client.retryDelay,
|
||||||
|
client,
|
||||||
|
error
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = reconnect
|
module.exports = reconnect
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const pubsub = require('./pubsub')
|
const pubsub = require('./pubsub')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils')
|
||||||
|
|
||||||
function onError (client, err) {
|
function onError(client, err) {
|
||||||
const commandObj = client.commandQueue.shift()
|
const commandObj = client.commandQueue.shift()
|
||||||
if (commandObj.error) {
|
if (commandObj.error) {
|
||||||
err.stack = commandObj.error.stack.replace(/^Error.*?\n/, `ReplyError: ${err.message}\n`)
|
err.stack = commandObj.error.stack.replace(/^Error.*?\n/, `ReplyError: ${err.message}\n`)
|
||||||
@@ -28,7 +28,7 @@ function onError (client, err) {
|
|||||||
commandObj.callback(err)
|
commandObj.callback(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalReply (client, reply) {
|
function normalReply(client, reply) {
|
||||||
const command = client.commandQueue.shift()
|
const command = client.commandQueue.shift()
|
||||||
if (client._multi === false) {
|
if (client._multi === false) {
|
||||||
reply = utils.handleReply(client, reply, command)
|
reply = utils.handleReply(client, reply, command)
|
||||||
@@ -36,10 +36,11 @@ function normalReply (client, reply) {
|
|||||||
command.callback(null, reply)
|
command.callback(null, reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onResult (client, reply) {
|
function onResult(client, reply) {
|
||||||
// If in monitor mode, all normal commands are still working and we only want to emit the streamlined commands
|
// If in monitor mode, all normal commands are still working and we only want
|
||||||
// As this is not the average use case and monitor is expensive anyway, let's change the code here, to improve
|
// to emit the streamlined commands As this is not the average use case and
|
||||||
// the average performance of all other commands in case of no monitor mode
|
// monitor is expensive anyway, let's change the code here, to improve the
|
||||||
|
// average performance of all other commands in case of no monitor mode
|
||||||
if (client._monitoring === true) {
|
if (client._monitoring === true) {
|
||||||
var replyStr
|
var replyStr
|
||||||
// TODO: This could be further improved performance wise
|
// TODO: This could be further improved performance wise
|
||||||
|
@@ -5,9 +5,9 @@ const URL = require('url')
|
|||||||
|
|
||||||
// TODO: Improve the unify performance by checking for the arguments length
|
// TODO: Improve the unify performance by checking for the arguments length
|
||||||
// before trying to access that argument.
|
// before trying to access that argument.
|
||||||
function unifyOptions (portArg, hostArg, options) {
|
function unifyOptions(portArg, hostArg, options) {
|
||||||
if (typeof portArg === 'number' || (typeof portArg === 'string' && /^\d+$/.test(portArg))) {
|
if (typeof portArg === 'number' || (typeof portArg === 'string' && /^\d+$/.test(portArg))) {
|
||||||
var host
|
let host
|
||||||
if (typeof hostArg === 'string') {
|
if (typeof hostArg === 'string') {
|
||||||
host = hostArg
|
host = hostArg
|
||||||
} else {
|
} else {
|
||||||
@@ -24,6 +24,7 @@ function unifyOptions (portArg, hostArg, options) {
|
|||||||
|
|
||||||
const parsed = URL.parse(portArg.url || portArg, true, true)
|
const parsed = URL.parse(portArg.url || portArg, true, true)
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
// [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
|
// [redis:]//[[user][:password]@][host][:port][/db-number][?db=db-number[&password=bar[&option=value]]]
|
||||||
if (parsed.slashes) { // We require slashes
|
if (parsed.slashes) { // We require slashes
|
||||||
if (parsed.auth) {
|
if (parsed.auth) {
|
||||||
@@ -42,11 +43,9 @@ function unifyOptions (portArg, hostArg, options) {
|
|||||||
options.port = parsed.port
|
options.port = parsed.port
|
||||||
}
|
}
|
||||||
if (parsed.search !== '') {
|
if (parsed.search !== '') {
|
||||||
for (var elem in parsed.query) {
|
const keys = Object.keys(parsed.query)
|
||||||
/* istanbul ignore if */
|
for (var i = 0; i < keys.length; i++) {
|
||||||
if (!Object.prototype.hasOwnProperty.call(parsed.query, elem)) {
|
const elem = keys[i]
|
||||||
continue
|
|
||||||
}
|
|
||||||
// If options are passed twice, only the parsed options will be used
|
// If options are passed twice, only the parsed options will be used
|
||||||
if (elem in options) {
|
if (elem in options) {
|
||||||
if (options[elem] === parsed.query[elem]) {
|
if (options[elem] === parsed.query[elem]) {
|
||||||
|
27
lib/utils.js
27
lib/utils.js
@@ -6,12 +6,12 @@
|
|||||||
* @param {any[]} reply
|
* @param {any[]} reply
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
function replyToObject (reply) {
|
function replyToObject(reply) {
|
||||||
if (reply.length === 0) {
|
if (reply.length === 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const obj = {}
|
const obj = {}
|
||||||
for (let i = 0; i < reply.length; i += 2) {
|
for (var i = 0; i < reply.length; i += 2) {
|
||||||
obj[reply[i].toString('binary')] = reply[i + 1]
|
obj[reply[i].toString('binary')] = reply[i + 1]
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
@@ -23,7 +23,7 @@ function replyToObject (reply) {
|
|||||||
* @param {any[]} reply
|
* @param {any[]} reply
|
||||||
* @returns any[]|string
|
* @returns any[]|string
|
||||||
*/
|
*/
|
||||||
function replyToStrings (reply) {
|
function replyToStrings(reply) {
|
||||||
if (reply === null) {
|
if (reply === null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ function replyToStrings (reply) {
|
|||||||
}
|
}
|
||||||
if (typeof reply.map === 'function') { // instanceof Array
|
if (typeof reply.map === 'function') { // instanceof Array
|
||||||
const res = new Array(reply.length)
|
const res = new Array(reply.length)
|
||||||
for (let i = 0; i < reply.length; i++) {
|
for (var i = 0; i < reply.length; i++) {
|
||||||
// Recursively call the function as slowlog returns deep nested replies
|
// Recursively call the function as slowlog returns deep nested replies
|
||||||
res[i] = replyToStrings(reply[i])
|
res[i] = replyToStrings(reply[i])
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ function replyToStrings (reply) {
|
|||||||
* @param {any} obj
|
* @param {any} obj
|
||||||
* @returns any
|
* @returns any
|
||||||
*/
|
*/
|
||||||
function clone (obj) {
|
function clone(obj) {
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
const copy = new Array(obj.length)
|
const copy = new Array(obj.length)
|
||||||
for (var i = 0; i < obj.length; i++) {
|
for (var i = 0; i < obj.length; i++) {
|
||||||
@@ -81,7 +81,7 @@ function clone (obj) {
|
|||||||
* @param {undefined|object} obj
|
* @param {undefined|object} obj
|
||||||
* @returns object
|
* @returns object
|
||||||
*/
|
*/
|
||||||
function convenienceClone (obj) {
|
function convenienceClone(obj) {
|
||||||
return clone(obj) || {}
|
return clone(obj) || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ function convenienceClone (obj) {
|
|||||||
* @param {any} res
|
* @param {any} res
|
||||||
* @param {Denque} queue
|
* @param {Denque} queue
|
||||||
*/
|
*/
|
||||||
function replyInOrder (client, callback, err, res, queue) {
|
function replyInOrder(client, callback, err, res, queue) {
|
||||||
const commandObj = queue
|
const commandObj = queue
|
||||||
? queue.peekBack()
|
? queue.peekBack()
|
||||||
: (client.offlineQueue.peekBack() || client.commandQueue.peekBack())
|
: (client.offlineQueue.peekBack() || client.commandQueue.peekBack())
|
||||||
@@ -121,7 +121,7 @@ function replyInOrder (client, callback, err, res, queue) {
|
|||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
* @param {string} msg
|
* @param {string} msg
|
||||||
*/
|
*/
|
||||||
function warn (client, msg) {
|
function warn(client, msg) {
|
||||||
if (client.listeners('warning').length !== 0) {
|
if (client.listeners('warning').length !== 0) {
|
||||||
client.emit('warning', msg)
|
client.emit('warning', msg)
|
||||||
} else {
|
} else {
|
||||||
@@ -140,8 +140,9 @@ function warn (client, msg) {
|
|||||||
* @param {Command} command
|
* @param {Command} command
|
||||||
* @returns {string|number|null|Buffer|any[]|object}
|
* @returns {string|number|null|Buffer|any[]|object}
|
||||||
*/
|
*/
|
||||||
function handleReply (client, reply, command) {
|
function handleReply(client, reply, command) {
|
||||||
if (client._options.detectBuffers === true && command.bufferArgs === false || client._messageBuffers === true) {
|
if (client._options.detectBuffers === true && command.bufferArgs === false ||
|
||||||
|
client._messageBuffers === true) {
|
||||||
reply = replyToStrings(reply)
|
reply = replyToStrings(reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,12 +158,12 @@ function handleReply (client, reply, command) {
|
|||||||
* @param {Error|null} err
|
* @param {Error|null} err
|
||||||
* @param {any} reply
|
* @param {any} reply
|
||||||
*/
|
*/
|
||||||
function print (err, reply) {
|
function print(err, reply) {
|
||||||
if (err) {
|
if (err) {
|
||||||
// A error always begins with Error:
|
// A error always begins with Error:
|
||||||
console.error(err.toString())
|
console.error(err.toString())
|
||||||
} else {
|
} else {
|
||||||
console.log('Reply: ' + reply)
|
console.log(`Reply: ${reply}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +172,7 @@ function print (err, reply) {
|
|||||||
*
|
*
|
||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
*/
|
*/
|
||||||
function setReconnectDefaults (client) {
|
function setReconnectDefaults(client) {
|
||||||
client.retryTimer = null
|
client.retryTimer = null
|
||||||
client.retryTotaltime = 0
|
client.retryTotaltime = 0
|
||||||
client.retryDelay = 100
|
client.retryDelay = 100
|
||||||
|
@@ -21,10 +21,11 @@ var errors = null
|
|||||||
/**
|
/**
|
||||||
* @description Pipeline and write all commands to the stream
|
* @description Pipeline and write all commands to the stream
|
||||||
*
|
*
|
||||||
* If the pipelined string exceeds X mb, write it directly to the stream and pipeline the rest again.
|
* If the pipelined string exceeds X mb, write it directly to the stream and
|
||||||
|
* pipeline the rest again.
|
||||||
* @param {RedisClient} client
|
* @param {RedisClient} client
|
||||||
*/
|
*/
|
||||||
function writeToStream (client) {
|
function writeToStream(client) {
|
||||||
const stream = client._stream
|
const stream = client._stream
|
||||||
const queue = client._pipelineQueue
|
const queue = client._pipelineQueue
|
||||||
const cache = client._strCache
|
const cache = client._strCache
|
||||||
@@ -41,7 +42,7 @@ function writeToStream (client) {
|
|||||||
client._pipeline = false
|
client._pipeline = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function write (client) {
|
function write(client) {
|
||||||
if (client._pipeline === false) {
|
if (client._pipeline === false) {
|
||||||
client._stream.cork()
|
client._stream.cork()
|
||||||
client._pipeline = true
|
client._pipeline = true
|
||||||
@@ -49,11 +50,11 @@ function write (client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function pipelineBuffers (client, commandStr) {
|
function pipelineBuffers(client, commandStr) {
|
||||||
const queue = client._pipelineQueue
|
const queue = client._pipelineQueue
|
||||||
client._strCache += commandStr
|
client._strCache += commandStr
|
||||||
while (copy.length) {
|
while (copy.length) {
|
||||||
var arg = copy.shift()
|
const arg = copy.shift()
|
||||||
if (typeof arg === 'string') {
|
if (typeof arg === 'string') {
|
||||||
client._strCache += `$${Buffer.byteLength(arg)}\r\n${arg}\r\n`
|
client._strCache += `$${Buffer.byteLength(arg)}\r\n${arg}\r\n`
|
||||||
} else {
|
} else {
|
||||||
@@ -69,20 +70,20 @@ function pipelineBuffers (client, commandStr) {
|
|||||||
client._strCache = ''
|
client._strCache = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function toString (arg) {
|
function toString(arg) {
|
||||||
if (typeof arg === 'string') {
|
if (typeof arg === 'string') {
|
||||||
copy.push(arg)
|
copy.push(arg)
|
||||||
} else if (typeof arg === 'number') {
|
} else if (typeof arg === 'number') {
|
||||||
copy.push('' + arg)
|
copy.push(`${arg}`)
|
||||||
} else if (arg instanceof Array) {
|
} else if (arg instanceof Array) {
|
||||||
for (var i = 0; i < arg.length; i += 1) {
|
for (let i = 0; i < arg.length; i += 1) {
|
||||||
toString(arg[i])
|
toString(arg[i])
|
||||||
}
|
}
|
||||||
} else if (arg && arg.constructor.name === 'Buffer') { // TODO: check performance
|
} else if (arg && arg.constructor.name === 'Buffer') { // TODO: check performance
|
||||||
copy.push(arg)
|
copy.push(arg)
|
||||||
bufferCount++
|
bufferCount++
|
||||||
} else if (typeof arg === 'boolean') { // TODO: Remove this support and use hooks instead
|
} else if (typeof arg === 'boolean') { // TODO: Remove this support and use hooks instead
|
||||||
copy.push('' + arg)
|
copy.push(`${arg}`)
|
||||||
} else if (arg && arg.constructor.name === 'Object') { // Check if this is actually a good check or not
|
} else if (arg && arg.constructor.name === 'Object') { // Check if this is actually a good check or not
|
||||||
// TODO: As soon as we add support for JSON
|
// TODO: As soon as we add support for JSON
|
||||||
// We could simple stringify this right here.
|
// We could simple stringify this right here.
|
||||||
@@ -99,7 +100,7 @@ function toString (arg) {
|
|||||||
toString(val)
|
toString(val)
|
||||||
})
|
})
|
||||||
} else if (arg instanceof Set) {
|
} else if (arg instanceof Set) {
|
||||||
arg.forEach((val) => toString(val))
|
arg.forEach(val => toString(val))
|
||||||
} else if (arg && arg.constructor.name === 'Date') { // Check if this is actually a good check or not
|
} else if (arg && arg.constructor.name === 'Date') { // Check if this is actually a good check or not
|
||||||
copy.push(arg.toString())
|
copy.push(arg.toString())
|
||||||
} else {
|
} else {
|
||||||
@@ -110,7 +111,7 @@ function toString (arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnErr (client, command) {
|
function returnErr(client, command) {
|
||||||
const err = new TypeError('NodeRedis can not handle the provided arguments (see "error.issues" property).\n\nFurther information https://github.com/asd')
|
const err = new TypeError('NodeRedis can not handle the provided arguments (see "error.issues" property).\n\nFurther information https://github.com/asd')
|
||||||
err.command = command.command.toUpperCase()
|
err.command = command.command.toUpperCase()
|
||||||
err.args = command.args
|
err.args = command.args
|
||||||
@@ -119,13 +120,14 @@ function returnErr (client, command) {
|
|||||||
utils.replyInOrder(client, command.callback, err, undefined, client.commandQueue)
|
utils.replyInOrder(client, command.callback, err, undefined, client.commandQueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always use 'Multi bulk commands', but if passed any Buffer args, then do multiple writes, one for each arg.
|
// Always use 'Multi bulk commands', but if passed any Buffer args, then do
|
||||||
// This means that using Buffers in commands is going to be slower, so use Strings if you don't already have a Buffer.
|
// multiple writes, one for each arg. This means that using Buffers in commands
|
||||||
|
// is going to be slower, so use Strings if you don't already have a Buffer.
|
||||||
|
|
||||||
// TODO: It is faster to move this part somewhere else
|
// TODO: It is faster to move this part somewhere else
|
||||||
// We could move this to the function creation as well
|
// We could move this to the function creation as well
|
||||||
// if we use hooks for our individual commands!
|
// if we use hooks for our individual commands!
|
||||||
function normalizeAndWrite (client, command) {
|
function normalizeAndWrite(client, command) {
|
||||||
const args = command.args
|
const args = command.args
|
||||||
const origName = command.command
|
const origName = command.command
|
||||||
const renameCommands = client._options.renameCommands
|
const renameCommands = client._options.renameCommands
|
||||||
@@ -134,7 +136,7 @@ function normalizeAndWrite (client, command) {
|
|||||||
: origName
|
: origName
|
||||||
|
|
||||||
bufferCount = 0
|
bufferCount = 0
|
||||||
for (var i = 0; i < args.length; i++) {
|
for (let i = 0; i < args.length; i++) {
|
||||||
toString(args[i])
|
toString(args[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +155,7 @@ function normalizeAndWrite (client, command) {
|
|||||||
|
|
||||||
const bufferArgs = bufferCount !== 0
|
const bufferArgs = bufferCount !== 0
|
||||||
const len = copy.length
|
const len = copy.length
|
||||||
var commandStr = `*${len + 1}\r\n$${name.length}\r\n${name}\r\n`
|
let commandStr = `*${len + 1}\r\n$${name.length}\r\n${name}\r\n`
|
||||||
|
|
||||||
command.bufferArgs = bufferArgs
|
command.bufferArgs = bufferArgs
|
||||||
command.argsLength = len
|
command.argsLength = len
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
"test": "nyc --cache mocha ./test/*.js ./test/commands/*.js --timeout=8000",
|
"test": "nyc --cache mocha ./test/*.js ./test/commands/*.js --timeout=8000",
|
||||||
"posttest": "npm run coverage",
|
"posttest": "npm run coverage",
|
||||||
"compare": "node benchmarks/diff_multi_bench_output.js beforeBench.txt afterBench.txt",
|
"compare": "node benchmarks/diff_multi_bench_output.js beforeBench.txt afterBench.txt",
|
||||||
"lint": "standard . --fix"
|
"lint": "eslint . --fix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"denque": "^1.2.2",
|
"denque": "^1.2.2",
|
||||||
@@ -37,11 +37,13 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"coveralls": "^2.13.3",
|
"coveralls": "^2.13.3",
|
||||||
"cross-spawn": "^5.1.0",
|
"cross-spawn": "^5.1.0",
|
||||||
|
"eslint": "^4.12.0",
|
||||||
|
"eslint-config-airbnb-base": "^12.1.0",
|
||||||
|
"eslint-plugin-import": "^2.8.0",
|
||||||
"intercept-stdout": "~0.1.2",
|
"intercept-stdout": "~0.1.2",
|
||||||
"metrics": "^0.1.14",
|
"metrics": "^0.1.14",
|
||||||
"mocha": "^3.5.3",
|
"mocha": "^3.5.3",
|
||||||
"nyc": "^8.3.0",
|
"nyc": "^8.3.0",
|
||||||
"standard": "^10.0.2",
|
|
||||||
"tcp-port-used": "^0.1.2",
|
"tcp-port-used": "^0.1.2",
|
||||||
"uuid": "^2.0.1"
|
"uuid": "^2.0.1"
|
||||||
},
|
},
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
// TODO: Fix redis process spawn on windows
|
// TODO: Fix redis process spawn on windows
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
@@ -215,7 +216,8 @@ if (process.platform !== 'win32') {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
client.once('ready', () => {
|
client.once('ready', () => {
|
||||||
// Coherent behavior with all other offline commands fires commands before emitting but does not wait till they return
|
// Coherent behavior with all other offline commands fires commands
|
||||||
|
// before emitting but does not wait till they return
|
||||||
assert.strictEqual(client._pubSubMode, 2)
|
assert.strictEqual(client._pubSubMode, 2)
|
||||||
client.ping().then(() => { // Make sure all commands were properly processed already
|
client.ping().then(() => { // Make sure all commands were properly processed already
|
||||||
client._stream.destroy()
|
client._stream.destroy()
|
||||||
@@ -224,11 +226,15 @@ if (process.platform !== 'win32') {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('individual commands work properly with batch', (done) => {
|
it('individual commands work properly with batch', (done) => {
|
||||||
// quit => might return an error instead of "OK" in the exec callback... (if not connected)
|
// quit => might return an error instead of "OK" in the exec callback...
|
||||||
// auth => might return an error instead of "OK" in the exec callback... (if no password is required / still loading on Redis <= 2.4)
|
// (if not connected)
|
||||||
// This could be fixed by checking the return value of the callback in the exec callback and
|
//
|
||||||
// returning the manipulated [error, result] from the callback.
|
// auth => might return an error instead of "OK" in the exec callback...
|
||||||
// There should be a better solution though
|
// (if no password is required / still loading on Redis <= 2.4)
|
||||||
|
//
|
||||||
|
// This could be fixed by checking the return value of the callback in
|
||||||
|
// the exec callback and returning the manipulated [error, result] from
|
||||||
|
// the callback. There should be a better solution though
|
||||||
|
|
||||||
const args = config.configureClient('localhost', {
|
const args = config.configureClient('localhost', {
|
||||||
noReadyCheck: true
|
noReadyCheck: true
|
||||||
@@ -240,25 +246,26 @@ if (process.platform !== 'win32') {
|
|||||||
end() // Should be called for each command after monitor
|
end() // Should be called for each command after monitor
|
||||||
})
|
})
|
||||||
client.batch()
|
client.batch()
|
||||||
.auth(auth)
|
.auth(auth)
|
||||||
.select(5)
|
.select(5)
|
||||||
.monitor()
|
.monitor()
|
||||||
.set('foo', 'bar')
|
.set('foo', 'bar')
|
||||||
.info('stats')
|
.info('stats')
|
||||||
.get('foo')
|
.get('foo')
|
||||||
.subscribe(['foo', 'bar', 'foo'])
|
.subscribe(['foo', 'bar', 'foo'])
|
||||||
.unsubscribe('foo')
|
.unsubscribe('foo')
|
||||||
.subscribe('/foo')
|
.subscribe('/foo')
|
||||||
.psubscribe('*')
|
.psubscribe('*')
|
||||||
.quit()
|
.quit()
|
||||||
.exec().then((res) => {
|
.exec()
|
||||||
res[4] = res[4].substr(0, 9)
|
.then((res) => {
|
||||||
assert.deepStrictEqual(
|
res[4] = res[4].substr(0, 9)
|
||||||
res,
|
assert.deepStrictEqual(
|
||||||
['OK', 'OK', 'OK', 'OK', '# Stats\r\n', 'bar', [2, ['foo', 'bar', 'foo']], [1, ['foo']], [2, ['/foo']], [3, ['*']], 'OK']
|
res,
|
||||||
)
|
['OK', 'OK', 'OK', 'OK', '# Stats\r\n', 'bar', [2, ['foo', 'bar', 'foo']], [1, ['foo']], [2, ['/foo']], [3, ['*']], 'OK']
|
||||||
end()
|
)
|
||||||
})
|
end()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'batch\' method', () => {
|
describe('The \'batch\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -101,7 +102,7 @@ describe('The \'batch\' method', () => {
|
|||||||
['incr', 'batchfoo'],
|
['incr', 'batchfoo'],
|
||||||
['incr', 'batchbar']
|
['incr', 'batchbar']
|
||||||
]).exec().then(helper.fail).catch((err) => {
|
]).exec().then(helper.fail).catch((err) => {
|
||||||
const replies = err.replies
|
const { replies } = err
|
||||||
assert.strictEqual(2, replies[0].length)
|
assert.strictEqual(2, replies[0].length)
|
||||||
assert.strictEqual(null, replies[0][0])
|
assert.strictEqual(null, replies[0][0])
|
||||||
assert.strictEqual(null, replies[0][1])
|
assert.strictEqual(null, replies[0][1])
|
||||||
@@ -150,8 +151,8 @@ describe('The \'batch\' method', () => {
|
|||||||
[['hmset', 'batchhmset2', 'batchbar2', 'batchfoo3', 'batchbar3', 'test']],
|
[['hmset', 'batchhmset2', 'batchbar2', 'batchfoo3', 'batchbar3', 'test']],
|
||||||
['hmset', ['batchhmset', 'batchbar', 'batchfoo']],
|
['hmset', ['batchhmset', 'batchbar', 'batchfoo']],
|
||||||
['hmset', arr3],
|
['hmset', arr3],
|
||||||
['hmset', now, {123456789: 'abcdefghij', 'some manner of key': 'a type of value', 'otherTypes': 555}],
|
['hmset', now, { 123456789: 'abcdefghij', 'some manner of key': 'a type of value', otherTypes: 555 }],
|
||||||
['hmset', 'key2', {'0123456789': 'abcdefghij', 'some manner of key': 'a type of value', 'otherTypes': 999}],
|
['hmset', 'key2', { '0123456789': 'abcdefghij', 'some manner of key': 'a type of value', otherTypes: 999 }],
|
||||||
['hmset', new Set(['batchhmset', ['batchbar', 'batchbaz']])],
|
['hmset', new Set(['batchhmset', ['batchbar', 'batchbaz']])],
|
||||||
['hmset', ['batchhmset'], new Map([['batchbar', 'batchbaz']])]
|
['hmset', ['batchhmset'], new Map([['batchbar', 'batchbaz']])]
|
||||||
])
|
])
|
||||||
@@ -159,7 +160,8 @@ describe('The \'batch\' method', () => {
|
|||||||
.hmget('key2', arr2)
|
.hmget('key2', arr2)
|
||||||
.hmget(['batchhmset2', ['some manner of key', 'batchbar3']])
|
.hmget(['batchhmset2', ['some manner of key', 'batchbar3']])
|
||||||
.mget('batchfoo2', ['batchfoo3', 'batchfoo'])
|
.mget('batchfoo2', ['batchfoo3', 'batchfoo'])
|
||||||
.exec().then((replies) => {
|
.exec()
|
||||||
|
.then((replies) => {
|
||||||
assert.strictEqual(arr.length, 3)
|
assert.strictEqual(arr.length, 3)
|
||||||
assert.strictEqual(arr2.length, 2)
|
assert.strictEqual(arr2.length, 2)
|
||||||
assert.strictEqual(arr3.length, 3)
|
assert.strictEqual(arr3.length, 3)
|
||||||
@@ -194,7 +196,8 @@ describe('The \'batch\' method', () => {
|
|||||||
.incr('some')
|
.incr('some')
|
||||||
.incr('keys')
|
.incr('keys')
|
||||||
.mget('some', 'keys')
|
.mget('some', 'keys')
|
||||||
.exec().then(helper.isDeepEqual(['OK', 11, 21, ['11', '21']]))
|
.exec()
|
||||||
|
.then(helper.isDeepEqual(['OK', 11, 21, ['11', '21']]))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows multiple commands to work the same as normal to be performed using a chaining API', () => {
|
it('allows multiple commands to work the same as normal to be performed using a chaining API', () => {
|
||||||
@@ -203,7 +206,8 @@ describe('The \'batch\' method', () => {
|
|||||||
.incr('some')
|
.incr('some')
|
||||||
.incr(['keys'])
|
.incr(['keys'])
|
||||||
.mget('some', 'keys')
|
.mget('some', 'keys')
|
||||||
.exec().then(helper.isDeepEqual(['OK', 11, 21, ['11', '21']]))
|
.exec()
|
||||||
|
.then(helper.isDeepEqual(['OK', 11, 21, ['11', '21']]))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows an array to be provided indicating multiple operations to perform', () => {
|
it('allows an array to be provided indicating multiple operations to perform', () => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const intercept = require('intercept-stdout')
|
const intercept = require('intercept-stdout')
|
||||||
|
|
||||||
describe('The \'blpop\' method', () => {
|
describe('The \'blpop\' method', () => {
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'client\' method', () => {
|
describe('The \'client\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -144,8 +145,9 @@ describe('The \'client\' method', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('sets the name', () => {
|
it('sets the name', () => {
|
||||||
// The querys are auto pipelined and the response is a response to all querys of one client
|
// The querys are auto pipelined and the response is a response to all
|
||||||
// per chunk. So the execution order is only guaranteed on each client
|
// querys of one client per chunk. So the execution order is only
|
||||||
|
// guaranteed on each client
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
client.client('setname', 'RUTH'),
|
client.client('setname', 'RUTH'),
|
||||||
client2.client('setname', ['RENEE']).then(helper.isString('OK')),
|
client2.client('setname', ['RENEE']).then(helper.isString('OK')),
|
||||||
|
@@ -3,13 +3,15 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const uuid = require('uuid')
|
const uuid = require('uuid')
|
||||||
|
|
||||||
describe('The \'dbsize\' method', () => {
|
describe('The \'dbsize\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
describe(`using ${ip}`, () => {
|
describe(`using ${ip}`, () => {
|
||||||
let key, value
|
let key
|
||||||
|
let value
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
key = uuid.v4()
|
key = uuid.v4()
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'del\' method', () => {
|
describe('The \'del\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -4,7 +4,8 @@ const assert = require('assert')
|
|||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'eval\' method', () => {
|
describe('The \'eval\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -121,7 +122,8 @@ describe('The \'eval\' method', () => {
|
|||||||
.rpush('mylist', 'a')
|
.rpush('mylist', 'a')
|
||||||
.rpush('mylist', 'b')
|
.rpush('mylist', 'b')
|
||||||
.rpush('mylist', 'c')
|
.rpush('mylist', 'c')
|
||||||
.exec().then((replies) => {
|
.exec()
|
||||||
|
.then((replies) => {
|
||||||
return client.eval('local foo = redis.call(\'lrange\',\'mylist\',0,-1); return {type(foo),foo[1],foo[2],foo[3],# foo}', 0).then((res) => {
|
return client.eval('local foo = redis.call(\'lrange\',\'mylist\',0,-1); return {type(foo),foo[1],foo[2],foo[3],# foo}', 0).then((res) => {
|
||||||
assert.strictEqual(5, res.length)
|
assert.strictEqual(5, res.length)
|
||||||
assert.strictEqual('table', res[0])
|
assert.strictEqual('table', res[0])
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'exists\' method', () => {
|
describe('The \'exists\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'expire\' method', () => {
|
describe('The \'expire\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const uuid = require('uuid')
|
const uuid = require('uuid')
|
||||||
|
|
||||||
describe('The \'flushdb\' method', () => {
|
describe('The \'flushdb\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
describe(`using ${ip}`, () => {
|
describe(`using ${ip}`, () => {
|
||||||
let key, key2
|
let key
|
||||||
|
let key2
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
key = uuid.v4()
|
key = uuid.v4()
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'geoadd\' method', () => {
|
describe('The \'geoadd\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const uuid = require('uuid')
|
const uuid = require('uuid')
|
||||||
|
|
||||||
describe('The \'get\' method', () => {
|
describe('The \'get\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
describe(`using ${ip}`, () => {
|
describe(`using ${ip}`, () => {
|
||||||
let key, value
|
let key
|
||||||
|
let value
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
key = uuid.v4()
|
key = uuid.v4()
|
||||||
|
@@ -2,13 +2,16 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const uuid = require('uuid')
|
const uuid = require('uuid')
|
||||||
|
|
||||||
describe('The \'getset\' method', () => {
|
describe('The \'getset\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
describe(`using ${ip}`, () => {
|
describe(`using ${ip}`, () => {
|
||||||
let key, value, value2
|
let key
|
||||||
|
let value
|
||||||
|
let value2
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
key = uuid.v4()
|
key = uuid.v4()
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'hgetall\' method', () => {
|
describe('The \'hgetall\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'hincrby\' method', () => {
|
describe('The \'hincrby\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'hlen\' method', () => {
|
describe('The \'hlen\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'hmget\' method', () => {
|
describe('The \'hmget\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -13,7 +14,7 @@ describe('The \'hmget\' method', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
client = redis.createClient.apply(null, args)
|
client = redis.createClient.apply(null, args)
|
||||||
client.flushdb()
|
client.flushdb()
|
||||||
return client.hmset(hash, {'0123456789': 'abcdefghij', 'some manner of key': 'a type of value'})
|
return client.hmset(hash, { '0123456789': 'abcdefghij', 'some manner of key': 'a type of value' })
|
||||||
.then(helper.isString('OK'))
|
.then(helper.isString('OK'))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'hmset\' method', () => {
|
describe('The \'hmset\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -20,25 +21,25 @@ describe('The \'hmset\' method', () => {
|
|||||||
return client.hgetall(hash).then(helper.isDeepEqual({
|
return client.hgetall(hash).then(helper.isDeepEqual({
|
||||||
'0123456789': 'abcdefghij',
|
'0123456789': 'abcdefghij',
|
||||||
'some manner of key': 'a type of value',
|
'some manner of key': 'a type of value',
|
||||||
'otherTypes': '555'
|
otherTypes: '555'
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles object-style syntax', () => {
|
it('handles object-style syntax', () => {
|
||||||
client.hmset(hash, {'0123456789': 'abcdefghij', 'some manner of key': 'a type of value', 'otherTypes': 555}).then(helper.isString('OK'))
|
client.hmset(hash, { '0123456789': 'abcdefghij', 'some manner of key': 'a type of value', otherTypes: 555 }).then(helper.isString('OK'))
|
||||||
return client.hgetall(hash).then(helper.isDeepEqual({
|
return client.hgetall(hash).then(helper.isDeepEqual({
|
||||||
'0123456789': 'abcdefghij',
|
'0123456789': 'abcdefghij',
|
||||||
'some manner of key': 'a type of value',
|
'some manner of key': 'a type of value',
|
||||||
'otherTypes': '555'
|
otherTypes: '555'
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handles object-style syntax and the key being a number', () => {
|
it('handles object-style syntax and the key being a number', () => {
|
||||||
client.hmset(231232, {'0123456789': 'abcdefghij', 'some manner of key': 'a type of value', 'otherTypes': 555})
|
client.hmset(231232, { '0123456789': 'abcdefghij', 'some manner of key': 'a type of value', otherTypes: 555 })
|
||||||
return client.hgetall(231232).then(helper.isDeepEqual({
|
return client.hgetall(231232).then(helper.isDeepEqual({
|
||||||
'0123456789': 'abcdefghij',
|
'0123456789': 'abcdefghij',
|
||||||
'some manner of key': 'a type of value',
|
'some manner of key': 'a type of value',
|
||||||
'otherTypes': '555'
|
otherTypes: '555'
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'hset\' method', () => {
|
describe('The \'hset\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -43,8 +44,9 @@ describe('The \'hset\' method', () => {
|
|||||||
it('warns if someone passed a array either as field or as value', () => {
|
it('warns if someone passed a array either as field or as value', () => {
|
||||||
const hash = 'test hash'
|
const hash = 'test hash'
|
||||||
const field = 'array'
|
const field = 'array'
|
||||||
// This would be converted to "array contents" but if you use more than one entry,
|
// This would be converted to "array contents" but if you use more than
|
||||||
// it'll result in e.g. "array contents,second content" and this is not supported and considered harmful
|
// one entry, it'll result in e.g. "array contents,second content" and
|
||||||
|
// this is not supported and considered harmful
|
||||||
const value = ['array contents']
|
const value = ['array contents']
|
||||||
return client.hmset(hash, field, value).then(assert, helper.isError())
|
return client.hmset(hash, field, value).then(assert, helper.isError())
|
||||||
})
|
})
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'incr\' method', () => {
|
describe('The \'incr\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'info\' method', () => {
|
describe('The \'info\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -4,7 +4,8 @@ const assert = require('assert')
|
|||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'keys\' method', () => {
|
describe('The \'keys\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -20,8 +21,8 @@ describe('The \'keys\' method', () => {
|
|||||||
client.mset(['test keys 1', 'test val 1', 'test keys 2', 'test val 2']).then(helper.isString('OK'))
|
client.mset(['test keys 1', 'test val 1', 'test keys 2', 'test val 2']).then(helper.isString('OK'))
|
||||||
return client.keys('test keys*').then((results) => {
|
return client.keys('test keys*').then((results) => {
|
||||||
assert.strictEqual(2, results.length)
|
assert.strictEqual(2, results.length)
|
||||||
assert.ok(~results.indexOf('test keys 1'))
|
assert.notStrictEqual(results.indexOf('test keys 1'), -1)
|
||||||
assert.ok(~results.indexOf('test keys 2'))
|
assert.notStrictEqual(results.indexOf('test keys 2'), -1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ describe('The \'keys\' method', () => {
|
|||||||
client.mset(keysValues.reduce((a, b) => a.concat(b))).then(helper.isString('OK'))
|
client.mset(keysValues.reduce((a, b) => a.concat(b))).then(helper.isString('OK'))
|
||||||
|
|
||||||
return client.keys('multibulk:*').then((results) => {
|
return client.keys('multibulk:*').then((results) => {
|
||||||
assert.deepStrictEqual(keysValues.map((val) => val[0]).sort(), results.sort())
|
assert.deepStrictEqual(keysValues.map(val => val[0]).sort(), results.sort())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'mget\' method', () => {
|
describe('The \'mget\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const utils = require('../../lib/utils')
|
const utils = require('../../lib/utils')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'monitor\' method', () => {
|
describe('The \'monitor\' method', () => {
|
||||||
helper.allTests((parser, ip, args) => {
|
helper.allTests((parser, ip, args) => {
|
||||||
@@ -185,8 +186,9 @@ describe('The \'monitor\' method', () => {
|
|||||||
assert.deepStrictEqual(args, responses.shift())
|
assert.deepStrictEqual(args, responses.shift())
|
||||||
assert(utils.monitorRegex.test(rawOutput), rawOutput)
|
assert(utils.monitorRegex.test(rawOutput), rawOutput)
|
||||||
if (responses.length === 0) {
|
if (responses.length === 0) {
|
||||||
// The publish is called right after the reconnect and the monitor is called before the message is emitted.
|
// The publish is called right after the reconnect and the monitor
|
||||||
// Therefore we have to wait till the next tick
|
// is called before the message is emitted. Therefore we have to
|
||||||
|
// wait till the next tick
|
||||||
process.nextTick(() => {
|
process.nextTick(() => {
|
||||||
assert(called)
|
assert(called)
|
||||||
pub.end(false)
|
pub.end(false)
|
||||||
|
@@ -3,13 +3,17 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const uuid = require('uuid')
|
const uuid = require('uuid')
|
||||||
|
|
||||||
describe('The \'mset\' method', () => {
|
describe('The \'mset\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
describe(`using ${ip}`, () => {
|
describe(`using ${ip}`, () => {
|
||||||
let key, value, key2, value2
|
let key
|
||||||
|
let value
|
||||||
|
let key2
|
||||||
|
let value2
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
key = uuid.v4()
|
key = uuid.v4()
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'msetnx\' method', () => {
|
describe('The \'msetnx\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'randomkey\' method', () => {
|
describe('The \'randomkey\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'rename\' method', () => {
|
describe('The \'rename\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'renamenx\' method', () => {
|
describe('The \'renamenx\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'rpush\' command', () => {
|
describe('The \'rpush\' command', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sadd\' method', () => {
|
describe('The \'sadd\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -18,7 +19,7 @@ describe('The \'sadd\' method', () => {
|
|||||||
it('allows a single value to be added to the set', () => {
|
it('allows a single value to be added to the set', () => {
|
||||||
client.sadd('set0', 'member0').then(helper.isNumber(1))
|
client.sadd('set0', 'member0').then(helper.isNumber(1))
|
||||||
return client.smembers('set0').then((res) => {
|
return client.smembers('set0').then((res) => {
|
||||||
assert.ok(~res.indexOf('member0'))
|
assert.notStrictEqual(res.indexOf('member0'), -1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -31,9 +32,9 @@ describe('The \'sadd\' method', () => {
|
|||||||
client.sadd('set0', ['member0', 'member1', 'member2']).then(helper.isNumber(3))
|
client.sadd('set0', ['member0', 'member1', 'member2']).then(helper.isNumber(3))
|
||||||
return client.smembers('set0').then((res) => {
|
return client.smembers('set0').then((res) => {
|
||||||
assert.strictEqual(res.length, 3)
|
assert.strictEqual(res.length, 3)
|
||||||
assert.ok(~res.indexOf('member0'))
|
assert.notStrictEqual(res.indexOf('member0'), -1)
|
||||||
assert.ok(~res.indexOf('member1'))
|
assert.notStrictEqual(res.indexOf('member1'), -1)
|
||||||
assert.ok(~res.indexOf('member2'))
|
assert.notStrictEqual(res.indexOf('member2'), -1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -41,9 +42,9 @@ describe('The \'sadd\' method', () => {
|
|||||||
client.sadd(['set0', 'member0', 'member1', 'member2']).then(helper.isNumber(3))
|
client.sadd(['set0', 'member0', 'member1', 'member2']).then(helper.isNumber(3))
|
||||||
return client.smembers('set0').then((res) => {
|
return client.smembers('set0').then((res) => {
|
||||||
assert.strictEqual(res.length, 3)
|
assert.strictEqual(res.length, 3)
|
||||||
assert.ok(~res.indexOf('member0'))
|
assert.notStrictEqual(res.indexOf('member0'), -1)
|
||||||
assert.ok(~res.indexOf('member1'))
|
assert.notStrictEqual(res.indexOf('member1'), -1)
|
||||||
assert.ok(~res.indexOf('member2'))
|
assert.notStrictEqual(res.indexOf('member2'), -1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'scard\' method', () => {
|
describe('The \'scard\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'script\' method', () => {
|
describe('The \'script\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sdiff\' method', () => {
|
describe('The \'sdiff\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sdiffstore\' method', () => {
|
describe('The \'sdiffstore\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -28,7 +29,7 @@ describe('The \'sdiffstore\' method', () => {
|
|||||||
|
|
||||||
return client.smembers('quux').then((values) => {
|
return client.smembers('quux').then((values) => {
|
||||||
const members = values.sort()
|
const members = values.sort()
|
||||||
assert.deepStrictEqual(members, [ 'b', 'x' ])
|
assert.deepStrictEqual(members, ['b', 'x'])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'select\' method', () => {
|
describe('The \'select\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,13 +3,15 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const uuid = require('uuid')
|
const uuid = require('uuid')
|
||||||
|
|
||||||
describe('The \'set\' method', () => {
|
describe('The \'set\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
describe(`using ${ip}`, () => {
|
describe(`using ${ip}`, () => {
|
||||||
let key, value
|
let key
|
||||||
|
let value
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
key = uuid.v4()
|
key = uuid.v4()
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'setex\' method', () => {
|
describe('The \'setex\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'setnx\' method', () => {
|
describe('The \'setnx\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sinter\' method', () => {
|
describe('The \'sinter\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -26,7 +27,7 @@ describe('The \'sinter\' method', () => {
|
|||||||
|
|
||||||
return client.sinter('sa', 'sb').then((intersection) => {
|
return client.sinter('sa', 'sb').then((intersection) => {
|
||||||
assert.strictEqual(intersection.length, 2)
|
assert.strictEqual(intersection.length, 2)
|
||||||
assert.deepStrictEqual(intersection.sort(), [ 'b', 'c' ])
|
assert.deepStrictEqual(intersection.sort(), ['b', 'c'])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sinterstore\' method', () => {
|
describe('The \'sinterstore\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sismember\' method', () => {
|
describe('The \'sismember\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'slowlog\' method', () => {
|
describe('The \'slowlog\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'smembers\' method', () => {
|
describe('The \'smembers\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -21,7 +22,7 @@ describe('The \'smembers\' method', () => {
|
|||||||
return client.smembers('foo').then((values) => {
|
return client.smembers('foo').then((values) => {
|
||||||
assert.strictEqual(values.length, 2)
|
assert.strictEqual(values.length, 2)
|
||||||
const members = values.sort()
|
const members = values.sort()
|
||||||
assert.deepStrictEqual(members, [ 'x', 'y' ])
|
assert.deepStrictEqual(members, ['x', 'y'])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'smove\' method', () => {
|
describe('The \'smove\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
|
||||||
function setupData (client) {
|
const { redis } = config
|
||||||
|
|
||||||
|
function setupData(client) {
|
||||||
client.rpush('y', 'd')
|
client.rpush('y', 'd')
|
||||||
client.rpush('y', 'b')
|
client.rpush('y', 'b')
|
||||||
client.rpush('y', 'a')
|
client.rpush('y', 'a')
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'spop\' method', () => {
|
describe('The \'spop\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'srem\' method', () => {
|
describe('The \'srem\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -30,7 +31,7 @@ describe('The \'srem\' method', () => {
|
|||||||
client.srem('set0', ['member1', 'member2']).then(helper.isNumber(2))
|
client.srem('set0', ['member1', 'member2']).then(helper.isNumber(2))
|
||||||
return client.smembers('set0').then((res) => {
|
return client.smembers('set0').then((res) => {
|
||||||
assert.strictEqual(res.length, 1)
|
assert.strictEqual(res.length, 1)
|
||||||
assert.ok(~res.indexOf('member0'))
|
assert.notStrictEqual(res.indexOf('member0'), -1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ describe('The \'srem\' method', () => {
|
|||||||
client.sendCommand('srem', ['set0', 'member1', 'member2']).then(helper.isNumber(2))
|
client.sendCommand('srem', ['set0', 'member1', 'member2']).then(helper.isNumber(2))
|
||||||
return client.smembers('set0').then((res) => {
|
return client.smembers('set0').then((res) => {
|
||||||
assert.strictEqual(res.length, 1)
|
assert.strictEqual(res.length, 1)
|
||||||
assert.ok(~res.indexOf('member0'))
|
assert.notStrictEqual(res.indexOf('member0'), -1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -48,9 +49,9 @@ describe('The \'srem\' method', () => {
|
|||||||
client.srem(['set0', 'member3', 'member4']).then(helper.isNumber(0))
|
client.srem(['set0', 'member3', 'member4']).then(helper.isNumber(0))
|
||||||
return client.smembers('set0').then((res) => {
|
return client.smembers('set0').then((res) => {
|
||||||
assert.strictEqual(res.length, 3)
|
assert.strictEqual(res.length, 3)
|
||||||
assert.ok(~res.indexOf('member0'))
|
assert.notStrictEqual(res.indexOf('member0'), -1)
|
||||||
assert.ok(~res.indexOf('member1'))
|
assert.notStrictEqual(res.indexOf('member1'), -1)
|
||||||
assert.ok(~res.indexOf('member2'))
|
assert.notStrictEqual(res.indexOf('member2'), -1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sunion\' method', () => {
|
describe('The \'sunion\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'sunionstore\' method', () => {
|
describe('The \'sunionstore\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'ttl\' method', () => {
|
describe('The \'ttl\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'type\' method', () => {
|
describe('The \'type\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'watch\' method', () => {
|
describe('The \'watch\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'zadd\' method', () => {
|
describe('The \'zadd\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'zscan\' method', () => {
|
describe('The \'zscan\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const config = require('../lib/config')
|
const config = require('../lib/config')
|
||||||
const helper = require('../helper')
|
const helper = require('../helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('The \'zscore\' method', () => {
|
describe('The \'zscore\' method', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -4,11 +4,13 @@ const assert = require('assert')
|
|||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const RedisProcess = require('./lib/redis-process')
|
const RedisProcess = require('./lib/redis-process')
|
||||||
|
|
||||||
let rp
|
let rp
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const redis = config.redis
|
|
||||||
|
|
||||||
// TODO: Fix redis process spawn on windows
|
const { redis } = config
|
||||||
|
|
||||||
|
// TODO: Fix redis process spawn on windows
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
describe('master slave sync', () => {
|
describe('master slave sync', () => {
|
||||||
let master = null
|
let master = null
|
||||||
@@ -29,7 +31,7 @@ if (process.platform !== 'win32') {
|
|||||||
let i = 0
|
let i = 0
|
||||||
while (i < 1000) {
|
while (i < 1000) {
|
||||||
i++
|
i++
|
||||||
// Write some data in the redis instance, so there's something to sync
|
// Write some data in the redis instance, so there's something to sync
|
||||||
multi.set(`foo${i}`, `bar${new Array(500).join(Math.random())}`)
|
multi.set(`foo${i}`, `bar${new Array(500).join(Math.random())}`)
|
||||||
}
|
}
|
||||||
return multi.exec()
|
return multi.exec()
|
||||||
@@ -42,8 +44,9 @@ if (process.platform !== 'win32') {
|
|||||||
let firstInfo
|
let firstInfo
|
||||||
slave = redis.createClient({
|
slave = redis.createClient({
|
||||||
port,
|
port,
|
||||||
retryStrategy (options) {
|
retryStrategy(options) {
|
||||||
// Try to reconnect in very small intervals to catch the master_link_status down before the sync completes
|
// Try to reconnect in very small intervals to catch the
|
||||||
|
// master_link_status down before the sync completes
|
||||||
return 10
|
return 10
|
||||||
}
|
}
|
||||||
})
|
})
|
@@ -4,9 +4,11 @@ const assert = require('assert')
|
|||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const connect = require('../lib/connect')
|
const connect = require('../lib/connect')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const Redis = config.redis
|
|
||||||
|
const { Redis } = config
|
||||||
const intercept = require('intercept-stdout')
|
const intercept = require('intercept-stdout')
|
||||||
const net = require('net')
|
const net = require('net')
|
||||||
|
|
||||||
let client
|
let client
|
||||||
|
|
||||||
describe('connection tests', () => {
|
describe('connection tests', () => {
|
||||||
@@ -18,9 +20,10 @@ describe('connection tests', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('support for a private stream', () => {
|
it('support for a private stream', () => {
|
||||||
// While using a private stream, reconnecting and other features are not going to work properly.
|
// While using a private stream, reconnecting and other features are not
|
||||||
// Besides that some functions also have to be monkey patched to be safe from errors in this case.
|
// going to work properly. Besides that some functions also have to be
|
||||||
// Therefore this is not officially supported!
|
// monkey patched to be safe from errors in this case. Therefore this is not
|
||||||
|
// officially supported!
|
||||||
const socket = new net.Socket()
|
const socket = new net.Socket()
|
||||||
client = new Redis({
|
client = new Redis({
|
||||||
prefix: 'test',
|
prefix: 'test',
|
||||||
@@ -41,7 +44,7 @@ describe('connection tests', () => {
|
|||||||
client = Redis.createClient({
|
client = Redis.createClient({
|
||||||
connectTimeout: 5,
|
connectTimeout: 5,
|
||||||
port: 9999,
|
port: 9999,
|
||||||
retryStrategy (options) {
|
retryStrategy(options) {
|
||||||
client.quit().then((res) => {
|
client.quit().then((res) => {
|
||||||
assert.strictEqual(res, 'OK')
|
assert.strictEqual(res, 'OK')
|
||||||
assert.strictEqual(called++, -1)
|
assert.strictEqual(called++, -1)
|
||||||
@@ -158,7 +161,7 @@ describe('connection tests', () => {
|
|||||||
host: 'somewhere',
|
host: 'somewhere',
|
||||||
port: 6379,
|
port: 6379,
|
||||||
family: ip,
|
family: ip,
|
||||||
retryStrategy () {}
|
retryStrategy() {}
|
||||||
}
|
}
|
||||||
client = Redis.createClient(options)
|
client = Redis.createClient(options)
|
||||||
assert.strictEqual(client._connectionOptions.family, ip === 'IPv6' ? 6 : 4)
|
assert.strictEqual(client._connectionOptions.family, ip === 'IPv6' ? 6 : 4)
|
||||||
@@ -172,7 +175,7 @@ describe('connection tests', () => {
|
|||||||
|
|
||||||
it('retryStrategy used to reconnect with individual error', (done) => {
|
it('retryStrategy used to reconnect with individual error', (done) => {
|
||||||
client = Redis.createClient({
|
client = Redis.createClient({
|
||||||
retryStrategy (options) {
|
retryStrategy(options) {
|
||||||
if (options.totalRetryTime > 150) {
|
if (options.totalRetryTime > 150) {
|
||||||
client.set('foo', 'bar').then(assert, (err) => {
|
client.set('foo', 'bar').then(assert, (err) => {
|
||||||
assert.strictEqual(err.message, 'Stream connection ended and command aborted.')
|
assert.strictEqual(err.message, 'Stream connection ended and command aborted.')
|
||||||
@@ -191,7 +194,7 @@ describe('connection tests', () => {
|
|||||||
|
|
||||||
it('retryStrategy used to reconnect', (done) => {
|
it('retryStrategy used to reconnect', (done) => {
|
||||||
client = Redis.createClient({
|
client = Redis.createClient({
|
||||||
retryStrategy (options) {
|
retryStrategy(options) {
|
||||||
if (options.totalRetryTime > 150) {
|
if (options.totalRetryTime > 150) {
|
||||||
client.set('foo', 'bar').catch((err) => {
|
client.set('foo', 'bar').catch((err) => {
|
||||||
assert.strictEqual(err.message, 'Stream connection ended and command aborted.')
|
assert.strictEqual(err.message, 'Stream connection ended and command aborted.')
|
||||||
@@ -214,7 +217,7 @@ describe('connection tests', () => {
|
|||||||
})
|
})
|
||||||
Redis.debugMode = true
|
Redis.debugMode = true
|
||||||
client = Redis.createClient({
|
client = Redis.createClient({
|
||||||
retryStrategy (options) {
|
retryStrategy(options) {
|
||||||
client.set('foo', 'bar').catch((err) => {
|
client.set('foo', 'bar').catch((err) => {
|
||||||
assert.strictEqual(err.code, 'NR_CLOSED')
|
assert.strictEqual(err.code, 'NR_CLOSED')
|
||||||
assert.strictEqual(err.message, 'Stream connection ended and command aborted.')
|
assert.strictEqual(err.message, 'Stream connection ended and command aborted.')
|
||||||
@@ -241,7 +244,7 @@ describe('connection tests', () => {
|
|||||||
// Auto detect ipv4 and use non routeable ip to trigger the timeout
|
// Auto detect ipv4 and use non routeable ip to trigger the timeout
|
||||||
host: '10.255.255.1',
|
host: '10.255.255.1',
|
||||||
connectTimeout,
|
connectTimeout,
|
||||||
retryStrategy () {
|
retryStrategy() {
|
||||||
return 5000
|
return 5000
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -510,7 +513,7 @@ describe('connection tests', () => {
|
|||||||
// Cover info parts with no value
|
// Cover info parts with no value
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
const command = client.commandQueue.peekAt(0)
|
const command = client.commandQueue.peekAt(0)
|
||||||
const callback = command.callback
|
const { callback } = command
|
||||||
command.callback = (err, res) => {
|
command.callback = (err, res) => {
|
||||||
res += 'added:\r\n'
|
res += 'added:\r\n'
|
||||||
callback(err, res)
|
callback(err, res)
|
||||||
@@ -528,7 +531,8 @@ describe('connection tests', () => {
|
|||||||
client.info = function () {
|
client.info = function () {
|
||||||
return tmp().then((res) => {
|
return tmp().then((res) => {
|
||||||
if (!delayed) {
|
if (!delayed) {
|
||||||
// Try reconnecting after one second even if redis tells us the time needed is above one second
|
// Try reconnecting after one second even if redis tells us the
|
||||||
|
// time needed is above one second
|
||||||
client.serverInfo.persistence.loading = 1
|
client.serverInfo.persistence.loading = 1
|
||||||
client.serverInfo.persistence.loading_eta_seconds = 2.5
|
client.serverInfo.persistence.loading_eta_seconds = 2.5
|
||||||
delayed = true
|
delayed = true
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('detectBuffers', () => {
|
describe('detectBuffers', () => {
|
||||||
let client
|
let client
|
||||||
@@ -61,7 +62,8 @@ describe('detectBuffers', () => {
|
|||||||
.hget(Buffer.from('hash key 2'), 'key 1')
|
.hget(Buffer.from('hash key 2'), 'key 1')
|
||||||
.hget('hash key 2', Buffer.from('key 2'))
|
.hget('hash key 2', Buffer.from('key 2'))
|
||||||
.hget('hash key 2', 'key 2')
|
.hget('hash key 2', 'key 2')
|
||||||
.exec().then((reply) => {
|
.exec()
|
||||||
|
.then((reply) => {
|
||||||
assert.strictEqual(true, Array.isArray(reply))
|
assert.strictEqual(true, Array.isArray(reply))
|
||||||
assert.strictEqual(4, reply.length)
|
assert.strictEqual(4, reply.length)
|
||||||
assert.strictEqual('val 1', reply[0])
|
assert.strictEqual('val 1', reply[0])
|
||||||
@@ -81,7 +83,8 @@ describe('detectBuffers', () => {
|
|||||||
.hget(Buffer.from('hash key 2'), 'key 1')
|
.hget(Buffer.from('hash key 2'), 'key 1')
|
||||||
.hget('hash key 2', Buffer.from('key 2'))
|
.hget('hash key 2', Buffer.from('key 2'))
|
||||||
.hget('hash key 2', 'key 2')
|
.hget('hash key 2', 'key 2')
|
||||||
.exec().then((reply) => {
|
.exec()
|
||||||
|
.then((reply) => {
|
||||||
assert.strictEqual(true, Array.isArray(reply))
|
assert.strictEqual(true, Array.isArray(reply))
|
||||||
assert.strictEqual(4, reply.length)
|
assert.strictEqual(4, reply.length)
|
||||||
assert.strictEqual('val 1', reply[0])
|
assert.strictEqual('val 1', reply[0])
|
||||||
|
@@ -3,8 +3,9 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const fork = require('child_process').fork
|
const { fork } = require('child_process')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('stack traces', () => {
|
describe('stack traces', () => {
|
||||||
it('should return good traces with NODE_ENV=development set', (done) => {
|
it('should return good traces with NODE_ENV=development set', (done) => {
|
||||||
|
@@ -5,6 +5,7 @@ const path = require('path')
|
|||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const RedisProcess = require('./lib/redis-process')
|
const RedisProcess = require('./lib/redis-process')
|
||||||
const StunnelProcess = require('./lib/stunnel-process')
|
const StunnelProcess = require('./lib/stunnel-process')
|
||||||
|
|
||||||
let rp
|
let rp
|
||||||
let stunnelProcess
|
let stunnelProcess
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ process.on('unhandledRejection', (err, promise) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function startRedis (conf, done, port) {
|
function startRedis(conf, done, port) {
|
||||||
RedisProcess.start((err, _rp) => {
|
RedisProcess.start((err, _rp) => {
|
||||||
rp = _rp
|
rp = _rp
|
||||||
return done(err)
|
return done(err)
|
||||||
@@ -37,7 +38,7 @@ if (!process.env.REDIS_TESTS_STARTED) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayHelper (results) {
|
function arrayHelper(results) {
|
||||||
if (results instanceof Array) {
|
if (results instanceof Array) {
|
||||||
assert.strictEqual(results.length, 1, 'The array length may only be one element')
|
assert.strictEqual(results.length, 1, 'The array length may only be one element')
|
||||||
return results[0]
|
return results[0]
|
||||||
@@ -45,7 +46,7 @@ function arrayHelper (results) {
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
function toString (res) {
|
function toString(res) {
|
||||||
// If options are passed to return either strings or buffers...
|
// If options are passed to return either strings or buffers...
|
||||||
if (Buffer.isBuffer(res)) {
|
if (Buffer.isBuffer(res)) {
|
||||||
return res.toString()
|
return res.toString()
|
||||||
@@ -55,40 +56,40 @@ function toString (res) {
|
|||||||
}
|
}
|
||||||
// Stringify all values as well
|
// Stringify all values as well
|
||||||
if (typeof res === 'object' && res !== null) {
|
if (typeof res === 'object' && res !== null) {
|
||||||
Object.keys(res).map((key) => (res[key] = toString(res[key])))
|
Object.keys(res).forEach((key) => { res[key] = toString(res[key]) })
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
redisProcess () {
|
redisProcess() {
|
||||||
return rp
|
return rp
|
||||||
},
|
},
|
||||||
stopRedis (done) {
|
stopRedis(done) {
|
||||||
rp.stop(done)
|
rp.stop(done)
|
||||||
},
|
},
|
||||||
startRedis,
|
startRedis,
|
||||||
stopStunnel (done) {
|
stopStunnel(done) {
|
||||||
if (stunnelProcess) {
|
if (stunnelProcess) {
|
||||||
StunnelProcess.stop(stunnelProcess, done)
|
StunnelProcess.stop(stunnelProcess, done)
|
||||||
} else {
|
} else {
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
startStunnel (done) {
|
startStunnel(done) {
|
||||||
StunnelProcess.start((err, _stunnelProcess) => {
|
StunnelProcess.start((err, _stunnelProcess) => {
|
||||||
stunnelProcess = _stunnelProcess
|
stunnelProcess = _stunnelProcess
|
||||||
return done(err)
|
return done(err)
|
||||||
}, path.resolve(__dirname, './conf'))
|
}, path.resolve(__dirname, './conf'))
|
||||||
},
|
},
|
||||||
isNumber (expected) {
|
isNumber(expected) {
|
||||||
return function (results) {
|
return function (results) {
|
||||||
results = arrayHelper(results)
|
results = arrayHelper(results)
|
||||||
assert.strictEqual(results, expected, `${expected} !== ${results}`)
|
assert.strictEqual(results, expected, `${expected} !== ${results}`)
|
||||||
assert.strictEqual(typeof results, 'number', `expected a number, got ${typeof results}`)
|
assert.strictEqual(typeof results, 'number', `expected a number, got ${typeof results}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isString (str) {
|
isString(str) {
|
||||||
str = `${str}` // Make sure it's a string
|
str = `${str}` // Make sure it's a string
|
||||||
return function (results) {
|
return function (results) {
|
||||||
results = arrayHelper(results)
|
results = arrayHelper(results)
|
||||||
@@ -96,50 +97,51 @@ module.exports = {
|
|||||||
assert.strictEqual(results, str, `${str} does not match ${results}`)
|
assert.strictEqual(results, str, `${str} does not match ${results}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isNull () {
|
isNull() {
|
||||||
return function (results) {
|
return function (results) {
|
||||||
results = arrayHelper(results)
|
results = arrayHelper(results)
|
||||||
assert.strictEqual(results, null, `${results} is not null`)
|
assert.strictEqual(results, null, `${results} is not null`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isUndefined () {
|
isUndefined() {
|
||||||
return function (results) {
|
return function (results) {
|
||||||
results = arrayHelper(results)
|
results = arrayHelper(results)
|
||||||
assert.strictEqual(results, undefined, `${results} is not undefined`)
|
assert.strictEqual(results, undefined, `${results} is not undefined`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isError (regex) {
|
isError(regex) {
|
||||||
return function (err, res) {
|
return function (err, res) {
|
||||||
assert.strictEqual(res, undefined, 'There should be an error, no result!')
|
assert.strictEqual(res, undefined, 'There should be an error, no result!')
|
||||||
assert(err instanceof Error, 'err is not instance of \'Error\', but an error is expected here.')
|
assert(err instanceof Error, 'err is not instance of \'Error\', but an error is expected here.')
|
||||||
if (regex) assert(regex.test(err.message))
|
if (regex) assert(regex.test(err.message))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isDeepEqual (args) {
|
isDeepEqual(args) {
|
||||||
return function (res) {
|
return function (res) {
|
||||||
res = toString(res)
|
res = toString(res)
|
||||||
assert.deepStrictEqual(res, args)
|
assert.deepStrictEqual(res, args)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
match (pattern) {
|
match(pattern) {
|
||||||
return function (results) {
|
return function (results) {
|
||||||
results = arrayHelper(results)
|
results = arrayHelper(results)
|
||||||
assert(pattern.test(results), `expected string '${results}' to match ${pattern.toString()}`)
|
assert(pattern.test(results), `expected string '${results}' to match ${pattern.toString()}`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail (err) {
|
fail(err) {
|
||||||
err = err instanceof Error
|
err = err instanceof Error
|
||||||
? err
|
? err
|
||||||
: new Error('This should not be reachable')
|
: new Error('This should not be reachable')
|
||||||
throw err
|
throw err
|
||||||
},
|
},
|
||||||
serverVersionAtLeast (connection, desiredVersion) {
|
serverVersionAtLeast(connection, desiredVersion) {
|
||||||
// Wait until a connection has established (otherwise a timeout is going to be triggered at some point)
|
// Wait until a connection has established (otherwise a timeout is going to
|
||||||
|
// be triggered at some point)
|
||||||
if (Object.keys(connection.serverInfo).length === 0) {
|
if (Object.keys(connection.serverInfo).length === 0) {
|
||||||
throw new Error('Version check not possible as the client is not yet ready or did not expose the version')
|
throw new Error('Version check not possible as the client is not yet ready or did not expose the version')
|
||||||
}
|
}
|
||||||
// Return true if the server version >= desiredVersion
|
// Return true if the server version >= desiredVersion
|
||||||
const version = connection.serverInfo.server.version
|
const { version } = connection.serverInfo.server
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
if (version[i] > desiredVersion[i]) {
|
if (version[i] > desiredVersion[i]) {
|
||||||
return true
|
return true
|
||||||
@@ -151,7 +153,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
allTests (opts, cb) {
|
allTests(opts, cb) {
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
cb = opts
|
cb = opts
|
||||||
opts = {}
|
opts = {}
|
||||||
@@ -167,11 +169,9 @@ module.exports = {
|
|||||||
}]
|
}]
|
||||||
options.forEach((options) => {
|
options.forEach((options) => {
|
||||||
let strOptions = ''
|
let strOptions = ''
|
||||||
let key
|
const keys = Object.keys(options)
|
||||||
for (key in options) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
if (options.hasOwnProperty(key)) {
|
strOptions += `${keys[i]}: ${options[keys[i]]}; `
|
||||||
strOptions += `${key}: ${options[key]}; `
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
describe(`using options: ${strOptions}`, () => {
|
describe(`using options: ${strOptions}`, () => {
|
||||||
protocols.forEach((ip, i) => {
|
protocols.forEach((ip, i) => {
|
||||||
@@ -183,12 +183,12 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
removeMochaListener () {
|
removeMochaListener() {
|
||||||
const mochaListener = process.listeners('uncaughtException').pop()
|
const mochaListener = process.listeners('uncaughtException').pop()
|
||||||
process.removeListener('uncaughtException', mochaListener)
|
process.removeListener('uncaughtException', mochaListener)
|
||||||
return mochaListener
|
return mochaListener
|
||||||
},
|
},
|
||||||
callFuncAfter (func, max) {
|
callFuncAfter(func, max) {
|
||||||
let i = 0
|
let i = 0
|
||||||
return function () {
|
return function () {
|
||||||
i++
|
i++
|
||||||
@@ -199,7 +199,7 @@ module.exports = {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
killConnection (client) {
|
killConnection(client) {
|
||||||
// Change the connection option to a non existing one and destroy the stream
|
// Change the connection option to a non existing one and destroy the stream
|
||||||
client._connectionOptions = {
|
client._connectionOptions = {
|
||||||
port: 65535,
|
port: 65535,
|
||||||
|
@@ -11,7 +11,7 @@ const config = {
|
|||||||
IPv4: '127.0.0.1',
|
IPv4: '127.0.0.1',
|
||||||
IPv6: '::1'
|
IPv6: '::1'
|
||||||
},
|
},
|
||||||
configureClient (ip, opts) {
|
configureClient(ip, opts) {
|
||||||
const args = []
|
const args = []
|
||||||
// Do not manipulate the opts => copy them each time
|
// Do not manipulate the opts => copy them each time
|
||||||
opts = opts ? JSON.parse(JSON.stringify(opts)) : {}
|
opts = opts ? JSON.parse(JSON.stringify(opts)) : {}
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
// Spawned by the goodStacks.spec.js tests
|
// Spawned by the goodStacks.spec.js tests
|
||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const redis = require('../../index')
|
const redis = require('../../index')
|
||||||
|
|
||||||
const client = redis.createClient()
|
const client = redis.createClient()
|
||||||
|
|
||||||
// Both error cases would normally return bad stack traces
|
// Both error cases would normally return bad stack traces
|
||||||
|
@@ -9,7 +9,7 @@ const tcpPortUsed = require('tcp-port-used')
|
|||||||
|
|
||||||
// wait for redis to be listening in
|
// wait for redis to be listening in
|
||||||
// all three modes (ipv4, ipv6, socket).
|
// all three modes (ipv4, ipv6, socket).
|
||||||
function waitForRedis (available, cb, port) {
|
function waitForRedis(available, cb, port) {
|
||||||
if (process.platform === 'win32') return cb()
|
if (process.platform === 'win32') return cb()
|
||||||
|
|
||||||
const time = Date.now()
|
const time = Date.now()
|
||||||
@@ -49,7 +49,7 @@ function waitForRedis (available, cb, port) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
start (done, conf, port) {
|
start(done, conf, port) {
|
||||||
let spawnFailed = false
|
let spawnFailed = false
|
||||||
// spawn redis with our testing configuration.
|
// spawn redis with our testing configuration.
|
||||||
const confFile = conf || path.resolve(__dirname, '../conf/redis.conf')
|
const confFile = conf || path.resolve(__dirname, '../conf/redis.conf')
|
||||||
@@ -67,10 +67,10 @@ module.exports = {
|
|||||||
// return an object that can be used in
|
// return an object that can be used in
|
||||||
// an after() block to shutdown redis.
|
// an after() block to shutdown redis.
|
||||||
return done(null, {
|
return done(null, {
|
||||||
spawnFailed () {
|
spawnFailed() {
|
||||||
return spawnFailed
|
return spawnFailed
|
||||||
},
|
},
|
||||||
stop (done) {
|
stop(done) {
|
||||||
if (spawnFailed) return done()
|
if (spawnFailed) return done()
|
||||||
rp.once('exit', (code) => {
|
rp.once('exit', (code) => {
|
||||||
let error = null
|
let error = null
|
||||||
|
@@ -1,22 +1,22 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
// Helper to start and stop the stunnel process.
|
// Helper to start and stop the stunnel process.
|
||||||
const spawn = require('child_process').spawn
|
const { spawn } = require('child_process')
|
||||||
const EventEmitter = require('events')
|
const EventEmitter = require('events')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const util = require('util')
|
const util = require('util')
|
||||||
|
|
||||||
function once (cb) {
|
function once(cb) {
|
||||||
let called = false
|
let called = false
|
||||||
return function () {
|
return function (...args) {
|
||||||
if (called) return
|
if (called) return
|
||||||
called = true
|
called = true
|
||||||
cb.apply(this, arguments)
|
cb.apply(this, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function StunnelProcess (confDir) {
|
function StunnelProcess(confDir) {
|
||||||
EventEmitter.call(this)
|
EventEmitter.call(this)
|
||||||
|
|
||||||
// Set up an stunnel to redis; edit the conf file to include required absolute paths
|
// Set up an stunnel to redis; edit the conf file to include required absolute paths
|
||||||
@@ -24,7 +24,8 @@ function StunnelProcess (confDir) {
|
|||||||
const confText = fs.readFileSync(`${confFile}.template`).toString().replace(/__dirname/g, confDir)
|
const confText = fs.readFileSync(`${confFile}.template`).toString().replace(/__dirname/g, confDir)
|
||||||
|
|
||||||
fs.writeFileSync(confFile, confText)
|
fs.writeFileSync(confFile, confText)
|
||||||
const stunnel = this.stunnel = spawn('stunnel', [confFile])
|
this.stunnel = spawn('stunnel', [confFile])
|
||||||
|
const { stunnel } = this
|
||||||
|
|
||||||
// Handle child process events, and failure to set up tunnel
|
// Handle child process events, and failure to set up tunnel
|
||||||
this.timer = setTimeout(() => {
|
this.timer = setTimeout(() => {
|
||||||
@@ -67,13 +68,13 @@ StunnelProcess.prototype.stop = function (done) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
start (done, confDir) {
|
start(doneOrig, confDir) {
|
||||||
done = once(done)
|
const done = once(doneOrig)
|
||||||
const stunnel = new StunnelProcess(confDir)
|
const stunnel = new StunnelProcess(confDir)
|
||||||
stunnel.once('error', done.bind(done))
|
stunnel.once('error', done.bind(done))
|
||||||
stunnel.once('started', done.bind(done, null, stunnel))
|
stunnel.once('started', done.bind(done, null, stunnel))
|
||||||
},
|
},
|
||||||
stop (stunnel, done) {
|
stop(stunnel, done) {
|
||||||
stunnel.removeAllListeners()
|
stunnel.removeAllListeners()
|
||||||
stunnel.stop()
|
stunnel.stop()
|
||||||
stunnel.once('error', done.bind(done))
|
stunnel.once('error', done.bind(done))
|
||||||
|
@@ -1,14 +1,16 @@
|
|||||||
// spawned by the unref tests in nodeRedis.spec.js.
|
// spawned by the unref tests in nodeRedis.spec.js.
|
||||||
// when configured, unref causes the client to exit
|
// when configured, unref causes the client to exit
|
||||||
// as soon as there are no outstanding commands.
|
// as soon as there are no outstanding commands.
|
||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const redis = require('../../index')
|
const redis = require('../../index')
|
||||||
|
|
||||||
const HOST = process.argv[2] || '127.0.0.1'
|
const HOST = process.argv[2] || '127.0.0.1'
|
||||||
const PORT = process.argv[3]
|
const PORT = process.argv[3]
|
||||||
const args = PORT ? [PORT, HOST] : [HOST]
|
const args = PORT ? [PORT, HOST] : [HOST]
|
||||||
|
|
||||||
const c = redis.createClient.apply(redis, args)
|
const c = redis.createClient(...args)
|
||||||
c.info((err, reply) => {
|
c.info((err, reply) => {
|
||||||
if (err) process.exit(-1)
|
if (err) process.exit(-1)
|
||||||
if (!reply.length) process.exit(-1)
|
if (!reply.length) process.exit(-1)
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const utils = require('../lib/utils')
|
const utils = require('../lib/utils')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const zlib = require('zlib')
|
const zlib = require('zlib')
|
||||||
|
|
||||||
let client
|
let client
|
||||||
|
|
||||||
describe('The \'multi\' method', () => {
|
describe('The \'multi\' method', () => {
|
||||||
@@ -23,32 +25,32 @@ describe('The \'multi\' method', () => {
|
|||||||
|
|
||||||
// Some random object created from http://beta.json-generator.com/
|
// Some random object created from http://beta.json-generator.com/
|
||||||
const testObj = {
|
const testObj = {
|
||||||
'Id': '5642c4c33d4667c4a1fefd99',
|
Id: '5642c4c33d4667c4a1fefd99',
|
||||||
'index': 0,
|
index: 0,
|
||||||
'guid': '5baf1f1c-7621-41e7-ae7a-f8c6f3199b0f',
|
guid: '5baf1f1c-7621-41e7-ae7a-f8c6f3199b0f',
|
||||||
'isActive': true,
|
isActive: true,
|
||||||
'balance': '$1,028.63',
|
balance: '$1,028.63',
|
||||||
'picture': 'http://placehold.it/32x32',
|
picture: 'http://placehold.it/32x32',
|
||||||
'age': 31,
|
age: 31,
|
||||||
'eyeColor': 'green',
|
eyeColor: 'green',
|
||||||
'name': {'first': 'Shana', 'last': 'Long'},
|
name: { first: 'Shana', last: 'Long' },
|
||||||
'company': 'MANGLO',
|
company: 'MANGLO',
|
||||||
'email': 'shana.long@manglo.us',
|
email: 'shana.long@manglo.us',
|
||||||
'phone': '+1 (926) 405-3105',
|
phone: '+1 (926) 405-3105',
|
||||||
'address': '747 Dank Court, Norfolk, Ohio, 1112',
|
address: '747 Dank Court, Norfolk, Ohio, 1112',
|
||||||
'about': 'Eu pariatur in nisi occaecat enim qui consequat nostrud cupidatat id. ' +
|
about: 'Eu pariatur in nisi occaecat enim qui consequat nostrud cupidatat id. ' +
|
||||||
'Commodo commodo dolore esse irure minim quis deserunt anim laborum aute deserunt et est. Quis nisi laborum deserunt nisi quis.',
|
'Commodo commodo dolore esse irure minim quis deserunt anim laborum aute deserunt et est. Quis nisi laborum deserunt nisi quis.',
|
||||||
'registered': 'Friday, April 18, 2014 9:56 AM',
|
registered: 'Friday, April 18, 2014 9:56 AM',
|
||||||
'latitude': '74.566613',
|
latitude: '74.566613',
|
||||||
'longitude': '-11.660432',
|
longitude: '-11.660432',
|
||||||
'tags': [7, 'excepteur'],
|
tags: [7, 'excepteur'],
|
||||||
'range': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
range: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||||
'friends': [3, {'id': 1, 'name': 'Schultz Dyer'}],
|
friends: [3, { id: 1, name: 'Schultz Dyer' }],
|
||||||
'greeting': 'Hello, Shana! You have 5 unread messages.',
|
greeting: 'Hello, Shana! You have 5 unread messages.',
|
||||||
'favoriteFruit': 'strawberry'
|
favoriteFruit: 'strawberry'
|
||||||
}
|
}
|
||||||
|
|
||||||
function run () {
|
function run() {
|
||||||
if (end() === true) {
|
if (end() === true) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -132,10 +134,11 @@ describe('The \'multi\' method', () => {
|
|||||||
|
|
||||||
it('results in a execabort #2', () => {
|
it('results in a execabort #2', () => {
|
||||||
// Check that using monitor with a transactions results in an error
|
// Check that using monitor with a transactions results in an error
|
||||||
return client.multi().set('foo', 'bar').monitor().exec().then(assert, (err) => {
|
return client.multi().set('foo', 'bar').monitor().exec()
|
||||||
assert.strictEqual(err.code, 'EXECABORT')
|
.then(assert, (err) => {
|
||||||
client.end(false)
|
assert.strictEqual(err.code, 'EXECABORT')
|
||||||
})
|
client.end(false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sanity check', (done) => {
|
it('sanity check', (done) => {
|
||||||
@@ -178,7 +181,7 @@ describe('The \'multi\' method', () => {
|
|||||||
const multi1 = client.multi()
|
const multi1 = client.multi()
|
||||||
multi1.set('m1', '123')
|
multi1.set('m1', '123')
|
||||||
multi1.get('m1')
|
multi1.get('m1')
|
||||||
multi1.exec().then(() => (called = true))
|
multi1.exec().then(() => { called = true })
|
||||||
client.once('ready', () => {
|
client.once('ready', () => {
|
||||||
const multi1 = client.multi()
|
const multi1 = client.multi()
|
||||||
multi1.set('m2', '456')
|
multi1.set('m2', '456')
|
||||||
@@ -199,7 +202,7 @@ describe('The \'multi\' method', () => {
|
|||||||
host: 'somewhere',
|
host: 'somewhere',
|
||||||
port: 6379,
|
port: 6379,
|
||||||
family: 'IPv6',
|
family: 'IPv6',
|
||||||
retryStrategy () {}
|
retryStrategy() {}
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.strictEqual(client._connectionOptions.family, 6)
|
assert.strictEqual(client._connectionOptions.family, 6)
|
||||||
@@ -334,8 +337,8 @@ describe('The \'multi\' method', () => {
|
|||||||
[['hmset', 'multihmset2', 'multibar2', 'multifoo3', 'multibar3', 'test']],
|
[['hmset', 'multihmset2', 'multibar2', 'multifoo3', 'multibar3', 'test']],
|
||||||
['hmset', ['multihmset', 'multibar', 'multifoo']],
|
['hmset', ['multihmset', 'multibar', 'multifoo']],
|
||||||
['hmset', arr3],
|
['hmset', arr3],
|
||||||
['hmset', now, {123456789: 'abcdefghij', 'some manner of key': 'a type of value', 'otherTypes': 555}],
|
['hmset', now, { 123456789: 'abcdefghij', 'some manner of key': 'a type of value', otherTypes: 555 }],
|
||||||
['hmset', 'key2', {'0123456789': 'abcdefghij', 'some manner of key': 'a type of value', 'otherTypes': 999}],
|
['hmset', 'key2', { '0123456789': 'abcdefghij', 'some manner of key': 'a type of value', otherTypes: 999 }],
|
||||||
['hmset', 'multihmset', ['multibar', 'multibaz']],
|
['hmset', 'multihmset', ['multibar', 'multibaz']],
|
||||||
['hmset', 'multihmset', ['multibar', 'multibaz']]
|
['hmset', 'multihmset', ['multibar', 'multibaz']]
|
||||||
])
|
])
|
||||||
@@ -343,7 +346,8 @@ describe('The \'multi\' method', () => {
|
|||||||
.hmget('key2', arr2)
|
.hmget('key2', arr2)
|
||||||
.hmget(['multihmset2', 'some manner of key', 'multibar3'])
|
.hmget(['multihmset2', 'some manner of key', 'multibar3'])
|
||||||
.mget('multifoo2', ['multifoo3', 'multifoo'])
|
.mget('multifoo2', ['multifoo3', 'multifoo'])
|
||||||
.exec().then((replies) => {
|
.exec()
|
||||||
|
.then((replies) => {
|
||||||
assert.strictEqual(arr.length, 3)
|
assert.strictEqual(arr.length, 3)
|
||||||
assert.strictEqual(arr2.length, 2)
|
assert.strictEqual(arr2.length, 2)
|
||||||
assert.strictEqual(arr3.length, 3)
|
assert.strictEqual(arr3.length, 3)
|
||||||
@@ -376,7 +380,8 @@ describe('The \'multi\' method', () => {
|
|||||||
.incr('some')
|
.incr('some')
|
||||||
.incr('keys')
|
.incr('keys')
|
||||||
.mget('some', ['keys'])
|
.mget('some', ['keys'])
|
||||||
.exec().then(helper.isDeepEqual(['OK', 11, 21, ['11', '21']]))
|
.exec()
|
||||||
|
.then(helper.isDeepEqual(['OK', 11, 21, ['11', '21']]))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows an array to be provided indicating multiple operations to perform', () => {
|
it('allows an array to be provided indicating multiple operations to perform', () => {
|
||||||
@@ -395,7 +400,8 @@ describe('The \'multi\' method', () => {
|
|||||||
things: 'here'
|
things: 'here'
|
||||||
})
|
})
|
||||||
.hgetall('multihash')
|
.hgetall('multihash')
|
||||||
.exec().then((replies) => {
|
.exec()
|
||||||
|
.then((replies) => {
|
||||||
assert.strictEqual('OK', replies[0])
|
assert.strictEqual('OK', replies[0])
|
||||||
assert.strictEqual(Object.keys(replies[2]).length, 4)
|
assert.strictEqual(Object.keys(replies[2]).length, 4)
|
||||||
assert.strictEqual('foo', replies[2].a)
|
assert.strictEqual('foo', replies[2].a)
|
||||||
@@ -406,28 +412,32 @@ describe('The \'multi\' method', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('reports EXECABORT exceptions when they occur (while queueing)', () => {
|
it('reports EXECABORT exceptions when they occur (while queueing)', () => {
|
||||||
return client.multi().config('bar').set('foo').set('bar').exec().then(assert, (err) => {
|
return client.multi().config('bar').set('foo').set('bar')
|
||||||
assert.strictEqual(err.code, 'EXECABORT')
|
.exec()
|
||||||
assert(err.message.match(/^EXECABORT/), 'Error message should begin with EXECABORT')
|
.then(assert, (err) => {
|
||||||
assert.strictEqual(err.errors.length, 2, 'err.errors should have 2 items')
|
assert.strictEqual(err.code, 'EXECABORT')
|
||||||
assert.strictEqual(err.errors[0].command, 'SET')
|
assert(err.message.match(/^EXECABORT/), 'Error message should begin with EXECABORT')
|
||||||
assert.strictEqual(err.errors[0].code, 'ERR')
|
assert.strictEqual(err.errors.length, 2, 'err.errors should have 2 items')
|
||||||
assert.strictEqual(err.errors[0].position, 1)
|
assert.strictEqual(err.errors[0].command, 'SET')
|
||||||
assert(/^ERR/.test(err.errors[0].message), 'Actual error message should begin with ERR')
|
assert.strictEqual(err.errors[0].code, 'ERR')
|
||||||
})
|
assert.strictEqual(err.errors[0].position, 1)
|
||||||
|
assert(/^ERR/.test(err.errors[0].message), 'Actual error message should begin with ERR')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('reports multiple exceptions when they occur (while EXEC is running)', () => {
|
it('reports multiple exceptions when they occur (while EXEC is running)', () => {
|
||||||
return client.multi().config('bar').debug('foo').eval('return {err=\'this is an error\'}', 0).exec().then(assert, (err) => {
|
return client.multi().config('bar').debug('foo').eval('return {err=\'this is an error\'}', 0)
|
||||||
assert.strictEqual(err.replies.length, 3)
|
.exec()
|
||||||
assert.strictEqual(err.replies[0].code, 'ERR')
|
.then(assert, (err) => {
|
||||||
assert.strictEqual(err.replies[0].command, 'CONFIG')
|
assert.strictEqual(err.replies.length, 3)
|
||||||
assert.strictEqual(err.replies[2].code, undefined)
|
assert.strictEqual(err.replies[0].code, 'ERR')
|
||||||
assert.strictEqual(err.replies[2].command, 'EVAL')
|
assert.strictEqual(err.replies[0].command, 'CONFIG')
|
||||||
assert(/^this is an error/.test(err.replies[2].message))
|
assert.strictEqual(err.replies[2].code, undefined)
|
||||||
assert(/^ERR/.test(err.replies[0].message), 'Error message should begin with ERR')
|
assert.strictEqual(err.replies[2].command, 'EVAL')
|
||||||
assert(/^ERR/.test(err.replies[1].message), 'Error message should begin with ERR')
|
assert(/^this is an error/.test(err.replies[2].message))
|
||||||
})
|
assert(/^ERR/.test(err.replies[0].message), 'Error message should begin with ERR')
|
||||||
|
assert(/^ERR/.test(err.replies[1].message), 'Error message should begin with ERR')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not use a transaction with execAtomic if no command is used', () => {
|
it('should not use a transaction with execAtomic if no command is used', () => {
|
||||||
@@ -487,16 +497,19 @@ describe('The \'multi\' method', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('indivdual commands work properly with multi', () => {
|
it('indivdual commands work properly with multi', () => {
|
||||||
// Neither of the following work properly in a transactions:
|
// Neither of the following work properly in a transactions: (This is
|
||||||
// (This is due to Redis not returning the reply as expected / resulting in undefined behavior)
|
// due to Redis not returning the reply as expected / resulting in
|
||||||
// (Likely there are more commands that do not work with a transaction)
|
// undefined behavior) (Likely there are more commands that do not
|
||||||
|
// work with a transaction)
|
||||||
//
|
//
|
||||||
// auth => can't be called after a multi command
|
// auth => can't be called after a multi command monitor => results in
|
||||||
// monitor => results in faulty return values e.g. multi().monitor().set('foo', 'bar').get('foo')
|
// faulty return values e.g. multi().monitor().set('foo',
|
||||||
// returns ['OK, 'OK', 'monitor reply'] instead of ['OK', 'OK', 'bar']
|
// 'bar').get('foo') returns ['OK, 'OK', 'monitor reply'] instead of
|
||||||
// quit => ends the connection before the exec
|
// ['OK', 'OK', 'bar'] quit => ends the connection before the exec
|
||||||
// client reply skip|off => results in weird return values. Not sure what exactly happens
|
// client reply skip|off => results in weird return values. Not sure
|
||||||
// subscribe => enters subscribe mode and this does not work in combination with exec (the same for psubscribe, unsubscribe...)
|
// what exactly happens subscribe => enters subscribe mode and this
|
||||||
|
// does not work in combination with exec (the same for psubscribe,
|
||||||
|
// unsubscribe...)
|
||||||
//
|
//
|
||||||
|
|
||||||
// Make sure sendCommand is not called
|
// Make sure sendCommand is not called
|
||||||
@@ -514,7 +527,10 @@ describe('The \'multi\' method', () => {
|
|||||||
return multi.exec().then((res) => {
|
return multi.exec().then((res) => {
|
||||||
res[2] = res[2].substr(0, 10)
|
res[2] = res[2].substr(0, 10)
|
||||||
assert.strictEqual(client.selectedDb, 5)
|
assert.strictEqual(client.selectedDb, 5)
|
||||||
assert.deepStrictEqual(client.serverInfo.keyspace.db5, { avg_ttl: 0, expires: 0, keys: 1 })
|
assert.deepStrictEqual(
|
||||||
|
client.serverInfo.keyspace.db5,
|
||||||
|
{ avg_ttl: 0, expires: 0, keys: 1 }
|
||||||
|
)
|
||||||
assert.deepStrictEqual(res, ['OK', 'OK', '# Server\r\n', 'bar'])
|
assert.deepStrictEqual(res, ['OK', 'OK', '# Server\r\n', 'bar'])
|
||||||
return client.flushdb()
|
return client.flushdb()
|
||||||
})
|
})
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const fork = require('child_process').fork
|
const { fork } = require('child_process')
|
||||||
const Errors = require('redis-errors')
|
const Errors = require('redis-errors')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
let client
|
let client
|
||||||
|
|
||||||
describe('The nodeRedis client', () => {
|
describe('The nodeRedis client', () => {
|
||||||
@@ -41,7 +42,7 @@ describe('The nodeRedis client', () => {
|
|||||||
|
|
||||||
it('reset the parser while reconnecting (See #1190)', (done) => {
|
it('reset the parser while reconnecting (See #1190)', (done) => {
|
||||||
const client = redis.createClient({
|
const client = redis.createClient({
|
||||||
retryStrategy () {
|
retryStrategy() {
|
||||||
return 5
|
return 5
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -113,10 +114,9 @@ describe('The nodeRedis client', () => {
|
|||||||
assert.strictEqual(client2.selectedDb, 2)
|
assert.strictEqual(client2.selectedDb, 2)
|
||||||
assert(client.connected)
|
assert(client.connected)
|
||||||
assert(!client2.connected)
|
assert(!client2.connected)
|
||||||
for (const elem in client._options) {
|
const keys = Object.keys(client._options)
|
||||||
if (client._options.hasOwnProperty(elem)) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
assert.strictEqual(client2._options[elem], client._options[elem])
|
assert.strictEqual(client2._options[keys[i]], client._options[keys[i]])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
client2.on('error', (err) => {
|
client2.on('error', (err) => {
|
||||||
assert.strictEqual(err.message, 'Connection forcefully ended and command aborted.')
|
assert.strictEqual(err.message, 'Connection forcefully ended and command aborted.')
|
||||||
@@ -140,11 +140,10 @@ describe('The nodeRedis client', () => {
|
|||||||
assert.strictEqual(client._options.noReadyCheck, undefined)
|
assert.strictEqual(client._options.noReadyCheck, undefined)
|
||||||
assert.strictEqual(client2._options.noReadyCheck, true)
|
assert.strictEqual(client2._options.noReadyCheck, true)
|
||||||
assert.notDeepEqual(client._options, client2._options)
|
assert.notDeepEqual(client._options, client2._options)
|
||||||
for (const elem in client._options) {
|
const keys = Object.keys(client._options)
|
||||||
if (client._options.hasOwnProperty(elem)) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
if (elem !== 'noReadyCheck') {
|
if (keys[i] !== 'noReadyCheck') {
|
||||||
assert.strictEqual(client2._options[elem], client._options[elem])
|
assert.strictEqual(client2._options[keys[i]], client._options[keys[i]])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client2.on('ready', () => {
|
client2.on('ready', () => {
|
||||||
@@ -190,12 +189,14 @@ describe('The nodeRedis client', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('using multi with sendCommand should work as individual command instead of using the internal multi', () => {
|
it('using multi with sendCommand should work as individual command instead of using the internal multi', () => {
|
||||||
// This is necessary to keep backwards compatibility and it is the only way to handle multi as you want in nodeRedis
|
// This is necessary to keep backwards compatibility and it is the
|
||||||
|
// only way to handle multi as you want in nodeRedis
|
||||||
client.sendCommand('multi')
|
client.sendCommand('multi')
|
||||||
client.sendCommand('set', ['foo', 'bar']).then(helper.isString('QUEUED'))
|
client.sendCommand('set', ['foo', 'bar']).then(helper.isString('QUEUED'))
|
||||||
client.get('foo')
|
client.get('foo')
|
||||||
// exec is not manipulated if not fired by the individual multi command
|
// exec is not manipulated if not fired by the individual multi
|
||||||
// As the multi command is handled individually by the user he also has to handle the return value
|
// command As the multi command is handled individually by the user
|
||||||
|
// he also has to handle the return value
|
||||||
return client.exec().then(helper.isDeepEqual(['OK', 'bar']))
|
return client.exec().then(helper.isDeepEqual(['OK', 'bar']))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -205,7 +206,8 @@ describe('The nodeRedis client', () => {
|
|||||||
client.sendCommand('set', args).then(helper.isString('QUEUED'))
|
client.sendCommand('set', args).then(helper.isString('QUEUED'))
|
||||||
assert.deepStrictEqual(args, ['test', 'bla']) // Check args manipulation
|
assert.deepStrictEqual(args, ['test', 'bla']) // Check args manipulation
|
||||||
client.get('test').then(helper.isString('QUEUED'))
|
client.get('test').then(helper.isString('QUEUED'))
|
||||||
// As the multi command is handled individually by the user he also has to handle the return value
|
// As the multi command is handled individually by the user he also
|
||||||
|
// has to handle the return value
|
||||||
return client.exec().then(helper.isDeepEqual(['OK', 'bla']))
|
return client.exec().then(helper.isDeepEqual(['OK', 'bla']))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -245,13 +247,15 @@ describe('The nodeRedis client', () => {
|
|||||||
client.sendCommand('set', args).then(helper.isString('QUEUED'))
|
client.sendCommand('set', args).then(helper.isString('QUEUED'))
|
||||||
assert.deepStrictEqual(args, ['test', 'bla']) // Check args manipulation
|
assert.deepStrictEqual(args, ['test', 'bla']) // Check args manipulation
|
||||||
client.get('test').then(helper.isString('QUEUED'))
|
client.get('test').then(helper.isString('QUEUED'))
|
||||||
// As the multi command is handled individually by the user he also has to handle the return value
|
// As the multi command is handled individually by the user he also
|
||||||
|
// has to handle the return value
|
||||||
return client.exec().then(helper.isDeepEqual(['OK', 'bla']))
|
return client.exec().then(helper.isDeepEqual(['OK', 'bla']))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('the args array may contain a arbitrary number of arguments', () => {
|
it('the args array may contain a arbitrary number of arguments', () => {
|
||||||
client.sendCommand('mset', ['foo', 1, 'bar', 2, 'baz', 3]).then(helper.isString('OK'))
|
client.sendCommand('mset', ['foo', 1, 'bar', 2, 'baz', 3]).then(helper.isString('OK'))
|
||||||
// As the multi command is handled individually by the user he also has to handle the return value
|
// As the multi command is handled individually by the user he also
|
||||||
|
// has to handle the return value
|
||||||
return client.mget(['foo', 'bar', 'baz']).then(helper.isDeepEqual(['1', '2', '3']))
|
return client.mget(['foo', 'bar', 'baz']).then(helper.isDeepEqual(['1', '2', '3']))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -340,8 +344,8 @@ describe('The nodeRedis client', () => {
|
|||||||
|
|
||||||
describe('when redis closes unexpectedly', () => {
|
describe('when redis closes unexpectedly', () => {
|
||||||
it('reconnects and can retrieve the pre-existing data', (done) => {
|
it('reconnects and can retrieve the pre-existing data', (done) => {
|
||||||
client.on('reconnecting', function onRecon (params) {
|
client.on('reconnecting', function onRecon(params) {
|
||||||
client.on('connect', function onConnect () {
|
client.on('connect', function onConnect() {
|
||||||
const end = helper.callFuncAfter(() => {
|
const end = helper.callFuncAfter(() => {
|
||||||
client.removeListener('connect', onConnect)
|
client.removeListener('connect', onConnect)
|
||||||
client.removeListener('reconnecting', onRecon)
|
client.removeListener('reconnecting', onRecon)
|
||||||
@@ -365,8 +369,8 @@ describe('The nodeRedis client', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('reconnects properly when monitoring', (done) => {
|
it('reconnects properly when monitoring', (done) => {
|
||||||
client.on('reconnecting', function onRecon (params) {
|
client.on('reconnecting', function onRecon(params) {
|
||||||
client.on('ready', function onReady () {
|
client.on('ready', function onReady() {
|
||||||
assert.strictEqual(client._monitoring, true, 'monitoring after reconnect')
|
assert.strictEqual(client._monitoring, true, 'monitoring after reconnect')
|
||||||
client.removeListener('ready', onReady)
|
client.removeListener('ready', onReady)
|
||||||
client.removeListener('reconnecting', onRecon)
|
client.removeListener('reconnecting', onRecon)
|
||||||
@@ -502,7 +506,8 @@ describe('The nodeRedis client', () => {
|
|||||||
assert.strictEqual(err.message, 'Protocol error, got "a" as reply type byte. Please report this.')
|
assert.strictEqual(err.message, 'Protocol error, got "a" as reply type byte. Please report this.')
|
||||||
assert.strictEqual(err, error)
|
assert.strictEqual(err, error)
|
||||||
assert(err instanceof redis.ParserError)
|
assert(err instanceof redis.ParserError)
|
||||||
// After the hard failure work properly again. The set should have been processed properly too
|
// After the hard failure work properly again. The set should have
|
||||||
|
// been processed properly too
|
||||||
client.get('foo').then(helper.isString('bar')).then(done)
|
client.get('foo').then(helper.isString('bar')).then(done)
|
||||||
})
|
})
|
||||||
client.once('ready', () => {
|
client.once('ready', () => {
|
||||||
@@ -512,9 +517,9 @@ describe('The nodeRedis client', () => {
|
|||||||
assert(err instanceof redis.InterruptError)
|
assert(err instanceof redis.InterruptError)
|
||||||
error = err.origin
|
error = err.origin
|
||||||
})
|
})
|
||||||
// Make sure we call execute out of the reply.
|
// Make sure we call execute out of the reply. Ready is called in a
|
||||||
// Ready is called in a reply.
|
// reply. Fail the set answer. Has no corresponding command obj and
|
||||||
// Fail the set answer. Has no corresponding command obj and will therefore land in the error handler and set
|
// will therefore land in the error handler and set
|
||||||
process.nextTick(() => client._replyParser.execute(Buffer.from('a*1\r*1\r$1`zasd\r\na')))
|
process.nextTick(() => client._replyParser.execute(Buffer.from('a*1\r*1\r$1`zasd\r\na')))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -545,7 +550,7 @@ describe('The nodeRedis client', () => {
|
|||||||
|
|
||||||
it('enqueues operation and keep the queue while trying to reconnect', (done) => {
|
it('enqueues operation and keep the queue while trying to reconnect', (done) => {
|
||||||
client = redis.createClient(9999, null, {
|
client = redis.createClient(9999, null, {
|
||||||
retryStrategy (options) {
|
retryStrategy(options) {
|
||||||
if (options.attempt < 4) {
|
if (options.attempt < 4) {
|
||||||
return 50
|
return 50
|
||||||
}
|
}
|
||||||
@@ -587,6 +592,7 @@ describe('The nodeRedis client', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('flushes the command queue if connection is lost', (done) => {
|
it('flushes the command queue if connection is lost', (done) => {
|
||||||
|
const end = helper.callFuncAfter(done, 2)
|
||||||
client = redis.createClient()
|
client = redis.createClient()
|
||||||
|
|
||||||
client.once('ready', () => {
|
client.once('ready', () => {
|
||||||
@@ -607,8 +613,6 @@ describe('The nodeRedis client', () => {
|
|||||||
assert.strictEqual(client.commandQueue.length, 15)
|
assert.strictEqual(client.commandQueue.length, 15)
|
||||||
helper.killConnection(client)
|
helper.killConnection(client)
|
||||||
})
|
})
|
||||||
|
|
||||||
const end = helper.callFuncAfter(done, 2)
|
|
||||||
client.on('error', (err) => {
|
client.on('error', (err) => {
|
||||||
assert.strictEqual(err.code, 'ECONNREFUSED')
|
assert.strictEqual(err.code, 'ECONNREFUSED')
|
||||||
assert.strictEqual(err.errno, 'ECONNREFUSED')
|
assert.strictEqual(err.errno, 'ECONNREFUSED')
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('prefix key names', () => {
|
describe('prefix key names', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('publish/subscribe', () => {
|
describe('publish/subscribe', () => {
|
||||||
helper.allTests((ip, args) => {
|
helper.allTests((ip, args) => {
|
||||||
@@ -285,7 +286,7 @@ describe('publish/subscribe', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('unsubscribes, subscribes, unsubscribes... single and multiple entries mixed', (done) => {
|
it('unsubscribes, subscribes, unsubscribes... single and multiple entries mixed', (done) => {
|
||||||
function subscribe (channels) {
|
function subscribe(channels) {
|
||||||
sub.unsubscribe().then(helper.isNull)
|
sub.unsubscribe().then(helper.isNull)
|
||||||
sub.subscribe(channels).then(helper.isNull)
|
sub.subscribe(channels).then(helper.isNull)
|
||||||
}
|
}
|
||||||
@@ -313,7 +314,7 @@ describe('publish/subscribe', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('unsubscribes, subscribes, unsubscribes... single and multiple entries mixed. Without concrete channels', (done) => {
|
it('unsubscribes, subscribes, unsubscribes... single and multiple entries mixed. Without concrete channels', (done) => {
|
||||||
function subscribe (channels) {
|
function subscribe(channels) {
|
||||||
sub.unsubscribe(channels)
|
sub.unsubscribe(channels)
|
||||||
sub.unsubscribe(channels)
|
sub.unsubscribe(channels)
|
||||||
sub.subscribe(channels)
|
sub.subscribe(channels)
|
||||||
@@ -342,7 +343,7 @@ describe('publish/subscribe', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('unsubscribes, subscribes, unsubscribes... with pattern matching', (done) => {
|
it('unsubscribes, subscribes, unsubscribes... with pattern matching', (done) => {
|
||||||
function subscribe (channels, callback) {
|
function subscribe(channels, callback) {
|
||||||
sub.punsubscribe('prefix:*').then(helper.isNull)
|
sub.punsubscribe('prefix:*').then(helper.isNull)
|
||||||
sub.psubscribe(channels).then(callback)
|
sub.psubscribe(channels).then(callback)
|
||||||
}
|
}
|
||||||
@@ -461,7 +462,7 @@ describe('publish/subscribe', () => {
|
|||||||
const end = helper.callFuncAfter(done, 5)
|
const end = helper.callFuncAfter(done, 5)
|
||||||
const data = Array(10000).join('äüs^öéÉÉ`e')
|
const data = Array(10000).join('äüs^öéÉÉ`e')
|
||||||
sub.set('foo', data).then(() => {
|
sub.set('foo', data).then(() => {
|
||||||
sub.get('foo').then((res) => assert.strictEqual(typeof res, 'string'))
|
sub.get('foo').then(res => assert.strictEqual(typeof res, 'string'))
|
||||||
sub._stream.once('data', () => {
|
sub._stream.once('data', () => {
|
||||||
assert.strictEqual(sub._messageBuffers, false)
|
assert.strictEqual(sub._messageBuffers, false)
|
||||||
assert.strictEqual(sub.shouldBuffer, false)
|
assert.strictEqual(sub.shouldBuffer, false)
|
||||||
@@ -536,7 +537,7 @@ describe('publish/subscribe', () => {
|
|||||||
it('should not publish a message multiple times per command', (done) => {
|
it('should not publish a message multiple times per command', (done) => {
|
||||||
const published = {}
|
const published = {}
|
||||||
|
|
||||||
function subscribe (message) {
|
function subscribe(message) {
|
||||||
sub.removeAllListeners('subscribe')
|
sub.removeAllListeners('subscribe')
|
||||||
sub.removeAllListeners('message')
|
sub.removeAllListeners('message')
|
||||||
sub.removeAllListeners('unsubscribe')
|
sub.removeAllListeners('unsubscribe')
|
||||||
@@ -586,7 +587,8 @@ describe('publish/subscribe', () => {
|
|||||||
.psubscribe(['pattern:*'])
|
.psubscribe(['pattern:*'])
|
||||||
.punsubscribe('unknown*')
|
.punsubscribe('unknown*')
|
||||||
.punsubscribe(['pattern:*'])
|
.punsubscribe(['pattern:*'])
|
||||||
.exec().then(() => Promise.all([
|
.exec()
|
||||||
|
.then(() => Promise.all([
|
||||||
sub.client('kill', ['type', 'pubsub']),
|
sub.client('kill', ['type', 'pubsub']),
|
||||||
sub.psubscribe('*'),
|
sub.psubscribe('*'),
|
||||||
sub.punsubscribe('pa*'),
|
sub.punsubscribe('pa*'),
|
||||||
|
@@ -3,9 +3,10 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const redis = config.redis
|
|
||||||
|
|
||||||
// TODO: Fix redis process spawn on windows
|
const { redis } = config
|
||||||
|
|
||||||
|
// TODO: Fix redis process spawn on windows
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
describe('rename commands', () => {
|
describe('rename commands', () => {
|
||||||
before((done) => {
|
before((done) => {
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const Buffer = require('buffer').Buffer
|
const { Buffer } = require('buffer')
|
||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const config = require('./lib/config')
|
const config = require('./lib/config')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
|
|
||||||
describe('returnBuffers', () => {
|
describe('returnBuffers', () => {
|
||||||
helper.allTests((ip, basicArgs) => {
|
helper.allTests((ip, basicArgs) => {
|
||||||
@@ -64,7 +65,8 @@ describe('returnBuffers', () => {
|
|||||||
.hget(Buffer.from('hash key 2'), 'key 1')
|
.hget(Buffer.from('hash key 2'), 'key 1')
|
||||||
.hget('hash key 2', Buffer.from('key 2'))
|
.hget('hash key 2', Buffer.from('key 2'))
|
||||||
.hget('hash key 2', 'key 2')
|
.hget('hash key 2', 'key 2')
|
||||||
.exec().then((reply) => {
|
.exec()
|
||||||
|
.then((reply) => {
|
||||||
assert.strictEqual(4, reply.length)
|
assert.strictEqual(4, reply.length)
|
||||||
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect())
|
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect())
|
||||||
assert.strictEqual(true, Buffer.isBuffer(reply[1]))
|
assert.strictEqual(true, Buffer.isBuffer(reply[1]))
|
||||||
@@ -84,7 +86,8 @@ describe('returnBuffers', () => {
|
|||||||
.hget(Buffer.from('hash key 2'), 'key 1')
|
.hget(Buffer.from('hash key 2'), 'key 1')
|
||||||
.hget('hash key 2', Buffer.from('key 2'))
|
.hget('hash key 2', Buffer.from('key 2'))
|
||||||
.hget('hash key 2', 'key 2')
|
.hget('hash key 2', 'key 2')
|
||||||
.exec().then((reply) => {
|
.exec()
|
||||||
|
.then((reply) => {
|
||||||
assert.strictEqual(4, reply.length)
|
assert.strictEqual(4, reply.length)
|
||||||
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect())
|
assert.strictEqual('<Buffer 76 61 6c 20 31>', reply[0].inspect())
|
||||||
assert.strictEqual(true, Buffer.isBuffer(reply[1]))
|
assert.strictEqual(true, Buffer.isBuffer(reply[1]))
|
||||||
|
@@ -5,13 +5,14 @@ const config = require('./lib/config')
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const helper = require('./helper')
|
const helper = require('./helper')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const redis = config.redis
|
|
||||||
|
const { redis } = config
|
||||||
const utils = require('../lib/utils')
|
const utils = require('../lib/utils')
|
||||||
|
|
||||||
const tlsOptions = {
|
const tlsOptions = {
|
||||||
servername: 'redis.js.org',
|
servername: 'redis.js.org',
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
ca: [ String(fs.readFileSync(path.resolve(__dirname, './conf/redis.js.org.cert'))) ]
|
ca: [String(fs.readFileSync(path.resolve(__dirname, './conf/redis.js.org.cert')))]
|
||||||
}
|
}
|
||||||
|
|
||||||
const tlsPort = 6380
|
const tlsPort = 6380
|
||||||
@@ -109,7 +110,7 @@ describe('TLS connection tests', () => {
|
|||||||
it('fails to connect because the cert is not correct', function () {
|
it('fails to connect because the cert is not correct', function () {
|
||||||
if (skip) this.skip()
|
if (skip) this.skip()
|
||||||
const faultyCert = utils.clone(tlsOptions)
|
const faultyCert = utils.clone(tlsOptions)
|
||||||
faultyCert.ca = [ String(fs.readFileSync(path.resolve(__dirname, './conf/faulty.cert'))) ]
|
faultyCert.ca = [String(fs.readFileSync(path.resolve(__dirname, './conf/faulty.cert')))]
|
||||||
client = redis.createClient({
|
client = redis.createClient({
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
connectTimeout: 1000,
|
connectTimeout: 1000,
|
||||||
|
@@ -9,7 +9,7 @@ describe('createClient options', () => {
|
|||||||
it('pass the options in the second parameter after a port', () => {
|
it('pass the options in the second parameter after a port', () => {
|
||||||
const options = unifyOptions(1234, {
|
const options = unifyOptions(1234, {
|
||||||
option1: true,
|
option1: true,
|
||||||
option2 () {}
|
option2() {}
|
||||||
})
|
})
|
||||||
assert.strictEqual(Object.keys(options).length, 4)
|
assert.strictEqual(Object.keys(options).length, 4)
|
||||||
assert(options.option1)
|
assert(options.option1)
|
||||||
@@ -21,7 +21,7 @@ describe('createClient options', () => {
|
|||||||
it('pass the options in the third parameter after a port and host being set to null', () => {
|
it('pass the options in the third parameter after a port and host being set to null', () => {
|
||||||
const options = unifyOptions(1234, null, {
|
const options = unifyOptions(1234, null, {
|
||||||
option1: true,
|
option1: true,
|
||||||
option2 () {}
|
option2() {}
|
||||||
})
|
})
|
||||||
assert.strictEqual(Object.keys(options).length, 4)
|
assert.strictEqual(Object.keys(options).length, 4)
|
||||||
assert(options.option1)
|
assert(options.option1)
|
||||||
@@ -33,7 +33,7 @@ describe('createClient options', () => {
|
|||||||
it('pass the options in the third parameter after a port and host being set to undefined', () => {
|
it('pass the options in the third parameter after a port and host being set to undefined', () => {
|
||||||
const options = unifyOptions(1234, undefined, {
|
const options = unifyOptions(1234, undefined, {
|
||||||
option1: true,
|
option1: true,
|
||||||
option2 () {}
|
option2() {}
|
||||||
})
|
})
|
||||||
assert.strictEqual(Object.keys(options).length, 4)
|
assert.strictEqual(Object.keys(options).length, 4)
|
||||||
assert(options.option1)
|
assert(options.option1)
|
||||||
@@ -45,7 +45,7 @@ describe('createClient options', () => {
|
|||||||
it('pass the options in the third parameter after a port and host', () => {
|
it('pass the options in the third parameter after a port and host', () => {
|
||||||
const options = unifyOptions('1234', 'localhost', {
|
const options = unifyOptions('1234', 'localhost', {
|
||||||
option1: true,
|
option1: true,
|
||||||
option2 () {}
|
option2() {}
|
||||||
})
|
})
|
||||||
assert.strictEqual(Object.keys(options).length, 4)
|
assert.strictEqual(Object.keys(options).length, 4)
|
||||||
assert(options.option1)
|
assert(options.option1)
|
||||||
@@ -68,7 +68,7 @@ describe('createClient options', () => {
|
|||||||
it('pass the options in the second parameter after a port', () => {
|
it('pass the options in the second parameter after a port', () => {
|
||||||
const options = unifyOptions('/tmp/redis.sock', {
|
const options = unifyOptions('/tmp/redis.sock', {
|
||||||
option1: true,
|
option1: true,
|
||||||
option2 () {},
|
option2() {},
|
||||||
option3: [1, 2, 3]
|
option3: [1, 2, 3]
|
||||||
})
|
})
|
||||||
assert.strictEqual(Object.keys(options).length, 4)
|
assert.strictEqual(Object.keys(options).length, 4)
|
||||||
@@ -81,7 +81,7 @@ describe('createClient options', () => {
|
|||||||
it('pass the options in the third parameter after a port and host being set to null', () => {
|
it('pass the options in the third parameter after a port and host being set to null', () => {
|
||||||
const options = unifyOptions('/tmp/redis.sock', null, {
|
const options = unifyOptions('/tmp/redis.sock', null, {
|
||||||
option1: true,
|
option1: true,
|
||||||
option2 () {}
|
option2() {}
|
||||||
})
|
})
|
||||||
assert.strictEqual(Object.keys(options).length, 3)
|
assert.strictEqual(Object.keys(options).length, 3)
|
||||||
assert(options.option1)
|
assert(options.option1)
|
||||||
@@ -120,7 +120,8 @@ describe('createClient options', () => {
|
|||||||
option: [1, 2, 3]
|
option: [1, 2, 3]
|
||||||
})
|
})
|
||||||
unhookIntercept()
|
unhookIntercept()
|
||||||
assert.strictEqual(text,
|
assert.strictEqual(
|
||||||
|
text,
|
||||||
'nodeRedis: WARNING: You passed the db option twice!\n' +
|
'nodeRedis: WARNING: You passed the db option twice!\n' +
|
||||||
'nodeRedis: WARNING: You passed the port option twice!\n' +
|
'nodeRedis: WARNING: You passed the port option twice!\n' +
|
||||||
'nodeRedis: WARNING: You passed the password option twice!\n'
|
'nodeRedis: WARNING: You passed the password option twice!\n'
|
||||||
|
@@ -6,10 +6,10 @@ const intercept = require('intercept-stdout')
|
|||||||
const utils = require('../lib/utils')
|
const utils = require('../lib/utils')
|
||||||
|
|
||||||
describe('utils.js', () => {
|
describe('utils.js', () => {
|
||||||
describe('print helper', function () {
|
describe('print helper', () => {
|
||||||
it('callback with reply', function () {
|
it('callback with reply', () => {
|
||||||
var text = ''
|
let text = ''
|
||||||
const unhookIntercept = intercept(function (data) {
|
const unhookIntercept = intercept((data) => {
|
||||||
text += data
|
text += data
|
||||||
return ''
|
return ''
|
||||||
})
|
})
|
||||||
@@ -18,9 +18,9 @@ describe('utils.js', () => {
|
|||||||
assert.strictEqual(text, 'Reply: abc\n')
|
assert.strictEqual(text, 'Reply: abc\n')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('callback with error', function () {
|
it('callback with error', () => {
|
||||||
var text = ''
|
let text = ''
|
||||||
const unhookIntercept = intercept(function (data) {
|
const unhookIntercept = intercept((data) => {
|
||||||
text += data
|
text += data
|
||||||
return ''
|
return ''
|
||||||
})
|
})
|
||||||
@@ -37,7 +37,7 @@ describe('utils.js', () => {
|
|||||||
'i\'m special': true
|
'i\'m special': true
|
||||||
}],
|
}],
|
||||||
number: 5,
|
number: 5,
|
||||||
fn: function noop () {}
|
fn: function noop() {}
|
||||||
}
|
}
|
||||||
const clone = utils.clone(obj)
|
const clone = utils.clone(obj)
|
||||||
assert.deepStrictEqual(clone, obj)
|
assert.deepStrictEqual(clone, obj)
|
||||||
@@ -73,7 +73,7 @@ describe('utils.js', () => {
|
|||||||
}
|
}
|
||||||
const createCommandObj = function () {
|
const createCommandObj = function () {
|
||||||
return {
|
return {
|
||||||
callback (err, res) {
|
callback(err, res) {
|
||||||
if (err) errCount++
|
if (err) errCount++
|
||||||
else resCount++
|
else resCount++
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user