Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dabroek committed May 4, 2017
0 parents commit 36bb42e
Show file tree
Hide file tree
Showing 11 changed files with 3,704 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"presets": [
[
"es2015",
{
"modules": false
}
]
],
"plugins": [
"external-helpers",
],
"env": {
"test": {
"presets": [
"es2015"
],
"plugins": [
"transform-runtime"
]
}
}
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
.idea/
*.log
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
sudo: false
language: node_js
node_js:
- "node"
- "4.2"
services: redis-server
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2017 Matthijs Dabroek

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
175 changes: 175 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
[![build status](https://travis-ci.org/dabroek/node-cache-manager-ioredis.svg?branch=master)](https://travis-ci.org/dabroek/node-cache-manager-ioredis)
[![dependencies status](https://david-dm.org/dabroek/node-cache-manager-ioredis/status.svg)](https://david-dm.org/dabroek/node-cache-manager-ioredis)
[![npm version](https://badge.fury.io/js/cache-manager-ioredis.svg)](https://badge.fury.io/js/cache-manager-ioredis)
[![GitHub issues](https://img.shields.io/github/issues/dabroek/node-cache-manager-ioredis.svg)](https://github.com/dabroek/node-cache-manager-ioredis/issues)

IORedis store for node cache manager
==================================

Redis cache store for [node-cache-manager](https://github.com/BryanDonovan/node-cache-manager).

This package is a almost identical to [node-cache-manager-redis-store](https://github.com/dabroek/node-cache-manager-redis-store), but uses [`ioredis`](https://github.com/luin/ioredis) instead of [`node_redis`](https://github.com/NodeRedis/node_redis). It aims to provide **the most simple wrapper possible** by just passing the configuration to the underlying [`ioredis`](https://github.com/luin/ioredis) package.

Installation
------------

```sh
npm install cache-manager-ioredis --save
```
or
```sh
yarn add cache-manager-ioredis
```

Usage Examples
--------------

See examples below on how to implement the IORedis cache store.

### Single store

```js
var cacheManager = require('cache-manager');
var redisStore = require('cache-manager-ioredis');

var redisCache = cacheManager.caching({
store: redisStore,
host: 'localhost', // default value
port: 6379, // default value
password: 'XXXXX',
db: 0,
ttl: 600
});

// listen for redis connection error event
var redisClient = redisCache.store.getClient();

redisClient.on('error', (error) => {
// handle error here
console.log(error);
});

var ttl = 5;

redisCache.set('foo', 'bar', { ttl: ttl }, (err) => {
if (err) {
throw err;
}

redisCache.get('foo', (err, result) => {
console.log(result);
// >> 'bar'
redisCache.del('foo', (err) => {
});
});
});

function getUser(id, cb) {
setTimeout(() => {
console.log("Returning user from slow database.");
cb(null, { id: id, name: 'Bob' });
}, 100);
}

var userId = 123;
var key = `user_${userId}`;

// Note: ttl is optional in wrap()
redisCache.wrap(key, (cb) => {
getUser(userId, cb);
}, { ttl: ttl }, (err, user) => {
console.log(user);

// Second time fetches user from redisCache
redisCache
.wrap(key, () => getUser(userId))
.then(console.log)
.catch(err => {
// handle error
});
});
```

### Multi-store

```js
var cacheManager = require('cache-manager');
var redisStore = require('cache-manager-ioredis');

var redisCache = cacheManager.caching({ store: redisStore, db: 0, ttl: 600 });
var memoryCache = cacheManager.caching({ store: 'memory', max: 100, ttl: 60 });

var multiCache = cacheManager.multiCaching([memoryCache, redisCache]);

var userId2 = 456;
var key2 = `user_${userId2}`;

// Set value in all caches
multiCache.set('foo2', 'bar2', { ttl: ttl }, (err) => {
if (err) {
throw err;
}

// Fetches from highest priority cache that has the key
multiCache.get('foo2', (err, result) => {
console.log(result);

// Delete from all caches
multiCache.del('foo2');
});
});

// Note: ttl is optional in wrap
multiCache.wrap(key2, (cb) => {
getUser(userId2, cb);
}, (err, user) => {
console.log(user);

// Second time fetches user from memoryCache, since it's highest priority.
// If the data expires in the memory cache, the next fetch would pull it from
// the 'someOtherCache', and set the data in memory again.
multiCache.wrap(key2, (cb) => {
getUser(userId2, cb);
}, (err, user) => {
console.log(user);
});
});
```

### Use Clustering (eg Amazon elasticache)

```
var cacheManager = require('cache-manager');
var redisStore = require('cache-manager-ioredis');
// https://github.com/luin/ioredis#cluster
var redisCache = cacheManager.caching({
store: redisStore,
clusterConfig: {
nodes: [
{
port: 6380,
host: '127.0.0.1'
},
{
port: 6381,
host: '127.0.0.1'
}
],
options: {
maxRedirections: 16
}
}
});
```

Contribution
------------

Want to help improve this package? We take [pull requests](https://github.com/dabroek/node-cache-manager-ioredis/pulls).


License
-------

The `node-cache-manager-ioredis` is licensed under the MIT license.
132 changes: 132 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
'use strict';

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var Redis = _interopDefault(require('ioredis'));

var redisStore = function redisStore() {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}

var redisCache = null;

if (args.length > 0 && args[0].clusterConfig) {
var _args$0$clusterConfig = args[0].clusterConfig,
nodes = _args$0$clusterConfig.nodes,
options = _args$0$clusterConfig.options;


redisCache = new Redis.Cluster(nodes, options || {});
} else {
redisCache = new (Function.prototype.bind.apply(Redis, [null].concat(args)))();
}

var storeArgs = redisCache.options;

return {
name: 'redis',
getClient: function getClient() {
return redisCache;
},
set: function set(key, value, options, cb) {
return new Promise(function (resolve, reject) {
if (typeof options === 'function') {
cb = options;
options = {};
}
options = options || {};

if (!cb) {
cb = function cb(err, result) {
return err ? reject(err) : resolve(result);
};
}

var ttl = options.ttl || options.ttl === 0 ? options.ttl : storeArgs.ttl;
var val = JSON.stringify(value) || '"undefined"';

if (ttl) {
redisCache.setex(key, ttl, val, handleResponse(cb));
} else {
redisCache.set(key, val, handleResponse(cb));
}
});
},
get: function get(key, options, cb) {
return new Promise(function (resolve, reject) {
if (typeof options === 'function') {
cb = options;
}

if (!cb) {
cb = function cb(err, result) {
return err ? reject(err) : resolve(result);
};
}

redisCache.get(key, handleResponse(cb, { parse: true }));
});
},
del: function del(key, options, cb) {
if (typeof options === 'function') {
cb = options;
}

redisCache.del(key, handleResponse(cb));
},
reset: function reset(cb) {
return redisCache.flushdb(handleResponse(cb));
},
keys: function keys(pattern, cb) {
return new Promise(function (resolve, reject) {
if (typeof pattern === 'function') {
cb = pattern;
pattern = '*';
}

if (!cb) {
cb = function cb(err, result) {
return err ? reject(err) : resolve(result);
};
}

redisCache.keys(pattern, handleResponse(cb));
});
},
ttl: function ttl(key, cb) {
return redisCache.ttl(key, handleResponse(cb));
},
isCacheableValue: storeArgs.isCacheableValue || function (value) {
return value !== undefined && value !== null;
}
};
};

function handleResponse(cb) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

return function (err, result) {
if (err) {
return cb && cb(err);
}

if (opts.parse) {
try {
result = JSON.parse(result);
} catch (e) {
return cb && cb(e);
}
}

return cb && cb(null, result);
};
}

var methods = {
create: function create() {
return redisStore.apply(undefined, arguments);
}
};

module.exports = methods;
Loading

0 comments on commit 36bb42e

Please sign in to comment.