I’m sure you’re all familiar with both Promises and exponential backoff. If you’re a regular visitor to this site, you’ll know these are two topics I often write about. In this post, I’ll combine the two, as exponential backoff should be able to handle promises as well as callbacks nowadays

The waiting game problem

If you are using any kind of service with rate limiting, or some other kind of reason that you might need to wait a bit and retry, you are probably already using exponential backoff. However if you are also using promises, then the approach needs to be a little different.

You can of course use this with any API but for this example, I’ll use the Node/JavaScript version of the Ephemeral Exchange API to handle a rejection request for an update intention.

You might get one of these if you state an intention to update a cache item, but someone else already already has one. For these examples, I’ll use ES6 for brevity.

Here’s a normal read with an intention. This will work fine unless someone else is also intending to update, in which case we’ll get back an error 429 (locked)

We can wrap all that in exponential backoff (I’ll go into the code for that later on), which eventually keeps trying and returns a promise that resolves when a good result is achieved (or we give up).

The arguments are expBackoff ( action , doRetry , options), so in the example above

  • action – is a promise which is resolved when efx.read is executed
  • doRetry – is a function that should return true is a re-attempt is required , or false if no retry is required. Here I only want to retry if I detect a 423 error.
  • options – we’ll come to them later
  • Eventually this will resolve (when the other person who is locking this record for update has finished), or it will reject when I’ve tried enough times or there is an error. The amount of time it waits between attempts is exponentially increasing according to the normal exponential backoff algorithm.

    But we’re missing a trick here, because along with a 429 code, we also get a hint of the maximum amount of time that this item will be locked for, so we could do with a mechanism to adjust the next wait time if it could be reduced (because the lock on the item will expire). The third argument to backoff are various options, one of which is a custom function to tweak the next wait time. It receives various values which allow you to customise the wait time, but the key one here is the result, which contains a property (intentExpires). If that is less than the proposed next wait time, I’ll use that instead.

    And that’s it – no more worries about what to do when it’s locked, or wasting a lot of time waiting unnecessarily.

    The code

    These functions are handily available in the ephemeral exchange API namespace from v1.1 , so no extra libraries are needed – or you can just copy them into your own code from below.

    For more like this see Google Apps Scripts Snippets
    Why not join our forum, follow the blog or follow me on twitter to ensure you get updates when they are available.