Awaiting AWS resources

Normally, when we work with AWS using AWS SDK, we need to wait for AWS resources to be in a specific status such as: an EC2 instance is running, a Kinesis stream is active, a Opsworks deployment process is successful… before we can continue. This can be done by continuous polling AWS resources until they are in a desired status.

Bellow is sample code for polling a newly created kinesis stream until it’s active.

function waitForStreamActive(streamName){
    let count = 0;
    const interval = 5000;
    const maxTries = 15;
    return (function wait(){
        return describeStream({StreamName : streamName}).then((data)=>{
            if(data.StreamDescription.StreamStatus === 'ACTIVE'){
                return Promise.resolve(streamName);
            } else {
                count++;
                logger.info(`Waiting for the stream ${streamName} active: ${count}`);
                //The stream is not active yet. Wait for some seconds
                if(count < maxTries){
                    return Promise.delay(interval).then(wait);
                } else {
                    return Promise.reject(`Max tries ${count} reached but the stream ${streamName} still not active`);
                }
            }
        });
    }());
}

We don't want to wait forever. In above code, when a polling completes, we will wait 5 seconds (interval) before a next polling. And we will do at most 15 tries (maxTries). If the resource isn't in a desired status after maxTries, we will terminate the polling process.

I kept doing this polling (partly b/c I was in a rush) by writing my own code until I realized that AWS SDK provides an API for this need (see waitFor):

waitFor(state, params, callback) ⇒ void

As waitFor is in abstract class (AWS.Service), we need to consult specific resource class for supported state names.

So, above code can be rewritten using AWS API waitFor as follows:

waitFor('streamExists', {StreamName: 'stream name'})
    .then(function(data){
        console.log(data);
    })
    .catch(function(err) {
        console.error(err);
    });

Sadly, AWS SDK for Node doesn't seem to allow us to config interval and maxTries parameters. I hadn't thought so ( because I know that AWS SDK for Ruby does allow us to do so) until I read the document carefully and found the hard-coded parameters stored in kinesis-2013-12-02.waiters2.json

{
  "version": 2,
  "waiters": {
    "StreamExists": {
      "delay": 10,
      "operation": "DescribeStream",
      "maxAttempts": 18,
      "acceptors": [
        {
          "expected": "ACTIVE",
          "matcher": "path",
          "state": "success",
          "argument": "StreamDescription.StreamStatus"
        }
      ]
    }
  }
}

Note: In code samples above, AWS's callback style APIs such as kinesis.describeStream, kinesis.waitFor… are converted to Promise style by using a a Promise library like bluebird

Advertisements

One thought on “Awaiting AWS resources

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s