Skip to main content

Serverless wrappers

Handler wrappers

Serverless function handlers require lots of various boilerplate: response headers for surviving CORS, validation of required parameters, error handling, and validation of the worker's Flex token. The template provides serverless wrappers to massively reduce the boilerplate within serverless functions.

An example boilerplate function using the prepareFlexFunction wrapper has been provided as a template you can use for creating each of your serverless functions.

prepareStudioFunction()

This wrapper should be used for all unauthenticated functions (i.e. when there is no Flex token provided in the request). It validates provided parameters against the specified requiredParameters array, sets up a response object with the appropriate response headers, and provides a common handleError function for automatic API retries.

prepareFlexFunction()

This wrapper should be used for all authenticated functions (i.e. a Flex token is provided in the request). It does everything that the prepareStudioFunction wrapper does, as well as validating the Flex token provided in the Token parameter. If the token is missing or invalid, the wrapper will automatically respond to the caller appropriately and prevent execution of your handler.

This wrapper should always be used for public (i.e. non-protected and non-private) functions which modify objects or expose potentially sensitive information.

Web service wrappers

When calling web services from your serverless functions, whether to Twilio or another service, it is generally desirable to add error handling and retry logic. The template provides wrappers for calling these services that will automatically handle errors and perform retries when necessary. A retry will be performed when an HTTP status of 412, 429, or 503 is returned, or if there is a connection error.

The following environment variables can be used to configure the retry handler:

  • TWILIO_SERVICE_MAX_BACKOFF - Maximum amount of wait time before the retry is attempted
  • TWILIO_SERVICE_MIN_BACKOFF - Minimum amount of wait time before the retry is attempted
  • TWILIO_SERVICE_RETRY_LIMIT - Maximum number of retry attempts
  • ENABLE_LOCAL_LOGGING - Whether to emit retry logs useful for local debugging

The following web service wrappers will return the web service response using this schema:

{
success: boolean; // Whether the web service request was successful
status: number; // The HTTP status code from the web service
data: any; // Data returned from the web service
}

executeWithRetry()

This function accepts a callback function that you can provide with the code to execute and return the web service request. If the code throws an error, a retry handler will be invoked to handle the error and perform a retry depending on the response status.

Example usage:

const axios = require('axios');
const { executeWithRetry } = require(Runtime.getFunctions()['common/helpers/function-helper'].path);

const result = await executeWithRetry(context, async () => {
// Make the API request
// Code that throws within this block will be handled by the retry handler
const response = await axios.get('https://my-amazing-service.tld/api/endpoint');
return response.data;
});

if (result.success) {
console.log('Web service response:', result.data);
}

executeTwilio()

This function works exactly the same as executeWithRetry(), however it also provides an instantiated Twilio client directly to the callback function.

Example usage:

const { twilioExecute } = require(Runtime.getFunctions()['common/helpers/function-helper'].path);

const conversationSid = 'CH...';
const result = await twilioExecute(context, (client) =>
client.conversations.v1.conversations(conversationSid).fetch()
);

if (result.success) {
console.log('Twilio API response:', result.data);
}

You may also wish to customize the error handling, for example to treat certain non-successful responses as a success, but use the wrapper's retry logic for everything else. Here is an example of doing so:

const { twilioExecute } = require(Runtime.getFunctions()['common/helpers/function-helper'].path);

const taskSid = 'WT...';
const result = await twilioExecute(context, async (client) => {
try {
return await client.taskrouter.v1
.workspaces(process.env.TWILIO_FLEX_WORKSPACE_SID)
.tasks(taskSid)
.update({ assignmentStatus: 'completed' });
} catch (error) {
if (error.code === 20001) {
console.warn('Handling error 20001');
return error.message;
}
// Re-throw the error for the retry handler to catch
throw error;
}
});

if (result.success) {
console.log('Twilio API response:', result.data);
}