tbadams45
tbadams45

Reputation: 878

Poll REST API for long running task

I'm designing a REST API to perform some tasks which require extensive computation, to be used by an additional service. In essence, a GET request to /command will begin the task, with the status being updated at /queue/12345. The client polls /queue/12345/ until the task is complete, at which point the server sends a 303 with the location of the result (/runs/12345).

What I'm trying to do right now is to write the polling function on the client side. What I have right now can successfully poll - however, because the setTimeout() function is called immediately after the request is sent. This means that I will poll forever, even though I don't call setTimeout() in the callback function of the request.

How can I ensure that my polling function ends once I've received a 303 status code?

// standard first call is pollQueue(uri, 0);
function pollQueue(uri, timesPolled, callback) {
    if(timesPolled > 28800) {
        // 288800 is (60 sec/min * 60 min/hr * 24 hr) / 3 sec/poll. Aka 24 hours.
        throw 'ResourceWillNeverBeReady';
    }

    console.log("polling " + uri);
    request({
      url: "http://localhost:2500/" + uri,
      followRedirect: false
    }, function (error, response, body) {
        if(response.statusCode === 303) {
            // callback handles requesting the actual data
            callback(response.headers.location); 
            return;
        }
    });

    setTimeout(function() { pollQueue(uri, timesPolled + 1, callback);}, 3000);
}

Upvotes: 2

Views: 2669

Answers (1)

tbadams45
tbadams45

Reputation: 878

Kevin B pointed out the obvious. All I needed to do was move the setTimeout() function into the callback.

// standard first call is pollQueue(uri, 0);
function pollQueue(uri, timesPolled, callback) {
    if(timesPolled > 28800) {
        // 288800 is (60 sec/min * 60 min/hr * 24 hr) / 3 sec/poll. Aka 24 hours.
        throw 'ResourceWillNeverBeReady';
    }

    console.log("polling " + uri);
    request({
      url: "http://localhost:2500/" + uri,
      followRedirect: false
    }, function (error, response, body) {
        if(response.statusCode === 303) {
            // callback handles requesting the actual data
            callback(response.headers.location); 
            return;
        }

        setTimeout(function() { pollQueue(uri, timesPolled + 1, callback);}, 3000);
    });
}

Upvotes: 1

Related Questions