Skip to content

Commit

Permalink
Merge pull request #217 from raveljs/feature/216
Browse files Browse the repository at this point in the history
Feature/216
  • Loading branch information
Ghnuberath authored Oct 20, 2017
2 parents 3ae008d + 72966d0 commit 226753b
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 15 deletions.
3 changes: 2 additions & 1 deletion documentation.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Ravel API
version: 0.22.2
version: 0.22.3
versions:
- 0.22.2
- 0.22.1
- 0.22.0
- 0.21.1
Expand Down
6 changes: 6 additions & 0 deletions lib/core/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ class Module {
* A reference to the internal Ravel key-value store connection (redis).
* See [node-redis](https://github.com/NodeRedis/node_redis) for more information.
*
* Since this is Ravel's own internal, long-lived connection, it is important that
* it not be blocked or suspended by calls to `exit`, `subcribe`, `psubscribe`,
* `unsubscribe` or `punsubscribe`.
*
* To retrieve an unrestricted connetion to Redis, use `kvstore.clone()`.
*
* @type Object
*/
get kvstore () {
Expand Down
6 changes: 6 additions & 0 deletions lib/core/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,12 @@ class Routes {
* A reference to the internal Ravel key-value store connection (redis).
* See [node-redis](https://github.com/NodeRedis/node_redis) for more information.
*
* Since this is Ravel's own internal, long-lived connection, it is important that
* it not be blocked or suspended by calls to `exit`, `subcribe`, `psubscribe`,
* `unsubscribe` or `punsubscribe`.
*
* To retrieve an unrestricted connetion to Redis, use `kvstore.clone()`.
*
* @type Object
*/
get kvstore () {
Expand Down
42 changes: 39 additions & 3 deletions lib/util/kvstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,28 @@ function retryStrategy (ravelInstance) {
}

/**
* Abstraction for redis-like data store.
* For disabling redis methods.
*
* @param {Object} client - Client to disable a method on.
* @param {string} fn - Name of the function to disable.
* @private
*/
function disable (client, fn) {
client[fn] = function () {
throw new ApplicationError.General(
`kvstore cannot use ${fn}(). Use kvstore.clone() to retrieve a fresh connection first.`);
};
}

/**
* Returns a fresh connection to Redis.
*
* @param {Ravel} ravelInstance - An instance of a Ravel app.
* @param {boolean} restrict - Iff true, disable `exit`, `subcribe`, `psubscribe`, `unsubscribe` and `punsubscribe`.
* @returns {Object} Returns a fresh connection to Redis.
* @private
*/
module.exports = function (ravelInstance) {
function createClient (ravelInstance, restrict = true) {
const client = redis.createClient(
ravelInstance.get('redis port'),
ravelInstance.get('redis host'),
Expand All @@ -55,7 +71,27 @@ module.exports = function (ravelInstance) {
clearInterval(redisKeepaliveInterval);
});

if (restrict) {
disable(client, 'quit');
disable(client, 'subscribe');
disable(client, 'psubscribe');
disable(client, 'unsubscribe');
disable(client, 'punsubscribe');
}

client.clone = function () {
return createClient(ravelInstance, false);
};

return client;
};
}

/**
* Abstraction for redis-like data store.
*
* @param {Ravel} ravelInstance - An instance of a Ravel app.
* @private
*/
module.exports = createClient;

module.exports.retryStrategy = retryStrategy;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ravel",
"version": "0.22.2",
"version": "0.22.3",
"author": "Sean McIntyre <[email protected]>",
"description": "Ravel Rapid Application Development Framework",
"engines": {
Expand Down
76 changes: 66 additions & 10 deletions test/util/test-kvstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const expect = chai.expect;
chai.use(require('chai-things'));
const mockery = require('mockery');

let Ravel, redisClientStub, redisMock, coreSymbols;
let Ravel, coreSymbols;

describe('Ravel', () => {
beforeEach((done) => {
Expand All @@ -15,20 +15,13 @@ describe('Ravel', () => {
warnOnReplace: false,
warnOnUnregistered: false
});
redisMock = {
createClient: () => {
redisClientStub = new (require('events').EventEmitter)(); // eslint-disable-line no-extra-parens
redisClientStub.auth = function () {};
redisClientStub.end = function () {};
return redisClientStub;
}
};
mockery.registerMock('redis', redisMock);
mockery.registerMock('redis', require('redis-mock'));
Ravel = new (require('../../lib/ravel'))();
coreSymbols = require('../../lib/core/symbols');
Ravel.log.setLevel(Ravel.log.NONE);
Ravel.set('redis port', 0);
Ravel.set('redis host', 'localhost');
Ravel.set('redis keepalive interval', 1000);

done();
});
Expand Down Expand Up @@ -102,5 +95,68 @@ describe('Ravel', () => {
done();
});
});

describe('kvstore', () => {
let kvstore, clone;
beforeEach(() => {
Ravel[coreSymbols.parametersLoaded] = true;
kvstore = require('../../lib/util/kvstore')(Ravel, true);
});

it('should prevent use of quit()', () => {
expect(() => {
kvstore.quit(() => {});
}).to.throw(Ravel.ApplicationError.General);
});

it('should prevent use of qsubscribeuit()', () => {
expect(() => {
kvstore.subscribe('chan');
}).to.throw(Ravel.ApplicationError.General);
});

it('should prevent use of psubscribe()', () => {
expect(() => {
kvstore.psubscribe('chan');
}).to.throw(Ravel.ApplicationError.General);
});

it('should prevent use of unsubscribe()', () => {
expect(() => {
kvstore.unsubscribe('chan');
}).to.throw(Ravel.ApplicationError.General);
});

it('should prevent use of punsubscribe()', () => {
expect(() => {
kvstore.punsubscribe('chan');
}).to.throw(Ravel.ApplicationError.General);
});

describe('#clone()', () => {
beforeEach(() => {
clone = kvstore.clone();
});
it('should support the use of quit()', () => {
expect(clone.quit).to.not.throw(Ravel.ApplicationError.General);
});

it('should support the use of qsubscribeuit()', () => {
expect(clone.subscribe).to.not.throw(Ravel.ApplicationError.General);
});

it('should support the use of psubscribe()', () => {
expect(clone.psubscribe).to.not.throw(Ravel.ApplicationError.General);
});

it('should support the use of unsubscribe()', () => {
expect(clone.unsubscribe).to.not.throw(Ravel.ApplicationError.General);
});

it('should support the use of punsubscribe()', () => {
expect(clone.punsubscribe).to.not.throw(Ravel.ApplicationError.General);
});
});
});
});
});

0 comments on commit 226753b

Please sign in to comment.