Skip to content

Support npm Node Redis v4 #337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 98 additions & 57 deletions lib/connect-redis.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,30 @@ module.exports = function (session) {
get(sid, cb = noop, showTombs = false) {
let key = this.prefix + sid

this.client.get(key, (err, data) => {
if (err) return cb(err)
if (!data) return cb()
if (data === TOMBSTONE) return cb(null, showTombs ? data : undefined)
this.client
.get(key)
.then((data) => {
if (!data) {
cb()
return
}
if (data === TOMBSTONE) {
cb(null, showTombs ? data : undefined)
return
}

let result
try {
result = this.serializer.parse(data)
} catch (err) {
return cb(err)
}
return cb(null, result)
})
let result
try {
result = this.serializer.parse(data)
} catch (err) {
cb(err)
return
}
cb(null, result)
})
.catch((err) => {
cb(err)
})
}

set(sid, sess, cb = noop) {
Expand All @@ -55,7 +66,7 @@ module.exports = function (session) {
} else if (oldSess && oldSess.lastModified !== sess.lastModified) {
sess = mergeDeep(oldSess, sess)
}
let args = [this.prefix + sid]
let args = ['SET', this.prefix + sid]
let value
sess.lastModified = Date.now()
try {
Expand All @@ -73,7 +84,14 @@ module.exports = function (session) {
}

if (ttl > 0) {
this.client.set(args, cb)
this.client
.sendCommand(args)
.then((r) => {
cb(null, r)
})
.catch((err) => {
cb(err)
})
} else {
// If the resulting TTL is negative we can delete / destroy the key
this.destroy(sid, cb)
Expand All @@ -86,24 +104,40 @@ module.exports = function (session) {
touch(sid, sess, cb = noop) {
if (this.disableTouch || this.disableTTL) return cb()
let key = this.prefix + sid
this.client.expire(key, this._getTTL(sess), (err, ret) => {
if (err) return cb(err)
if (ret !== 1) return cb(null, 'EXPIRED')
cb(null, 'OK')
})
this.client
.expire(key, this._getTTL(sess))
.then((ret) => {
if (ret !== 1) return cb(null, 'EXPIRED')
return cb(null, 'OK')
})
.catch((err) => {
return cb(err)
})
}

destroy(sid, cb = noop) {
let key = this.prefix + sid
this.client.set([key, TOMBSTONE, 'EX', 300], (err) => {
cb(err, 1)
})
this.client
.sendCommand(['SET', key, TOMBSTONE, 'EX', '300'])
.then((r) => {
cb(r)
})
.catch((err) => {
cb(err, 1)
})
}

clear(cb = noop) {
this._getAllKeys((err, keys) => {
if (err) return cb(err)
this.client.del(keys, cb)
this.client
.del(keys)
.then((r) => {
cb(null, r)
})
.catch((err) => {
cb(err)
})
})
}

Expand Down Expand Up @@ -131,23 +165,26 @@ module.exports = function (session) {
if (err) return cb(err)
if (keys.length === 0) return cb(null, [])

this.client.mget(keys, (err, sessions) => {
if (err) return cb(err)

let result
try {
result = sessions.reduce((accum, data, index) => {
if (!data || data === TOMBSTONE) return accum
data = this.serializer.parse(data)
data.id = keys[index].substr(prefixLen)
accum.push(data)
return accum
}, [])
} catch (e) {
err = e
}
return cb(err, result)
})
this.client
.mget(keys)
.then((sessions) => {
let result
try {
result = sessions.reduce((accum, data, index) => {
if (!data || data === TOMBSTONE) return accum
data = this.serializer.parse(data)
data.id = keys[index].substr(prefixLen)
accum.push(data)
return accum
}, [])
} catch (e) {
err = e
}
return cb(err, result)
})
.catch((err) => {
return cb(err)
})
})
}

Expand All @@ -159,31 +196,35 @@ module.exports = function (session) {
} else {
ttl = this.ttl
}
return ttl
// v4 cast to string
return '' + ttl
}

_getAllKeys(cb = noop) {
let pattern = this.prefix + '*'
this._scanKeys({}, 0, pattern, this.scanCount, cb)
this._scanKeys([], '0', pattern, this.scanCount, cb)
}

_scanKeys(keys = {}, cursor, pattern, count, cb = noop) {
let args = [cursor, 'match', pattern, 'count', count]
this.client.scan(args, (err, data) => {
if (err) return cb(err)

let [nextCursorId, scanKeys] = data
for (let key of scanKeys) {
keys[key] = true
}
_scanKeys(keys = [], cursor, pattern, count, cb = noop) {
this.client
.scan(cursor, {
'MATCH': pattern,
'COUNT': count
})
.then((data) => {
keys = keys.concat(data.keys);

// This can be a string or a number. We check both.
if (Number(nextCursorId) !== 0) {
return this._scanKeys(keys, nextCursorId, pattern, count, cb)
}
// This can be a string or a number. We check both.
let nextCursorId = Number(data.cursor);
if (nextCursorId !== 0) {
return this._scanKeys(keys, nextCursorId, pattern, count, cb)
}

cb(null, Object.keys(keys))
})
cb(null, keys)
})
.catch((err) => {
return cb(err)
})
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"mockdate": "^2.0.5",
"nyc": "^15.0.1",
"prettier": "^2.0.5",
"redis": "^3.1.2",
"redis": "^4.0.0",
"redis-mock": "^0.56.3"
},
"engines": {
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const session = require('express-session')

let RedisStore = require('connect-redis')(session)
let redisClient = redis.createClient()
redisClient.connect()

app.use(
session({
Expand Down
6 changes: 4 additions & 2 deletions test/connect-redis-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ test('defaults', async (t) => {
t.throws(() => new RedisStore(), 'client is required')

var client = redis.createClient(redisSrv.port, 'localhost')
await client.connect();
var store = new RedisStore({ client })

t.equal(store.client, client, 'stores client')
Expand All @@ -34,14 +35,15 @@ test('defaults', async (t) => {
t.equal(store.serializer, JSON, 'defaults to JSON serialization')
t.equal(store.disableTouch, false, 'defaults to having `touch` enabled')
t.equal(store.disableTTL, false, 'defaults to having `ttl` enabled')
client.end(false)
client.disconnect()
})

test('node_redis', async (t) => {
var client = redis.createClient(redisSrv.port, 'localhost')
await client.connect();
var store = new RedisStore({ client })
await lifecycleTest(store, t)
client.end(false)
client.disconnect()
})

test('ioredis', async (t) => {
Expand Down