diff --git a/helpers/mail.ts b/helpers/mail.ts index abd2214..0c3b291 100644 --- a/helpers/mail.ts +++ b/helpers/mail.ts @@ -2,6 +2,7 @@ import { Booking } from '../db/booking' import { getBaseURL } from '../helpers/url' import { daysFormatFrontend } from './date' import { generateCalendarEntry } from './ical' +import { retryWithDelay } from './retryWithDelay' const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY const ADMIN_EMAIL = process.env.ADMIN_EMAIL @@ -195,12 +196,17 @@ async function sendMail({ }, body: JSON.stringify(data), } - const resp = await fetch(SENDGRID_URL, fetchOptions) - const bodyText = await resp.text() - if (!resp.ok) { - throw new Error( - `Unable to send mail, status ${resp.status} ${resp.statusText}, ${bodyText}` - ) - } + return retryWithDelay({ + run: async () => { + const resp = await fetch(SENDGRID_URL, fetchOptions) + const bodyText = await resp.text() + + if (!resp.ok) { + throw new Error( + `Failed to send mail with status ${resp.status}: ${bodyText}` + ) + } + }, + }) } diff --git a/helpers/retryWithDelay.ts b/helpers/retryWithDelay.ts new file mode 100644 index 0000000..7f1023d --- /dev/null +++ b/helpers/retryWithDelay.ts @@ -0,0 +1,20 @@ +import pRetry from 'p-retry' + +export function retryWithDelay({ + run, + delay = 1000, +}: { + run: () => Promise + delay?: number +}) { + return pRetry(run, { + retries: 2, + onFailedAttempt: (error) => { + console.info( + `Attempt ${error.attemptNumber}: ${error.message}. ${error.retriesLeft} retries left` + ) + + return new Promise((resolve) => setTimeout(resolve, delay)) + }, + }) +} diff --git a/package-lock.json b/package-lock.json index 9502280..ae7392c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2796,6 +2796,11 @@ "integrity": "sha512-QZ8EMG2P3230GQNEMXtSJq8v8zJkJqs8xpbohMbBefYG7i1MX2YzOsDoBWF2dpq36mrkXpoNgmmeVnXIT0DYtw==", "dev": true }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, "@types/stack-utils": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", @@ -9454,6 +9459,15 @@ "aggregate-error": "^3.0.0" } }, + "p-retry": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.2.0.tgz", + "integrity": "sha512-jPH38/MRh263KKcq0wBNOGFJbm+U6784RilTmHjB/HM9kH9V8WlCpVUcdOmip9cjXOh6MxZ5yk1z2SjDUJfWmA==", + "requires": { + "@types/retry": "^0.12.0", + "retry": "^0.12.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -10783,6 +10797,11 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, "rework": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", diff --git a/package.json b/package.json index bd18ac4..80a172f 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "mongoose": "^5.10.13", "next": "^10.0.1", "next-iron-session": "^4.1.10", + "p-retry": "^4.2.0", "react": "^17.0.1", "react-calendar": "^3.2.0", "react-dom": "^17.0.1",