Giter Site home page Giter Site logo

express-redis-cache's Introduction

express-redis-cache

Build Status dependencies Status

Easily cache pages of your app using Express and Redis. Could be used without Express too.

Install

npm install express-redis-cache

express-redis-cache ships with a CLI utility you can invoke from the console. In order to use it, install express-redis-cache globally (might require super user privileges):

npm install -g express-redis-cache

Upgrade

Read this if you are upgrading from 0.0.8 to 0.1.x,

Usage

Just use it as a middleware in the stack of the route you want to cache.

var app = express();
var cache = require('express-redis-cache')();

// replace
app.get('/',
  function (req, res)  { ... });

// by
app.get('/',
  cache.route(),
  function (req, res)  { ... });

This will check if there is a cache entry for this route. If not. it will cache it and serve the cache next time route is called.

Redis connection info

By default, redis-express-cache connects to Redis using localhost as host and nothing as port (using Redis default port 6379). To use different port or host, declare them when you require express-redis-cache. If your Redis server requires password, use the auth_pass option.

var cache = require('express-redis-cache')({
  host: String, port: Number, auth_pass: REDIS_PASSWORD
  });

You can pass a Redis client as well:

require('express-redis-cache')({ client: require('redis').createClient() })

You can have several clients if you want to serve from more than one Redis server:

var cache = require('express-redis-cache');
var client1 = cache({ host: "...", port: "..." });
var client2 = cache({ host: "...", port: "..." });
...

Redis Unavailability

Should the redis become unavailable, the express-redis-cache object will emit errors but will not crash the app. Express.js requests during this time will be bypass cache and will return fresh data.

Once the redis recovers, the caching will begin working again. See example code in the /example folder.

Name of the cache entry

By default, the cache entry name will be default prefix:name where name's value defaults to req.originalUrl.

app.get('/',
  cache.route(), // cache entry name is `cache.prefix + "/"`
  function (req, res)  { ... });

You can specify a custom name like this:

app.get('/',
  cache.route('home'), // cache entry name is now `cache.prefix + "home"`
  function (req, res)  { ... });

You can also use the object syntax:

app.get('/',
  cache.route({ name: 'home' }), // cache entry name is `cache.prefix + "home"`
  function (req, res)  { ... });

Also, you can use res.express_redis_cache_name to specify the name of the entry such as:

app.get('/user/:userid',

  // middleware to define cache name

  function (req, res, next) {
    // set cache name
    res.express_redis_cache_name = 'user-' + req.params.userid;
    next();
    },

  // cache middleware

  cache.route(),

  // content middleware

  function (req, res) {
    res.render('user');
    }

  );

Conditional caching

You can also use a previous middleware to set whether or not to use the cache by using res.use_express_redis_cache:

app.get('/user',

  // middleware to decide if using cache

  function (req, res, next) {
    // Use only cache if user not signed in
    res.use_express_redis_cache = ! req.signedCookies.user;

    next();
    }.

  cache.route(), // this will be skipped if user is signed in

  function (req, res) {
    res.render('user');
    }
  );

Prefix

All entry names are prepended by a prefix. Prefix is set when calling the Constructor.

// Set default prefix to "test". All entry names will begin by "test:"
var cache = require('express-redis-cache')({ prefix: 'test' });

To know the prefix:

console.log('prefix', cache.prefix);

You can pass a custom prefix when calling route():

app.get('/index.html',
  cache.route('index', { prefix: 'test'  }), // force prefix to be "test", entry name will be "test:index"
  function (req, res)  { ... });

You can also choose not to use prefixes:

app.get('/index.html',
  cache.route({ prefix: false  }), // no prefixing, entry name will be "/index.html"
  function (req, res)  { ... });

Expiration

Unless specified otherwise when calling the Constructor, cache entries don't expire. You can specify a default lifetime when calling the constructor:

// Set default lifetime to 60 seconds for all entries
var cache = require('express-redis-cache')({ expire: 60 });

You can overwrite the default lifetime when calling route():

app.get('/index.html',
  cache.route({ expire: 5000  }), // cache entry will live 5000 seconds
  function (req, res)  { ... });

// You can also use the number sugar syntax
cache.route(5000);
// Or
cache.route('index', 5000);
// Or
cache.route({ prefix: 'test' }, 5000);

You can also provide a hash of status code / expiration values if you for example want to retry much sooner in failure cases (403/404/500/etc). Status ranges can be specified via 4xx/5xx. You must provide a default value (xxx). The most specific rule will be used. For example, if the status code is 200, and there are expirations set for 200, 2xx, and xxx, the expiration for 200 will be used.

app.get('/index.html',
  cache.route({
    expire: {
      200: 5000,
      4xx: 10,
      403: 5000,
      5xx: 10,
      xxx: 1
    }
  }),
  function (req, res)  { ... });

You can also specify

Content Type

You can use express-redis-cache to cache HTML pages, CSS stylesheets, JSON objects, anything really. Content-types are saved along the cache body and are retrieved using res._headers['content-type']. If you want to overwrite that, you can pass a custom type.

app.get('/index.html',
  cache.route({ type: 'text/plain'  }), // force entry type to be "text/plain"
  function (req, res)  { ... });

Events

The module emits the following events:

error

You can catch errors by adding a listener:

cache.on('error', function (error) {
  throw new Error('Cache error!');
});

message

express-redis-cache logs some information at runtime. You can access it like this:

cache.on('message', function (message) {
  // ...
});

connected

Emitted when the client is connected (or re-connected) to Redis server

cache.on('connected', function () {
  // ....
});

disconnected

Emitted when the client is disconnected from Redis server. When (and if) it reconnects, it will emit a 'connected' event again

cache.on('disconnected', function () {
  // ....
});

Note You can get the connexion status at any time by getting the property cache.connected which returns a boolean (true = connected, false = disconnected).

deprecated

Warning emitted when stumbled upon a deprecated part of the code

cache.on('deprecated', function (deprecated) {
  console.log('deprecated warning', {
      type: deprecated.type,
      name: deprecated.name,
      substitute: deprecated.substitute,
      file: deprecated.file,
      line: deprecated.line
  });
});

The Entry Model

This is the object synopsis we use to represent a cache entry:

var entry = {
  body:    String // the content of the cache
  touched: Number // last time cache was set (created or updated) as a Unix timestamp
  expire:  Number // the seconds cache entry lives (-1 if does not expire)
  type: String // the content-type
};

The module

The module exposes a function which instantiates a new instance of a class called ExpressRedisCache.

// This
var cache = require('express-redis-cache')({ /* ... */ });
// is the same than
var cache = new (require('express-redis-cache/lib/ExpressRedisCache'))({ /* ... */ });

The constructor

As stated above, call the function exposed by the module to create a new instance of ExpressRedisCache,

var cache = require('express-redis-cache')(/** Object | Undefined */ options);

Where options is an object that has the following properties:

| Option | Type | Default | Description | | ------------- |----------|-------|----------|--------| | host | String | undefined | Redis server host | port | Number | undefined | Redis server port | prefix | String | require('express-redis-cache/package.json').config.prefix | Default prefix (This will be prepended to all entry names) | | expire | Number | undefined | Default life time of entries in seconds | | client | RedisClient | require('redis').createClient({ host: cache.host, port: cache.port }) | A Redis client |

API

The route method is designed to integrate easily with Express. You can also define your own caching logics using the other methos of the API shown below.

get Get cache entries

cache.get(/** Mixed (optional) */ query, /** Function( Error, [Entry] ) */ callback );

To get all cache entries:

cache.get(function (error, entries) {
  if ( error ) throw error;

  entries.forEach(console.log.bind(console));
});

To get a specific entry:

cache.get('home', function (error, entries) {});

To get a specific entry for a given prefix:

cache.get({ name: 'home', prefix: 'test' }, function (error, entries) {});

You can use wildcard:

cache.get('user*', function (error, entries) {});

add Add a new cache entry

cache.add(/** String */ name, /** String */ body, /** Object (optional) **/ options, /** Function( Error, Entry ) */ callback )

Where options is an object that can have the following properties:

  • expire Number (lifetime of entry in seconds)
  • type String (the content-type)

Example:

cache.add('user:info', JSON.stringify({ id: 1, email: '[email protected]' }), { expire: 60 * 60 * 24, type: 'json' },
    function (error, added) {});

del Delete a cache entry

cache.del(/** String */ name, /** Function ( Error, Number deletions ) */ callback);

You can use wildcard (*) in name.

size Get cache size for all entries

cache.size(/** Function ( Error, Number bytes ) */);

Command line

We ship with a CLI. You can invoke it like this: express-redis-cache

View cache entries

express-redis-cache ls

Add cache entry

express-redis-cache add $name $body $expire --type $type

Examples

# Cache simple text
express-redis-cache add "test" "This is a test";

# Cache a file
express-redis-cache add "home" "$(cat index.html)";

# Cache a JSON object
express-redis-cache add "user1:location" '{ "lat": 4.7453, "lng": -31.332 }' --type json;

# Cache a text that will expire in one hour
express-redis-cache add "offer" "everything 25% off for the next hour" $(( 60 * 60 ));

Get single cache entry

express-redis-cache get $name
# Example: express-redis-cache get user1:*
# Output:

Delete cache entry

express-redis-cache del $name
# Example: express-redis-cache del user1:*
# Output:

Get total cache size

express-redis-cache size
# Output:

Example Code

Run the example to see how the caching behaves. You can kill the redis-server and the application will respond with non-cached information.

npm install
cd example
node example.js

Test

We use Mocha and Should for the tests. You can invoke tests like this:

npm test

Test environments

You can specify the following environments before running your tests:

export EX_RE_CA_HOST="";
export EX_RE_CA_PORT="";
export EX_RE_CA_PREFIX="";

Contributors


Enjoy!

express-redis-cache's People

Contributors

artursudnik avatar barwin avatar benmcmeen avatar bsyk avatar ckeboss avatar co2-git avatar dam1 avatar faceair avatar krazyjakee avatar mdbox avatar pwmckenna avatar rsnara avatar rv-kip avatar ykid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

express-redis-cache's Issues

Cannot set property 'name' of null

events.js:72
throw er; // Unhandled 'error' event
^
TypeError: Cannot set property 'name' of null
at Command. (/home/ec2-user/server/api/node_modules/express-redis-cache/lib/ExpressRedisCache/get.js:45:27)
at Command.b (domain.js:177:20)
at Command.b as callback
at normal_reply (/home/ec2-user/server/api/node_modules/redis/index.js:714:21)
at RedisClient.return_reply (/home/ec2-user/server/api/node_modules/redis/index.js:816:9)
at JavascriptRedisParser.Parser.returnReply (/home/ec2-user/server/api/node_modules/redis/index.js:188:18)
at JavascriptRedisParser.execute (/home/ec2-user/server/api/node_modules/redis/node_modules/redis-parser/lib/parser.js:413:12)
at Socket. (/home/ec2-user/server/api/node_modules/redis/index.js:267:27)
at Socket.emit (events.js:95:17)
at Socket. (stream_readable.js:765:14)
at Socket.emit (events.js:92:17)
at emitReadable
(_stream_readable.js:427:10)
at emitReadable (_stream_readable.js:423:5)
at readableAddChunk (_stream_readable.js:166:9)
at Socket.Readable.push (_stream_readable.js:128:10)
at TCP.onread (net.js:529:21)

Can't get binary content to be cached

If my route returns a binary file, the cache seems to simply ignore it, as far as I can tell.

This module was probably written to target caching of dynamic content, not static content (which most binaries are served as). Yet there are two use cases where you might want to have caching for binary files:

  • if the file is generated server side, through some heavy operation.
  • if the file is obtained through a http proxy

It should be easy to do with a little buffer.toString("hex") but the module doesn't allow to transform the response before it stores it and after it retrieves it.

Work with pipes

It seems that express-redis-cache doesn't cache the data if res is used as a pipe (res.send() is never called).

For example:

app.get('/test/:id', cache.route({ expire: 3600 }), function (req, res, next) {
    request({ method: req.method, uri: BASE_URL + req.url }).pipe(res);
});

Tests hang: test/route.js hangs due to uncaught error and unresolved callback

I'm not sure of an easy fix, which is why I've no PR to go along with this report, unfortunately. But the problem itself is hopefully easy enough to explain. Here's my attempt:

When trying to run the test suite via npm test, I noticed the tests never completes, but there are no errors reported.

I traced the faulty path of execution from test.js -> test/route.js -> lib/route.js -> lib/get.js

It turns out that name in lib/route.js is left undefined, and so lib/get.js throws an error:

    if ( typeof name !== 'string' ) {
      throw new Error('Missing name of cache to get');
    }

That error is caught in lib/route.js in the domain.on('error') block:

  domain.on('error', function (error) {
    throw error;
  });

So lib/route.js attempts to re-throw the error from lib/get.js, BUT, that error is never caught or reported.

You can verify this issue by adding a line to that error handler in lib/route.js that spits out some information to the console, as I've done locally:

  domain.on('error', function (error) {
    console.error("Caught error in lib/route.js", error);
    throw error;
  });

Then run the test suite again and you'll see the error logged.

Caught error in lib/route.js { [Error: Missing name of cache to get]
  domain:
   { domain: null,
     _events: { error: [Function] },
     _maxListeners: 10,
     members: [] },
  domainThrown: false,
  domainBound: [Function] }

The reason the process "hangs" is because the then() in test/route.js is never called:

            /** Emulate res **/
            var res = {
              send: function (body) {
                assert('it should be the same message', body === entry.body);

                then(); // <- THIS NEVER GETS CALLED
              }
            };

In summary:

  • A test is failing due to the 'name' in lib/route.js being undefined.
  • That failure is not being captured/reported by the test suite.
  • The test suite hangs because a promise in test/route.js is never resolved.

Other thoughts (nice-to-haves):

  • It'd be nice to use a more structured test harness like Mocha that has built-in timeouts for hanging async tests, etc.
  • It'd be nice to be able to run individual test scripts one-by-one rather than having to run test/test.js which in turn runs all the tests.

Redis Connection to localhost:6379 Failed

I'm new Express, and just created a basic app and trying to integrate the Redis cache for Express from npm

When I install and add the module in the app, and run the appp it gives the error described on the screenshot.

screenshot_4

Express Ver: 4.14.0

Advice for new entry on header change

Hi,

I would like to create a new entry when there is a difference in the header. For example for X-Requested-With or if a cookie is present. Is this something I can do using this module?

Should set the Cache-Control header

Without the Cache-Control header, browsers will make unnecessary calls to the server to get cached data. If the browser is aware of the cache duration, it can avoid calling the server at all until the cache is expired. This could be done by adding a header like this:

res.setHeader('Cache-Control', 'max-age=' + options.expire + '000');

Maintenance...

I'll maintain the project if you want to transfer to me.

Mapping missmatch with key and content - Caching different pages for different urls

events.js:72
throw er; // Unhandled 'error' event
^
TypeError: Cannot set property 'name' of null
at /var/www/mobile2/node_modules/express-redis-cache/lib/ExpressRedisCache/get.js:45:27
at b (domain.js:177:20)
at b (domain.js:183:18)
at try_callback (/var/www/mobile2/node_modules/redis/index.js:592:9)
at RedisClient.return_reply (/var/www/mobile2/node_modules/redis/index.js:685:13)
at ReplyParser. (/var/www/mobile2/node_modules/redis/index.js:321:14)
at ReplyParser.emit (events.js:95:17)
at ReplyParser.send_reply (/var/www/mobile2/node_modules/redis/lib/parser/javascript.js:300:10)
at ReplyParser.execute (/var/www/mobile2/node_modules/redis/lib/parser/javascript.js:211:22)
at RedisClient.on_data (/var/www/mobile2/node_modules/redis/index.js:547:27)
error: Forever detected script exited with code: 7
error: Script restart attempt #2

Express' app.param still executes if route is cached

Thanks for making this library! Really great stuff.

I'm running into an issue though where I have an Express param that is bound to a method that loads some data prior to the route

app.route('/user/:userId')
  .get(cache.route(), controller.getUserById)

app.param('userId', controller.loadUser);

What I'm seeing is that even though the route is cached it still runs the param method which loads the data from the database and slows down the route.

Any ideas how to get around this? Thanks.

TypeError: Cannot assign to read only property 'callback' of keys

TypeError: Cannot assign to read only property 'callback' of keys
at RedisClient.internalSendCommandWrapper (/app/node_modules/newrelic/lib/instrumentation/redis.js:76:22)
at RedisClient.wrappedFunction [as internal_send_command] (/app/node_modules/newrelic/lib/transaction/tracer/index.js:366:24)
at RedisClient.(anonymous function).RedisClient.(anonymous function) (/app/node_modules/redis/lib/commands.js:45:25)
at Domain.<anonymous> (/app/node_modules/express-redis-cache/lib/ExpressRedisCache/get.js:36:19)
at Domain.run (domain.js:228:14)
at ExpressRedisCache.get (/app/node_modules/express-redis-cache/lib/ExpressRedisCache/get.js:25:12)
at expressRedisCache_Middleware (/app/node_modules/express-redis-cache/lib/ExpressRedisCache/route.js:158:14)
at Layer.handle (/app/node_modules/express/lib/router/layer.js:95:5)
at Layer.wrappedLayerHandleRequest [as handle_request] (/app/node_modules/newrelic/lib/instrumentation/express.js:428:32)
at next (/app/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3)
at dispatch (eval at wrapHandle (/app/node_modules/newrelic/lib/instrumentation/express.js:539:19), <anonymous>:12:19)
at Layer.handle (/app/node_modules/express/lib/router/layer.js:95:5)
at Layer.wrappedLayerHandleRequest [as handle_request] (/app/node_modules/newrelic/lib/instrumentation/express.js:428:32)
at /app/node_modules/express/lib/router/index.js:277:22
at Function.process_params (/app/node_modules/express/lib/router/index.js:330:12)

TypeError: Cannot set property 'name' of null

TypeError: Cannot set property 'name' of null
at Command. (/home/mdladmin/source/web-chat/JavaScript/node_modules/express-redis-cache/lib/ExpressRedisCache/get.js:45:27)
at intercepted (domain.js:258:14)
at Command.runIntercepted (domain.js:272:12)
at bound (domain.js:287:14)
at Command.runBound (domain.js:300:12)
at RedisClient.return_reply (/home/mdladmin/source/web-chat/JavaScript/node_modules/express-redis-cache/node_modules/redis/index.js:664:25)

Caching disregards query strings for the route

Given the following simple example...

var express = require('express');
var cache = require('express-redis-cache')();

var app = express();

app.get('/', cache.route(), function(req, res) {
  res.json(req.query);
});

app.listen(9999);

a request to /?param=1 returns { param: 1 }

a subsequent request to /?param=2 also returns { param: 1 }

Given the nature of query strings changing the returned data, is this the expected behavior or am I using this library wrong?

In route.js in the following code:

name = name || res.expressRedisCacheName || req.originalUrl;

name is getting assigned on the first call and caching is done with that key for the express route from then on.

Hoping you could help me or let me know if I can submit a pull request...

use_express_redis_cache only disables storing to cache

Hey, I noticed res.use_express_redis_cache only disables storing to the cache, but not getting from it. Wouldn't it make sense to disable read and write?

I'm looking for a solution to completely disable caching if in debug.

Example in README says you can provide 'host', but the code ignores it.

The README says:

var cache = require('express-redis-cache')({
    host: String, port: Number
    });

But index.js sets client like so:

var client = options.client || require('redis').createClient(options.port);

So it pays attention to port but not host.

I'll attach a pull-request (hopefully) before too long.

Of course the easy workaround is to just build your own redis client and pass that to the constructor. That is certainly reasonable but either the README or the Code should be updated so that they are in sync.

Thanks

expressRedisCacheName __fileName and __line don't exist

There is a bug on:
https://github.com/rv-kip/express-redis-cache/blob/master/lib/ExpressRedisCache/route.js#L66
https://github.com/rv-kip/express-redis-cache/blob/master/lib/ExpressRedisCache/route.js#L102

Neither __fileName, nor __line, exist at all. The first one should be __filename and the __line doesn't exist. Check nodejs magic globals: https://nodejs.org/api/globals.html

Use expressRedisCacheName deprecated attribute to check. (Note you are using a domain.)

Thanks for your code.

The middleware should fail gracefully

If redis crashes, this middleware throws an error and crashes. Ideally, it would simulate a cache miss and let the express layer serve non-cached data. A bunch of error emits would be good too.

change default cache entry name

Now the default cache entry name is req.path, sometimes will make mistakes.

for example:

i define route in this way:

app.use "/day", require "./routes/day"
app.use "/story", require "./routes/story"

in /routes/day the req.path maybe is /123, and in /routes/story the req.path also can be /123.

so i suggust use req.originalUrl to replace it.

cache http response code

If for example "500" is cached, response retrieved from redis is served with "200" response code.

Expireat

I need to cache entries until midnight. This constraint can be accomplished using the redis command expireat, however it doesn't seem to be currently available in express-redis-cache. Is there a way to accomplish that constraint with the current release?

redis unavailability crashing

Hi! The README suggests that redis unavailability won't crash the app: "Should the redis become unavailable, the express-redis-cache object will emit errors but will not crash the app. Express.js requests during this time will be bypass cache and will return fresh data."

Unfortunately, I'm not seeing this -- when I stop my local redis from running, I get

cache { [Error: Redis connection to localhost:6379 failed - connect ECONNREFUSED]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect' }

I am calling it like so, from an external (not in app.js) routes file:

//cache
var cache = require('express-redis-cache')({
  host: config.redisHost, port: config.redisPort
  });

cache.on('error', function(error){
  console.error("cache", error);
});
...
routes.get('/fragments/flickr/:word', cache.route({expire: 86400}), fragments.flickr);

Any idea how to handle an unavailable redis? The graceful failure was one of the main selling points of express-redis-cache. :)

Errors hang Express when redis connectivity is lost with Redis client

Thanks for a great module. The documentation indicates errors should just be emitted and pass through to the route... which seems true if node couldn't connect to Redis at all on startup. But, if connectivity is lost after initial connection is made... the response is never returned. Here is my code (I pass around the exported cache objects as middleware to the routes in server.js):

'use strict';

var redis = require('redis'),
  constants = require('../constants/constants'),
  logger = require('../utils/logger');

var redisClient;
redisClient = redis.createClient(constants.redisPort, constants.redisHost);
redisClient.auth(constants.redisAuth);

redisClient.on('connect', function () {
  logger.info('Connected to redis... ');
});
redisClient.on('error', function (err) {
  logger.error('Error connecting to redis: ' + err);
});

var _redisCache = require('express-redis-cache')({ prefix: constants.env, client: redisClient, expires: 15 });

_redisCache.on('connected', function () {
  logger.info('Cache is functional...');
});
_redisCache.on('error', function (err) {
  logger.error('Cache error: ' + err);
});

exports.tenSecondCache = _redisCache.route(10);
exports.oneMinuteCache = _redisCache.route(60);
exports.fifteenMinuteCache = _redisCache.route(60*15);

It seems that when using a Redis client, once it has problems the error that's emitted to the cache error doesn't allow it to pass through? I can replicate this locally by cutting off network connectivity after the initial connection. Is there a way I can let it fall through in this case?

Conditional caching not working as expected

I'm having issues with conditional caching. I've tried placing the middleware step to define
res.use_express_redis_cache both before all of my routes, and as a callback before cache.route in a GET request. Neither of these seem to prevent the responses being returned from Redis' cache.

Examples:
As prior middleware:

app.use(function(req, res, next) {
  res.use_express_redis_cache = false;
  next();
});
app.route(...)

In the get request:

app.route('/offers')
  .get(function(req, res, next) {
    res.use_express_redis_cache = false;
    next();
}, cache.route(ms('5ms')), ... )

Upon testing both of these, the page is clearly still caching requests to /offers (checking in redis-cli MONITOR)

Am I missing something here?

Hi,could I make a suggestion?

When the cache expires,return the cache first,and then restore the cache asynchronously.In this way,the user can aways take a response quickly.Thank you~

Effect of caching route in redis using express-redis-cache

It is question not issue,what we are achieving from performance perspective by caching route into redis?
I got this question because I am working on application & I am caching route.
So during development,it becomes tedious to debug as code is getting cache in redis.

Error: OOM command not allowed when used memory > 'maxmemory'.

/home/faceair/zhihudaily/node_modules/express-redis-cache/node_modules/redis/index.js:575
throw callback_err;
^
Error: OOM command not allowed when used memory > 'maxmemory'.
at ReplyParser. (/home/faceair/zhihudaily/node_modules/express-redis-cache/node_modules/redis/index.js:317:31)
at ReplyParser.emit (events.js:95:17)
at ReplyParser.send_error (/home/faceair/zhihudaily/node_modules/express-redis-cache/node_modules/redis/lib/parser/javascript.js:296:10)
at ReplyParser.execute (/home/faceair/zhihudaily/node_modules/express-redis-cache/node_modules/redis/lib/parser/javascript.js:181:22)
at RedisClient.on_data (/home/faceair/zhihudaily/node_modules/express-redis-cache/node_modules/redis/index.js:547:27)
at Socket. (/home/faceair/zhihudaily/node_modules/express-redis-cache/node_modules/redis/index.js:102:14)
at Socket.emit (events.js:95:17)
at Socket. (stream_readable.js:764:14)
at Socket.emit (events.js:92:17)
at emitReadable
(_stream_readable.js:426:10)
at emitReadable (_stream_readable.js:422:5)
at readableAddChunk (_stream_readable.js:165:9)
at Socket.Readable.push (_stream_readable.js:127:10)
at TCP.onread (net.js:528:21)

I install this in my vps, and throw this error, what's wrong ?

Content-type doesn't create new entry

Hi,

An initial request with Accept:text/html header, responding with a Content-Type:text/html, then a subsequent request to the same route with Accept:application/json, responding with Content-Type:application/json doesn't create a new entry.

npm version

Hi everybody!

I'd better start giving thanks to co2 for your code. It has saved me a lot of time. Thanks!
I just want to report that the npm version of this library is not the latest and it doesn't give all its features (like using the right content-type of the cached element).

have a nice day!

ENV VAR to disable caching

would be nice to be able to toggle this using an environment var. I'd be happy to provide a pull request if there's interest.

Cached respone as [object Object]

I made a simple POC with "express": "~4.9.0", and add following code
app.get("/", reqcache.route({ expire: 60}), function(req, res, next) {,,,}

First response is fine as it comes from my own code, but second request which is supposed to give cached response gives '[object Object]'

installation issue

When I run the npm install express-redis-cache command I get the following error and no directory is created in my node_modules.

npm WARN package.json [email protected] No description
npm WARN package.json [email protected] No repository field.
npm WARN package.json [email protected] No README data
npm WARN install Refusing to install express-redis-cache as a dependency of itself

size command callback is not a function

version 0.1.8

$ express-redis-cache size
/usr/local/lib/node_modules/express-redis-cache/bin/express-redis-cache.js:14
    throw error;
    ^

TypeError: callback is not a function
    at Domain.<anonymous> (/usr/local/lib/node_modules/express-redis-cache/lib/ExpressRedisCache/size.js:21:5)
    at emitOne (events.js:77:13)
    at Domain.emit (events.js:169:7)
    at emitError (domain.js:65:24)
    at Domain.errorHandler [as _errorHandler] (domain.js:119:16)
    at process._fatalException (node.js:229:33)

Stop using keys

Hey there,

In our production environment this was pretty slow (https://s.put.re/4ueAZEA.png).
You can read more details about .keys under: http://redis.io/commands/keys

On this screenshot you can see our t2.small redis cache instance cpu usage on amazon, take a look at 2:50. That's where I replaced your caching lib with a custom one that uses .get (https://s.put.re/f36CV4z.png).

Maybe your usage of .keys has a deeper point I don't see here, but let me quote the redis docs:

Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code.

greetz

Expiration doesn't work unless specified via route()

When setting up the cache with

var cache = require('express-redis-cache')({ expire: 60 });

The expire value of the entry is always undefined and the item never expired from the cache. The unit test for this always succeeds since the value being checked is always undefined

it ( ' - entry which has a property expire which equals cache.expire', function () {
  should(entry.expire).equal(cache.expire);
});

Expiration does work when specified this way

cache.route("test", 300)

ls command not found

version 0.1.8

$ express-redis-cache ls
/usr/local/lib/node_modules/express-redis-cache/bin/express-redis-cache.js:14
    throw error;
    ^

TypeError: cache.ls is not a function
    at Domain.<anonymous> (/usr/local/lib/node_modules/express-redis-cache/bin/express-redis-cache.js:178:15)
    at Domain.run (domain.js:221:14)
    at /usr/local/lib/node_modules/express-redis-cache/bin/express-redis-cache.js:17:10
    at Object.<anonymous> (/usr/local/lib/node_modules/express-redis-cache/bin/express-redis-cache.js:270:3)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:457:10)
    at startup (node.js:136:18)

Error when key doesn't exist

Inside of get.js, line 43, hgetall is used to get a value from redis. It doesn't handle the case when the key doesn't exist. If the key doesn't exist then result is null which results in the below error being thrown. It looks like keys is used to check if the key exists but it could expire or be deleted in between the time that keys is called and hgetall is called.

TypeError: Cannot set property 'name' of null
    at Command.<anonymous> (/Users/dustinmartin/Projects/api/node_modules/express-redis-cache/lib/ExpressRedisCache/get.js:45:27)
    at intercepted (domain.js:251:14)
    at Command.runIntercepted (domain.js:265:12)
    at Command.nrWrappedHandler (/Users/dustinmartin/Projects/api/node_modules/newrelic/lib/transaction/tracer/index.js:398:19)
    at Command.wrapped (/Users/dustinmartin/Projects/api/node_modules/newrelic/lib/transaction/tracer/index.js:182:28)
    at Command.wrappedCallback (/Users/dustinmartin/Projects/api/node_modules/newrelic/lib/transaction/tracer/index.js:450:66)
    at Command.wrapped (/Users/dustinmartin/Projects/api/node_modules/newrelic/lib/transaction/tracer/index.js:182:28)
    at bound (domain.js:280:14)
    at Command.runBound (domain.js:293:12)
    at normal_reply (/Users/dustinmartin/Projects/api/node_modules/redis/index.js:662:21)
    at RedisClient.return_reply (/Users/dustinmartin/Projects/api/node_modules/redis/index.js:722:9)
    at JavascriptReplyParser.RedisClient.reply_parser.Parser.returnReply (/Users/dustinmartin/Projects/api/node_modules/redis/index.js:146:18)
    at JavascriptReplyParser.run (/Users/dustinmartin/Projects/api/node_modules/redis-parser/lib/javascript.js:137:18)
    at JavascriptReplyParser.execute (/Users/dustinmartin/Projects/api/node_modules/redis-parser/lib/javascript.js:112:10)
    at Socket.<anonymous> (/Users/dustinmartin/Projects/api/node_modules/redis/index.js:223:27)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:172:18)
    at Socket.Readable.push (_stream_readable.js:130:10)
    at TCP.onread (net.js:542:20)
[nodemon] app crashed - waiting for file changes before starting...

Prefix in cache.route not being set

Our app needs the ability to set a dynamic cache prefix. However, whenever I call cache.route({prefix: 'blah'}) and check what prefix is being utilized, it's always 'erc:'. How can I get cache.route to correctly set a prefix?

Thanks!

Cache should preserve original response status code

You've got a wonderful project here, but I notice results returned from the cache are always sent as 200, even if the original response is a 501 (Not Implemented) or what have you.

At first glance, it wouldn't be too hard to include a field in your entry model to include the original response.

Would you be open to accepting a pull request if I built out this feature?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.