Skip to content
Merged
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
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,68 @@ fastify.register(fastifyRedis, { client: redis })
// ...
```

## Registering multiple Redis client instances

By using the `namespace` option you can register multiple Redis client instances.

```js
const fastify = require('fastify')
const redis = require('redis').createClient({ host: 'localhost', port: 6379 })

fastify
.register(require('fastify-redis'), {
host: '127.0.0.1',
port: 6380,
namespace: 'hello'
})
.register(require('fastify-redis'), {
client: redis,
namespace: 'world'
})

// Here we will use the `hello` named instance
fastify.get('/hello', (req, reply) => {
const { redis } = fastify

redis.hello.get(req.query.key, (err, val) => {
reply.send(err || val)
})
})

fastify.post('/hello', (req, reply) => {
const { redis } = fastify

redis['hello'].set(req.body.key, req.body.value, (err) => {
reply.send(err || { status: 'ok' })
})
})

// Here we will use the `world` named instance
fastify.get('/world', (req, reply) => {
const { redis } = fastify

redis['world'].get(req.query.key, (err, val) => {
reply.send(err || val)
})
})

fastify.post('/world', (req, reply) => {
const { redis } = fastify

redis.world.set(req.body.key, req.body.value, (err) => {
reply.send(err || { status: 'ok' })
})
})

fastify.listen(3000, function (err) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})

```

## Acknowledgements

This project is kindly sponsored by:
Expand Down
52 changes: 43 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,52 @@ const fp = require('fastify-plugin')
const Redis = require('ioredis')

function fastifyRedis (fastify, options, next) {
var client = options.client || null
const namespace = options.namespace
delete options.namespace

if (!client) {
try {
client = new Redis(options)
} catch (err) {
return next(err)
let client = options.client || null

if (namespace) {
if (!fastify.redis) {
fastify.decorate('redis', {})
}
fastify.addHook('onClose', close)
}

fastify.decorate('redis', client)
if (fastify.redis[namespace]) {
return next(new Error(`Redis '${namespace}' instance namespace has already been registered`))
}

const closeNamedInstance = (fastify, done) => {
fastify.redis[namespace].quit(done)
}

if (!client) {
try {
client = new Redis(options)
} catch (err) {
return next(err)
}

fastify.addHook('onClose', closeNamedInstance)
}

fastify.redis[namespace] = client
} else {
if (fastify.redis) {
next(new Error('fastify-redis has already been registered'))
} else {
if (!client) {
try {
client = new Redis(options)
} catch (err) {
return next(err)
}

fastify.addHook('onClose', close)
}

fastify.decorate('redis', client)
}
}

next()
}
Expand Down
177 changes: 162 additions & 15 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ const test = t.test
const Fastify = require('fastify')
const fastifyRedis = require('./index')

t.beforeEach(done => {
t.beforeEach((done) => {
const fastify = Fastify()

fastify.register(fastifyRedis, {
host: '127.0.0.1'
})

fastify.ready(err => {
fastify.ready((err) => {
t.error(err)

fastify.redis.flushall(() => {
Expand All @@ -22,33 +22,33 @@ t.beforeEach(done => {
})
})

test('fastify.redis should exist', t => {
test('fastify.redis should exist', (t) => {
t.plan(2)
const fastify = Fastify()
fastify.register(fastifyRedis, {
host: '127.0.0.1'
})

fastify.ready(err => {
fastify.ready((err) => {
t.error(err)
t.ok(fastify.redis)

fastify.close()
})
})

test('fastify.redis should be the redis client', t => {
test('fastify.redis should be the redis client', (t) => {
t.plan(4)
const fastify = Fastify()

fastify.register(fastifyRedis, {
host: '127.0.0.1'
})

fastify.ready(err => {
fastify.ready((err) => {
t.error(err)

fastify.redis.set('key', 'value', err => {
fastify.redis.set('key', 'value', (err) => {
t.error(err)
fastify.redis.get('key', (err, val) => {
t.error(err)
Expand All @@ -60,41 +60,84 @@ test('fastify.redis should be the redis client', t => {
})
})

test('promises support', t => {
test('fastify.redis.test namespace should exist', (t) => {
t.plan(3)

const fastify = Fastify()
fastify.register(fastifyRedis, {
host: '127.0.0.1',
namespace: 'test'
})

fastify.ready((err) => {
t.error(err)
t.ok(fastify.redis)
t.ok(fastify.redis.test)

fastify.close()
})
})

test('fastify.redis.test should be the redis client', (t) => {
t.plan(4)
const fastify = Fastify()

fastify.register(fastifyRedis, {
host: '127.0.0.1',
namespace: 'test'
})

fastify.ready((err) => {
t.error(err)

fastify.redis.test.set('key_namespace', 'value_namespace', (err) => {
t.error(err)
fastify.redis.test.get('key_namespace', (err, val) => {
t.error(err)
t.equal(val, 'value_namespace')

fastify.close()
})
})
})
})

test('promises support', (t) => {
t.plan(2)
const fastify = Fastify()

fastify.register(fastifyRedis, {
host: '127.0.0.1'
})

fastify.ready(err => {
fastify.ready((err) => {
t.error(err)

fastify.redis.set('key', 'value')
fastify.redis
.set('key', 'value')
.then(() => {
return fastify.redis.get('key')
})
.then(val => {
.then((val) => {
t.equal(val, 'value')
fastify.close()
})
.catch(err => t.fail(err))
.catch((err) => t.fail(err))
})
})

test('custom client', t => {
test('custom client', (t) => {
t.plan(7)
const fastify = Fastify()
const redis = require('redis').createClient({ host: 'localhost', port: 6379 })

fastify.register(fastifyRedis, { client: redis })

fastify.ready(err => {
fastify.ready((err) => {
t.error(err)
t.is(fastify.redis, redis)

fastify.redis.set('key', 'value', err => {
fastify.redis.set('key', 'value', (err) => {
t.error(err)
fastify.redis.get('key', (err, val) => {
t.error(err)
Expand All @@ -110,3 +153,107 @@ test('custom client', t => {
})
})
})

test('custom client inside a namespace', (t) => {
t.plan(7)
const fastify = Fastify()
const redis = require('redis').createClient({ host: 'localhost', port: 6379 })

fastify.register(fastifyRedis, {
namespace: 'test',
client: redis
})

fastify.ready((err) => {
t.error(err)
t.is(fastify.redis.test, redis)

fastify.redis.test.set('key', 'value', (err) => {
t.error(err)
fastify.redis.test.get('key', (err, val) => {
t.error(err)
t.equal(val, 'value')

fastify.close(function (err) {
t.error(err)
fastify.redis.test.quit(function (err) {
t.error(err)
})
})
})
})
})
})

test('fastify.redis.test should throw with duplicate connection namespaces', (t) => {
t.plan(1)

const namespace = 'test'

const fastify = Fastify()
t.teardown(() => fastify.close())

fastify
.register(fastifyRedis, {
host: '127.0.0.1',
namespace
})
.register(fastifyRedis, {
host: '127.0.0.1',
namespace
})

fastify.ready((err) => {
t.is(err.message, `Redis '${namespace}' instance namespace has already been registered`)
})
})

test('Should throw when trying to register multiple instances without giving a namespace', (t) => {
t.plan(1)

const fastify = Fastify()
t.teardown(() => fastify.close())

fastify
.register(fastifyRedis, {
host: '127.0.0.1'
})
.register(fastifyRedis, {
host: '127.0.0.1'
})

fastify.ready((err) => {
t.is(err.message, 'fastify-redis has already been registered')
})
})

test('Should not throw within different contexts', (t) => {
t.plan(1)

const fastify = Fastify()
t.teardown(() => fastify.close())

fastify.register(function (instance, options, next) {
instance.register(fastifyRedis, {
host: '127.0.0.1'
})
next()
})

fastify.register(function (instance, options, next) {
instance
.register(fastifyRedis, {
host: '127.0.0.1',
namespace: 'test1'
})
.register(fastifyRedis, {
host: '127.0.0.1',
namespace: 'test2'
})
next()
})

fastify.ready((error) => {
t.is(error, null)
})
})