diff --git a/History.md b/History.md index de5b3ea..361d1f4 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,8 @@ +- 0.6.0 2014-06-15 + Adding caching.keys() function (issue #6) + Updating examples/redis_example/example.js with cache.keys() usage + Allow calling memory store get() without callback + - 0.5.0 2014-05-02 Adding reset() function to caching.js. Closes #5. diff --git a/examples/redis_example/example.js b/examples/redis_example/example.js index f6c3905..b010168 100644 --- a/examples/redis_example/example.js +++ b/examples/redis_example/example.js @@ -3,45 +3,67 @@ // npm install sol-redis-pool // node examples/redis_example/example.js +var util = require('util'); var cache_manager = require('../../'); var redis_store = require('./redis_store'); var redis_cache = cache_manager.caching({store: redis_store, db: 0, ttl: 100/*seconds*/}); +console.log("set/get/del example:"); redis_cache.set('foo', 'bar', function (err) { if (err) { throw err; } redis_cache.get('foo', function (err, result) { - console.log(result); + if (err) { throw err; } + console.log("result fetched from cache: " + result); // >> 'bar' - redis_cache.del('foo', function (err) { console.log(err); }); + redis_cache.del('foo', function (err) { + if (err) { throw err; } + }); }); }); +var user_id = 123; + +function create_key(id) { + return 'user_' + id; +} + function get_user(id, cb) { setTimeout(function () { - console.log("Returning user from slow database."); + console.log("\n\nReturning user from slow database."); cb(null, {id: id, name: 'Bob'}); }, 100); } -var user_id = 123; -var key = 'user_' + user_id; +function get_user_from_cache(id, cb) { + var key = create_key(id); + redis_cache.wrap(key, function (cache_cb) { + get_user(user_id, cache_cb); + }, cb); +} -redis_cache.wrap(key, function (cb) { - get_user(user_id, cb); -}, function (err, user) { +get_user_from_cache(user_id, function (err, user) { console.log(user); - // Second time fetches user from redis_cache - redis_cache.wrap(key, function (cb) { - get_user(user_id, cb); - }, function (err, user) { + // Second time fetches user from redis_cache + get_user_from_cache(user_id, function (err, user) { + console.log("user from second cache request:"); console.log(user); - process.exit(); + + redis_cache.keys(function (err, keys) { + console.log("keys: " + util.inspect(keys)); + + var key = create_key(user_id); + redis_cache.del(key, function (err) { + if (err) { throw err; } + process.exit(); + }); + }); }); }); // Outputs: -// Returning user from slow database. // { id: 123, name: 'Bob' } +// user from second cache request: // { id: 123, name: 'Bob' } +// keys: [ 'user_123' ] diff --git a/examples/redis_example/redis_store.js b/examples/redis_example/redis_store.js index ef39dfb..97a64fe 100644 --- a/examples/redis_example/redis_store.js +++ b/examples/redis_example/redis_store.js @@ -75,13 +75,27 @@ function redis_store(args) { }); }; + self.keys = function (pattern, cb) { + if (typeof pattern === 'function') { + cb = pattern; + pattern = '*'; + } + + connect(function (err, conn) { + if (err) { return cb(err); } + + conn.keys(pattern, function (err, result) { + pool.release(conn); + cb(err, result); + }); + }); + }; + return self; } -var methods = { +module.exports = { create: function (args) { return redis_store(args); } }; - -module.exports = methods; diff --git a/lib/caching.js b/lib/caching.js index 9e560db..f410a19 100644 --- a/lib/caching.js +++ b/lib/caching.js @@ -1,3 +1,4 @@ +/*jshint maxcomplexity:10*/ var caching = function (args) { args = args || {}; var self = {}; @@ -61,6 +62,10 @@ var caching = function (args) { self.reset = self.store.reset.bind(self.store); } + if (typeof self.store.keys === 'function') { + self.keys = self.store.keys.bind(self.store); + } + return self; }; diff --git a/lib/stores/memory.js b/lib/stores/memory.js index 351af0d..1b02648 100644 --- a/lib/stores/memory.js +++ b/lib/stores/memory.js @@ -20,9 +20,14 @@ var memory_store = function (args) { }; self.get = function (key, cb) { - process.nextTick(function () { - cb(null, lru_cache.get(key)); - }); + var value = lru_cache.get(key); + if (cb) { + process.nextTick(function () { + cb(null, value); + }); + } else { + return value; + } }; self.del = function (key, cb) { @@ -39,6 +44,17 @@ var memory_store = function (args) { } }; + self.keys = function (cb) { + var keys = lru_cache.keys(); + if (cb) { + process.nextTick(function () { + cb(null, keys); + }); + } else { + return keys; + } + }; + return self; }; diff --git a/package.json b/package.json index fdd8622..b257e5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cache-manager", - "version": "0.5.0", + "version": "0.6.0", "description": "Cache module for Node.js", "main": "index.js", "scripts": { diff --git a/test/caching.unit.js b/test/caching.unit.js index b9b8a3a..5f1f5dc 100644 --- a/test/caching.unit.js +++ b/test/caching.unit.js @@ -1,6 +1,7 @@ // TODO: These are really a mix of unit and integration tests. var assert = require('assert'); +var async = require('async'); var sinon = require('sinon'); var support = require('./support'); var check_err = support.check_err; @@ -39,13 +40,12 @@ describe("caching", function () { }); }); - it("lets us set data without a callback", function (done) { + it("lets us set and get data without a callback", function (done) { cache.set(key, value); setTimeout(function () { - cache.get(key, function (err, result) { - assert.equal(result, value); - done(); - }); + var result = cache.get(key); + assert.equal(result, value); + done(); }, 20); }); }); @@ -113,7 +113,7 @@ describe("caching", function () { key2 = support.random.string(20); value2 = support.random.string(); - cache.set(key, value, done); + cache.set(key2, value2, done); }); }); @@ -132,7 +132,7 @@ describe("caching", function () { }); }); - it("lets us clear the cache without a callback", function (done) { + it("lets us clear the cache without a callback (memory store only)", function (done) { cache.reset(); setTimeout(function () { cache.get(key, function (err, result) { @@ -147,6 +147,43 @@ describe("caching", function () { }); }); + describe("keys()", function () { + var key_count; + var saved_keys = []; + + beforeEach(function (done) { + key_count = 10; + var processed = 0; + + cache = caching({store: 'memory'}); + + function is_done() { + return processed === key_count; + } + + async.until(is_done, function (cb) { + processed += 1; + key = support.random.string(20); + saved_keys.push(key); + value = support.random.string(); + cache.set(key, value, cb); + }, done); + }); + + it("calls back with all keys in cache", function (done) { + cache.keys(function (err, keys) { + check_err(err); + assert.deepEqual(keys.sort, saved_keys.sort); + done(); + }); + }); + + it("lets us get the keys without a callback (memory store only)", function () { + var keys = cache.keys(); + assert.deepEqual(keys.sort, saved_keys.sort); + }); + }); + describe("wrap()", function () { describe("using memory (lru-cache) store", function () { var memory_store_stub; @@ -166,7 +203,7 @@ describe("caching", function () { memory_store.create.restore(); }); - it("calls back with the result of a function", function (done) { + it("calls back with the result of the wrapped function", function (done) { cache.wrap(key, function (cb) { methods.get_widget(name, cb); }, function (err, widget) {