node.js and Redis on Heroku for IODocs

2.8k views Asked by At

I'm trying to get IODocs running on Heroku. It requires node.js and Redis. Admittedly, I'm new to all of these technologies. Nonetheless, I've managed to get it running locally. However, I receive the following error when deploying to Heroku.

2011-12-01T11:55:18+00:00 app[web.1]: Redis To Go - port: 9030 hostname: dogfish.redistogo.com
2011-12-01T11:55:18+00:00 app[web.1]: Express server listening on port 9694
2011-12-01T11:55:19+00:00 heroku[web.1]: State changed from starting to up
2011-12-01T11:55:21+00:00 app[web.1]:         ^
2011-12-01T11:55:21+00:00 app[web.1]: Error: Redis connection to localhost:6379 failed - ECONNREFUSED, Connection refused
2011-12-01T11:55:21+00:00 app[web.1]:     at Socket.<anonymous> (/app/node_modules/redis/index.js:123:28)
2011-12-01T11:55:21+00:00 app[web.1]:     at Socket.emit (events.js:64:17)
2011-12-01T11:55:21+00:00 app[web.1]:     at Array.<anonymous> (net.js:828:27)
2011-12-01T11:55:21+00:00 app[web.1]:     at EventEmitter._tickCallback (node.js:126:26)
2011-12-01T11:55:23+00:00 heroku[web.1]: State changed from up to crashed

The only time I received a similar warning on my local mating was when Redis was not running. From what I can tell the Redis add-on is enabled for my app and running:

$ heroku config --long
NODE_ENV      => production
PATH          => bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin
REDISTOGO_URL => redis://redistogo:[email protected]:9030/

I've also tried some configuration suggestions. Neither seem to work.

// redis connection in app.js
var db;
if (process.env.REDISTOGO_URL) {
   var rtg = require("url").parse(process.env.REDISTOGO_URL);
// tried this line as well... gave a different error on .connect();
// db = require('redis-url').connect(process.env.REDISTOGO_URL);
   db = redis.createClient(rtg.port, rtg.hostname);
   db.auth(rtg.auth.split(":")[1]);

   // debug
   sys.puts('Redis To Go - port: ' + rtg.port + ' hostname: ' + rtg.hostname);
} else {
   db = redis.createClient(config.redis.port, config.redis.host);
   db.auth(config.redis.password);
}

From the difference in my Redis To Go debug line and Error, I'm sure this is a configuration issue. But don't know how to fix it. Any help is greatly appreciated.

4

There are 4 answers

0
Jason McCreary On BEST ANSWER

This indeed had to do with the configuration for Redis on Heroku. There were additional lines that required updates in I/O Docs app.js.

In the end, I piggy-backed the global config object at the top (~ line 60) after sniffing out the production (Heroku) environment.

if (process.env.REDISTOGOURL) {
  // use production (Heroku) redis configuration
  // overwrite config to keep it simple
  var rtg = require(‘url’).parse(process.env.REDISTOGOURL);
  config.redis.port = rtg.port;
  config.redis.host = rtg.hostname;
  config.redis.password = rtg.auth.split(“:”)[1];
}

I created a blog post for installing, configuring, and deploying I/O Docs that includes this as well as other changes that were required to run I/O Docs. I recommend you review it if you're interested in this project.

Thanks to Jan Jongboom and Kirsten Jones for helping me get started. In addition, I believe the project has been updated on GitHub to include Heroku configuration out of the box. However, I've yet to test it.

3
Jan Jongboom On

According to this line:

2011-12-01T11:55:21+00:00 app[web.1]: Error: Redis connection to localhost:6379 failed - ECONNREFUSED, Connection refused

You are trying to connect to localhost:6379, but the redis server is running at redis://redistogo:[email protected]:9030/. Can you try connecting to that URL manually and see if that works?

3
Kirsten Jones On

I actually have a blog post about how to get IODocs working on Heroku. It's got the config changes needed to get the REDIS working on Heroku with IODocs.

http://www.princesspolymath.com/princess_polymath/?p=489

Here's the code changes needed: Add the following block under “var db;” to app.'s:

if (process.env.REDISTOGO_URL) {
   var rtg   = require("url").parse(process.env.REDISTOGO_URL);
   db = require("redis").createClient(rtg.port, rtg.hostname);
   db.auth(rtg.auth.split(":")[1]);
} else {
   db = redis.createClient(config.redis.port, config.redis.host);
   db.auth(config.redis.password);
}

And then this in the Load API Configs section, after reading the config file:

var app = module.exports = express.createServer();
var hostname, port, password
if (process.env.REDISTOGO_URL) {
    var rtg   = require("url").parse(process.env.REDISTOGO_URL);
    hostname = rtg.hostname;
    port = rtg.port;
    password = rtg.auth.split(":")[1];
} else {
    hostname = config.redis.host;
    port = config.redis.port;
    password = config.redis.password;
}
1
Adrien Schuler On

Recently, a cleaner way would be to use the redis-url module which handles the configuration.

I'm personnaly using Express with Redis (via the Redis To Go addon) as a sessionStore, and it works well on Heroku.

Exemple :

const express           = require('express')

    , redis             = process.env.REDISTOGO_URL 
        ? require('redis-url').connect(process.env.REDISTOGO_URL) 
        : require('redis').createClient()

    , RedisStore        = require('connect-redis')(express)
    , sessionStore      = new RedisStore({ client: redis })
    , app               = express.createServer();

[...]

app.configure(function() {
    this
        .use(express.session({
            secret: 'mySecretHash', 
            store: sessionStore // Set redis as the sessionStore for Express
        }));
});