One Shortcoming That Twilio Doesn’t Want You to Find Out

I recently had to create a Servo chatbot using text messaging for a demo for a large company. We decided to use Twilio as the obvious choice — bought some numbers, created the Servo-Twilio driver, and implemented the bot. However, in the hours before the presentation, something broke.

Short Message Service is one of the best channels to get a message across. Everyone with a smartphone can send and receive messages, regardless of which instant messenger they use. It can contain images and links, and you can send it as a push notification without much hassle.

Several companies offer easy-to-handle APIs that allow programmatic SMS handling. Some are less-known and localized to their own country, but clearly, the international leader is Twilio, which offers developers many ways to integrate messaging, voice, and even emails — starting from RESTful API and ending in Autopilot visual flow editor. It seems that a developer can easily build a chatbot, for example, that communicates over text messages.

Or can it? Well, not many developers know, but Twilio does not guarantee the order of its messages! This means that if you’d like to send your customers a reminder that is split across several sentences, you might be heading for trouble. For example, what would be more natural than sending the following 4 messages:

It seems you haven't activated your account. The faster you activate it, the more you save!
Would you like me to help you activate it?

But as it turns out, these could appear on the customer’s phone as:

The faster you activate it, the more you save!
Would you like me to help you activate it?
It seems you haven't activated your account.

How embarrassing is that?

The problem is that due to the carrier’s ancient infrastructure, one cannot guarantee the order upon arrival, as Twilio itself admits.

Fortunately, there are some ways around it. We came across the problem when developing a channel driver for Twilio in Servo’s conversational framework. Unfortunately, this discovery was made just one hour before an important demo to a client, so we couldn’t fix it right away. But right after the meeting, we started hacking away on the keyboard, trying a few options.

The most natural method that came to mind was to allow some time between the messages. It has the drawback that it would slow the conversation, but the hope was that 500ms delay wouldn’t be too bad. However, this didn’t work well enough.

The next evolution step was simple enough, and that one worked. We simply waited until Twilio drivers acknowledged that the message was received — by sending back the response — and then wait 500ms, or what was left of it. As always, it’s better to use decoupled queues to implement it. I’ll give you the essence here, and if you need the rest of the details, check the code itself in GitHub under the server/chat folder.

When a message arrives the channel driver for sending, we put it into a messages queue.

... _clients[process.fsm_id].messages.push(msg);

And once for every conversation, we call a recurrent function that would extract this message from the queue:

if (!_clients[process.fsm_id].messages.length) {
this.send1Message(msg, process);

Which would call:

function send1Message(msg, process) { twilio.sendMessage(msg, (err, responseData) => { if (!err) { setTimeout(() => { msg = _clients[process.fsm_id].messages.pop(); this.send1Message(msg, process);// <== recursive loop }, this.timeoutMs); } else { console.error('twilio message err', err.message + ' ' + err.moreInfo, msg); } });

That’s it! It worked.

And what about that demo? Well, after all that, the demo went well. Unexpectedly, luck was on our side that day.

This UrIoTNews article is syndicated fromDzone