The grass is rarely greener, but it's always different

Twilio Conversations client resilient setup

With Twilio Conversations SDK 2.0 release there is a new way of creating the client and setting up the event handlers. As stated in the documentation and contrary to previous versions, when the client is created in order to guarantee it has been properly initialized we must wait for the stateChanged event to fire and check the passed state to verify the initialization was completed:

import { Client } from '@twilio/conversations';

const client = new Client(token);

// Before you use the client, subscribe to the `'stateChanged'` event and wait 
// for the `'initialized'` state to be reported.
client.on('stateChanged', (state) => {
  if (state === 'initialized') {
    // Use the client

What if we have a momentarily unreliable connection? Simply by changing the network quality in Chrome's network tab to Slow the Twilio Client refused to initialize and that was it.

In order to make the process a bit more resilient I wrote a function that wraps the initialization event inside a promise that resolves when the client is successfully initialized and tries to recreate the client using an exponential backoff promise otherwise.

//wait is a helper function that will wait a given number of seconds.
const wait = (ms) => new Promise((res) => setTimeout(res, ms));

const createTwilioClientWithRetries = (token, depth = 0) => {
    return new Promise((resolve, reject) => {
        //Create a new Twilio Client for the token.
        const twilioClient = new Client(token);

        twilioClient.on('stateChanged', async (state) => {
            try {
                if (state === 'initialized') {
                if (state === 'failed') {
                    if (depth > 5) {
                        throw new Error("Too many retries");
                    else {
                            type: TWILIO_TOKEN_FAILURE,
                            message: "Twilio Token Error"
                        await wait(2 ** depth * 10);
                        return await createTwilioClientWithRetries(token, depth + 1);
            } catch (err) {
                reject("Too many retries");

Initially I tried to shut the client down with await twilioClient.shutdown() before calling the next iteration but it would prevent me from creating any further instances of the client afterwards for some reason.

Have fun!

View original

#javascript #programming