1

I have a node.js script which starts at boot. It uses node-redis to create a client for Redis, but at boot Redis is not ready while node is already starting. So, it gives an exception and stops executing.

The first part looks like this:

var redis  = require("redis"),
    jobs   = require("jobs"),
    client = redis.createClient(),
    runner = new jobs(client, "job-queue",{});

// Continue using runner

The exception is thrown in line 3 (redis.createClient()).

My solution was to make an endless loop, create the client in a try/catch and when successful, stop the loop:

var redis  = require("redis"),
    jobs   = require("jobs"),
    queue  = 'job-queue',
    client = null,
    runner = null,
    createClient = function (redis, jobs, queue) {
        try {
            client = redis.createClient();
            return new jobs(client, queue, {});
        } catch (err) {
            return null;
        }
    };

while(true) {
    setTimeout(function() {
        runner = createClient(redis, jobs, queue);
    }, 1000);

    if (null !== runner) break;
}

// Continue using runner

After a couple of seconds, this is the output:

FATAL ERROR: JS Allocation failed - process out of memory

How can I solve this? I am searching for a solution which could be in php:

while (true) {
    $client = createClient($redis, $jobs, $queue);
    if ($client instanceof MyClient) break;
    else sleep(1);
}
1
  • If two startup services have dependencies, easyest thing to do is ensure to start in right order, i guess. Commented Oct 16, 2011 at 19:31

1 Answer 1

3

setTimeout is asynchronous. JavaScript (and Node.js) have very few functions that wait for something to happen before continuing (like sleep). Instead, execution continues to the next line right away, but you pass setTimeout a callback function which is run when it fires.

I would do something like this (warning, untested):

var redis  = require("redis"),
    jobs   = require("jobs"),
    queue  = 'job-queue';

function initializeRedis(callback) {
    (function createClient(){
        var runner;
        try {
            client = redis.createClient();
            runner = new jobs(client, queue, {});
        } catch (e) {}
        if (runner){
            callback(runner);
        } else {
            setTimeout(createClient, 1000);
        }
    })();
};

initializeRedis(function(runner){
    // Continue using runner
});
Sign up to request clarification or add additional context in comments.

6 Comments

This aspect oriented example seems a bit better than @Fosco's one (sorry Fosco), I'll mark this as an answer soon. Atm, exceptions in redis.createClient() are not caught by my try/catch. When I figured this out, I'll give you the credits.
@JurianSluiman Not a problem, deleted mine as it proved not to be a correct answer. I was pondering a solution with process.nexttick but didn't get around to it.
@Sidnicious, I assume that you wanted to write setTimeout(createClient, 1000);? Because this is wrong, it'll callback before success if the first attempt fails. It'll even call back more than once!
@thejh I don't completely follow… but I think I see what you mean. Does this fix it?
@Sidnicious: ah, sorry, I wanted to say return setTimeout(createClient, 1000);... but this should fix it, too, although it's an unusual style.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.