Skip to content

Commit

Permalink
Merge branch 'release/0.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
BryanDonovan committed Oct 31, 2013
2 parents 6300c4f + 6b7c323 commit 3fbe7d6
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 90 deletions.
3 changes: 3 additions & 0 deletions History.md
@@ -1,3 +1,6 @@
- 0.2.0 2013-10-31
Better examples, version bump.

- 0.1.3 2013-10-31
Fixing unreleased connection in redis example.

Expand Down
212 changes: 135 additions & 77 deletions README.md
Expand Up @@ -27,6 +27,44 @@ priority cache(s) first.

First, it includes a `wrap` function that lets you wrap any function in cache.
(Note, this was inspired by [node-caching](https://github.com/mape/node-caching).)
This is probably the feature you're looking for. As an example, where you might have to do this

```javascript
function get_cached_user(id, cb) {
memory_cache.get(id, function (err, result) {
if (err) { return cb(err); }

if (result) {
return cb(null, result);
}

get_user(id, function (err, result) {
if (err) { return cb(err); }
memory_cache.set(id, result);
cb(null, result);
});
});
}
```
... you can instead use the `wrap` function:

```javascript
function get_cached_user(id, cb) {
memory_cache.wrap(id, function (cache_callback) {
get_user(id, cache_callback);
}, cb);
}

get_cached_user(user_id, function (err, user) {
// First time fetches the user from the (fake) database:
console.log(user);

get_cached_user(user_id, function (err, user) {
// Second time fetches from cache.
console.log(user);
});
});
```

Second, node-cache-manager features a built-in memory cache (using [node-lru-cache](https://github.com/isaacs/node-lru-cache)),
with the standard functions you'd expect in most caches:
Expand All @@ -53,49 +91,69 @@ Redis cache store with connection pooling.
### Single Store

```javascript
var cache_manager = require('cache-manager');
var memory_cache = cache_manager.caching({store: 'memory', max: 100, ttl: 10/*seconds*/});

// Note: callback is optional in set() and del().

memory_cache.set('foo', 'bar', function(err) {
if (err) { throw err; }

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

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

var user_id = 123;
var key = 'user_' + user_id;

memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {
console.log(user);

// Second time fetches user from memory_cache
memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {
console.log(user);
});
});
var cache_manager = require('cache-manager');
var memory_cache = cache_manager.caching({store: 'memory', max: 100, ttl: 10/*seconds*/});

// Note: callback is optional in set() and del().

memory_cache.set('foo', 'bar', function(err) {
if (err) { throw err; }

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

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

var user_id = 123;
var key = 'user_' + user_id;

memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {
console.log(user);

// Second time fetches user from memory_cache
memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {
console.log(user);
});
});

// Outputs:
// Returning user from slow database.
// { id: 123, name: 'Bob' }
// { id: 123, name: 'Bob' }
```

// Outputs:
// Returning user from slow database.
// { id: 123, name: 'Bob' }
// { id: 123, name: 'Bob' }
Here's a very basic example of how you could use this in an Express app:

```javascript
function respond(res, err, data) {
if (err) {
res.json(500, err);
} else {
res.json(200, data);
}
}

app.get('/foo/bar', function(req, res) {
var cache_key = 'foo-bar:' + JSON.stringify(req.query);
memory_cache.wrap(cache_key, function(cache_cb) {
DB.find(req.query, cache_cb);
}, function(err, result) {
respond(res, err, result);
});
});
```

#### Custom Stores
Expand All @@ -107,47 +165,47 @@ in an instance of it, or pass in the path to the module.
E.g.,

```javascript
var my_store = require('your-homemade-store');
var cache = cache_manager.caching({store: my_store});
// or
var cache = cache_manager.caching({store: '/path/to/your/store'});
var my_store = require('your-homemade-store');
var cache = cache_manager.caching({store: my_store});
// or
var cache = cache_manager.caching({store: '/path/to/your/store'});
```

### Multi-Store

```javascript
var multi_cache = cache_manager.multi_caching([memory_cache, some_other_cache]);
user_id2 = 456;
key2 = 'user_' + user_id;

// Sets in all caches.
multi_cache.set('foo2', 'bar2', function(err) {
if (err) { throw err; }

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

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

multi_cache.wrap(key2, function (cb) {
get_user(user_id2, cb);
}, function (err, user) {
console.log(user);

// Second time fetches user from memory_cache, since it's highest priority.
// If the data expires in the memory cache, the next fetch would pull it from
// the 'some_other_cache', and set the data in memory again.
multi_cache.wrap(key2, function (cb) {
get_user(user_id2, cb);
}, function (err, user) {
console.log(user);
});
});
var multi_cache = cache_manager.multi_caching([memory_cache, some_other_cache]);
user_id2 = 456;
key2 = 'user_' + user_id;

// Sets in all caches.
multi_cache.set('foo2', 'bar2', function(err) {
if (err) { throw err; }

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

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

multi_cache.wrap(key2, function (cb) {
get_user(user_id2, cb);
}, function (err, user) {
console.log(user);

// Second time fetches user from memory_cache, since it's highest priority.
// If the data expires in the memory cache, the next fetch would pull it from
// the 'some_other_cache', and set the data in memory again.
multi_cache.wrap(key2, function (cb) {
get_user(user_id2, cb);
}, function (err, user) {
console.log(user);
});
});
```

## Tests
Expand Down
70 changes: 58 additions & 12 deletions examples/example.js
@@ -1,23 +1,28 @@
/*jshint unused:false*/
var cache_manager = require('../');
var memory_cache = cache_manager.caching({store: 'memory', max: 100, ttl: 10/*seconds*/});
var memory_cache2 = cache_manager.caching({store: 'memory', max: 100, ttl: 100/*seconds*/});

//
// Basic usage
//
memory_cache2.set('foo', 'bar', function (err) {
memory_cache.set('foo', 'bar', function (err) {
if (err) { throw err; }

memory_cache2.get('foo', function (err, result) {
memory_cache.get('foo', function (err, result) {
console.log(result);
// >> 'bar'
memory_cache2.del('foo', function (err) { console.log(err); });
memory_cache.del('foo', function (err) {
if (err) {
console.log(err);
}
});
});
});

function get_user(id, cb) {
setTimeout(function () {
console.log("Returning user from slow database.");
console.log("Fetching user from slow database.");
cb(null, {id: id, name: 'Bob'});
}, 100);
}
Expand All @@ -28,15 +33,37 @@ var key = 'user_' + user_id;
//
// wrap() example
//
memory_cache2.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {

// Instead of manually managing the cache like this:
function get_cached_user_manually(id, cb) {
memory_cache.get(id, function (err, result) {
if (err) { return cb(err); }

if (result) {
return cb(null, result);
}

get_user(id, function (err, result) {
if (err) { return cb(err); }
memory_cache.set(id, result);
cb(null, result);
});
});
}

// ... you can instead use the `wrap` function:
function get_cached_user(id, cb) {
memory_cache.wrap(id, function (cache_callback) {
get_user(id, cache_callback);
}, cb);
}

get_cached_user(user_id, function (err, user) {
// First time fetches the user from the (fake) database:
console.log(user);

// Second time fetches user from memory_cache2
memory_cache2.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {
get_cached_user(user_id, function (err, user) {
// Second time fetches from cache.
console.log(user);
});
});
Expand All @@ -47,6 +74,23 @@ memory_cache2.wrap(key, function (cb) {
// { id: 123, name: 'Bob' }


// Same as above, but written differently:
memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {
console.log(user);

// Second time fetches user from memory_cache
memory_cache.wrap(key, function (cb) {
get_user(user_id, cb);
}, function (err, user) {
console.log(user);
});
});

//
// multi-cache example
//
var multi_cache = cache_manager.multi_caching([memory_cache, memory_cache2]);
var user_id2 = 456;
var key2 = 'user_' + user_id;
Expand Down Expand Up @@ -76,7 +120,9 @@ multi_cache.wrap(key2, function (cb) {

// Delete from all caches
multi_cache.del('foo2', function (err) {
console.log(err);
if (err) {
console.log(err);
}
process.exit();
});
});
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "cache-manager",
"version": "0.1.3",
"version": "0.2.0",
"description": "Cache module for Node.js",
"main": "index.js",
"scripts": {
Expand Down

0 comments on commit 3fbe7d6

Please sign in to comment.