Skip to content

Commit

Permalink
feat(twilio): add retry on message send fail (#651)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidvitora authored Feb 7, 2024
1 parent f389ff8 commit a40bc7b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 12 deletions.
6 changes: 5 additions & 1 deletion packages/channels/src/twilio/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ export interface TwilioConfig extends ChannelConfig {
accountSID: string
authToken: string
messageDelay?: string
retryMaxAttempts?: number
retryDelay?: string
}

export const TwilioConfigSchema = {
accountSID: Joi.string().regex(/^AC.*/).required(),
authToken: Joi.string().required(),
messageDelay: Joi.string().optional()
messageDelay: Joi.string().optional(),
retryMaxAttempts: Joi.number().optional(),
retryDelay: Joi.string().optional()
}
45 changes: 34 additions & 11 deletions packages/channels/src/twilio/senders/common.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
import { backOff } from 'exponential-backoff'
import ms from 'ms'
import { CommonSender } from '../../base/senders/common'
import { TwilioContext } from '../context'

const DEFAULT_MAX_ATTEMPTS = 3

export class TwilioCommonSender extends CommonSender {
async send(context: TwilioContext) {
for (const message of context.messages) {
await context.state.twilio.messages.create({
...message,
from: context.identity,
to: context.sender
})
const { messageDelay, retryDelay, retryMaxAttempts = DEFAULT_MAX_ATTEMPTS } = context.state.config
await backOff(
async () => {
await context.state.twilio.messages.create({
...message,
from: context.identity,
to: context.sender
})

const { messageDelay } = context.state.config
if (messageDelay) {
// depending on the account it might be required to limit the rps to each number
// usually this is an issue for carousels
await new Promise((resolve) => setTimeout(resolve, ms(messageDelay)))
}
if (messageDelay) {
// depending on the account it might be required to limit the rps to each number
// usually this is an issue for carousels
await new Promise((resolve) => setTimeout(resolve, ms(messageDelay)))
}
},
{
jitter: 'none',
numOfAttempts: retryMaxAttempts,
startingDelay: (retryDelay && ms(retryDelay)) || 1000,
retry: (e, attemptNumber) => {
if (attemptNumber === 1) {
context.logger?.error(
e,
`Failed to send message to Twilio on first attempt. Retrying ${retryMaxAttempts} more times`
)
} else {
context.logger?.error(e, `Failed again, retry: ${attemptNumber}`)
}
return true
}
}
)
}
}
}

0 comments on commit a40bc7b

Please sign in to comment.