Backend robustness to email sending or analytics tracking failures (#728)
* Make `sendEmail` functions await email send success * Make tracking and email sending not throw on failure
This commit is contained in:
parent
186befd0ac
commit
d00fe7bcd2
|
@ -3,7 +3,7 @@ import * as Amplitude from '@amplitude/node'
|
||||||
import { DEV_CONFIG } from '../../common/envs/dev'
|
import { DEV_CONFIG } from '../../common/envs/dev'
|
||||||
import { PROD_CONFIG } from '../../common/envs/prod'
|
import { PROD_CONFIG } from '../../common/envs/prod'
|
||||||
|
|
||||||
import { isProd } from './utils'
|
import { isProd, tryOrLogError } from './utils'
|
||||||
|
|
||||||
const key = isProd() ? PROD_CONFIG.amplitudeApiKey : DEV_CONFIG.amplitudeApiKey
|
const key = isProd() ? PROD_CONFIG.amplitudeApiKey : DEV_CONFIG.amplitudeApiKey
|
||||||
|
|
||||||
|
@ -15,10 +15,12 @@ export const track = async (
|
||||||
eventProperties?: any,
|
eventProperties?: any,
|
||||||
amplitudeProperties?: Partial<Amplitude.Event>
|
amplitudeProperties?: Partial<Amplitude.Event>
|
||||||
) => {
|
) => {
|
||||||
await amp.logEvent({
|
return await tryOrLogError(
|
||||||
|
amp.logEvent({
|
||||||
event_type: eventName,
|
event_type: eventName,
|
||||||
user_id: userId,
|
user_id: userId,
|
||||||
event_properties: eventProperties,
|
event_properties: eventProperties,
|
||||||
...amplitudeProperties,
|
...amplitudeProperties,
|
||||||
})
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,9 +74,8 @@ export const sendMarketResolutionEmail = async (
|
||||||
|
|
||||||
// Modify template here:
|
// Modify template here:
|
||||||
// https://app.mailgun.com/app/sending/domains/mg.manifold.markets/templates/edit/market-resolved/initial
|
// https://app.mailgun.com/app/sending/domains/mg.manifold.markets/templates/edit/market-resolved/initial
|
||||||
// Mailgun username: james@mantic.markets
|
|
||||||
|
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
subject,
|
subject,
|
||||||
'market-resolved',
|
'market-resolved',
|
||||||
|
@ -152,7 +151,7 @@ export const sendWelcomeEmail = async (
|
||||||
const emailType = 'generic'
|
const emailType = 'generic'
|
||||||
const unsubscribeLink = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
const unsubscribeLink = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
||||||
|
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'Welcome to Manifold Markets!',
|
'Welcome to Manifold Markets!',
|
||||||
'welcome',
|
'welcome',
|
||||||
|
@ -183,7 +182,7 @@ export const sendOneWeekBonusEmail = async (
|
||||||
const emailType = 'generic'
|
const emailType = 'generic'
|
||||||
const unsubscribeLink = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
const unsubscribeLink = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
||||||
|
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'Manifold Markets one week anniversary gift',
|
'Manifold Markets one week anniversary gift',
|
||||||
'one-week',
|
'one-week',
|
||||||
|
@ -215,7 +214,7 @@ export const sendThankYouEmail = async (
|
||||||
const emailType = 'generic'
|
const emailType = 'generic'
|
||||||
const unsubscribeLink = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
const unsubscribeLink = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
||||||
|
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'Thanks for your Manifold purchase',
|
'Thanks for your Manifold purchase',
|
||||||
'thank-you',
|
'thank-you',
|
||||||
|
@ -250,7 +249,7 @@ export const sendMarketCloseEmail = async (
|
||||||
const emailType = 'market-resolve'
|
const emailType = 'market-resolve'
|
||||||
const unsubscribeUrl = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
const unsubscribeUrl = `${UNSUBSCRIBE_ENDPOINT}?id=${userId}&type=${emailType}`
|
||||||
|
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'Your market has closed',
|
'Your market has closed',
|
||||||
'market-close',
|
'market-close',
|
||||||
|
@ -309,7 +308,7 @@ export const sendNewCommentEmail = async (
|
||||||
if (contract.outcomeType === 'FREE_RESPONSE' && answerId && answerText) {
|
if (contract.outcomeType === 'FREE_RESPONSE' && answerId && answerText) {
|
||||||
const answerNumber = `#${answerId}`
|
const answerNumber = `#${answerId}`
|
||||||
|
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
subject,
|
subject,
|
||||||
'market-answer-comment',
|
'market-answer-comment',
|
||||||
|
@ -332,7 +331,7 @@ export const sendNewCommentEmail = async (
|
||||||
bet.outcome
|
bet.outcome
|
||||||
)}`
|
)}`
|
||||||
}
|
}
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
subject,
|
subject,
|
||||||
'market-comment',
|
'market-comment',
|
||||||
|
@ -377,7 +376,7 @@ export const sendNewAnswerEmail = async (
|
||||||
const subject = `New answer on ${question}`
|
const subject = `New answer on ${question}`
|
||||||
const from = `${name} <info@manifold.markets>`
|
const from = `${name} <info@manifold.markets>`
|
||||||
|
|
||||||
await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
subject,
|
subject,
|
||||||
'market-answer',
|
'market-answer',
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
import * as mailgun from 'mailgun-js'
|
import * as mailgun from 'mailgun-js'
|
||||||
|
import { tryOrLogError } from './utils'
|
||||||
|
|
||||||
const initMailgun = () => {
|
const initMailgun = () => {
|
||||||
const apiKey = process.env.MAILGUN_KEY as string
|
const apiKey = process.env.MAILGUN_KEY as string
|
||||||
return mailgun({ apiKey, domain: 'mg.manifold.markets' })
|
return mailgun({ apiKey, domain: 'mg.manifold.markets' })
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sendTextEmail = (to: string, subject: string, text: string) => {
|
export const sendTextEmail = async (
|
||||||
|
to: string,
|
||||||
|
subject: string,
|
||||||
|
text: string
|
||||||
|
) => {
|
||||||
const data: mailgun.messages.SendData = {
|
const data: mailgun.messages.SendData = {
|
||||||
from: 'Manifold Markets <info@manifold.markets>',
|
from: 'Manifold Markets <info@manifold.markets>',
|
||||||
to,
|
to,
|
||||||
|
@ -14,14 +19,15 @@ export const sendTextEmail = (to: string, subject: string, text: string) => {
|
||||||
// Don't rewrite urls in plaintext emails
|
// Don't rewrite urls in plaintext emails
|
||||||
'o:tracking-clicks': 'htmlonly',
|
'o:tracking-clicks': 'htmlonly',
|
||||||
}
|
}
|
||||||
const mg = initMailgun()
|
const mg = initMailgun().messages()
|
||||||
return mg.messages().send(data, (error) => {
|
const result = await tryOrLogError(mg.send(data))
|
||||||
if (error) console.log('Error sending email', error)
|
if (result != null) {
|
||||||
else console.log('Sent text email', to, subject)
|
console.log('Sent text email', to, subject)
|
||||||
})
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sendTemplateEmail = (
|
export const sendTemplateEmail = async (
|
||||||
to: string,
|
to: string,
|
||||||
subject: string,
|
subject: string,
|
||||||
templateId: string,
|
templateId: string,
|
||||||
|
@ -38,10 +44,10 @@ export const sendTemplateEmail = (
|
||||||
'o:tag': templateId,
|
'o:tag': templateId,
|
||||||
'o:tracking': true,
|
'o:tracking': true,
|
||||||
}
|
}
|
||||||
const mg = initMailgun()
|
const mg = initMailgun().messages()
|
||||||
|
const result = await tryOrLogError(mg.send(data))
|
||||||
return mg.messages().send(data, (error) => {
|
if (result != null) {
|
||||||
if (error) console.log('Error sending email', error)
|
console.log('Sent template email', templateId, to, subject)
|
||||||
else console.log('Sent template email', templateId, to, subject)
|
}
|
||||||
})
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,15 @@ export const writeAsync = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const tryOrLogError = async <T>(task: Promise<T>) => {
|
||||||
|
try {
|
||||||
|
return await task
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const isProd = () => {
|
export const isProd = () => {
|
||||||
return admin.instanceId().app.options.projectId === 'mantic-markets'
|
return admin.instanceId().app.options.projectId === 'mantic-markets'
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user