fix: replace all async foreach callbacks (#10157)

Co-authored-by: zomars <zomars@me.com>
fix/storybook-builds^2
nicktrn 2023-08-26 01:43:10 +01:00 committed by GitHub
parent 83aea7d28c
commit c1bcfcfa3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 266 additions and 240 deletions

View File

@ -158,9 +158,10 @@ test.describe("pro user", () => {
await expect(page.locator("[data-testid=success-page]")).toBeVisible(); await expect(page.locator("[data-testid=success-page]")).toBeVisible();
additionalGuests.forEach(async (email) => { const promises = additionalGuests.map(async (email) => {
await expect(page.locator(`[data-testid="attendee-email-${email}"]`)).toHaveText(email); await expect(page.locator(`[data-testid="attendee-email-${email}"]`)).toHaveText(email);
}); });
await Promise.all(promises);
}); });
test("Time slots should be reserved when selected", async ({ context, page }) => { test("Time slots should be reserved when selected", async ({ context, page }) => {

View File

@ -121,18 +121,21 @@ const Reschedule = async (bookingUid: string, cancellationReason: string) => {
const bookingRefsFiltered: BookingReference[] = bookingToReschedule.references.filter( const bookingRefsFiltered: BookingReference[] = bookingToReschedule.references.filter(
(ref) => !!credentialsMap.get(ref.type) (ref) => !!credentialsMap.get(ref.type)
); );
const promises = bookingRefsFiltered.map(async (bookingRef) => {
if (!bookingRef.uid) return;
if (bookingRef.type.endsWith("_calendar")) {
const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent);
} else if (bookingRef.type.endsWith("_video")) {
return deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
}
});
try { try {
bookingRefsFiltered.forEach(async (bookingRef) => { await Promise.all(promises);
if (bookingRef.uid) {
if (bookingRef.type.endsWith("_calendar")) {
const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent);
} else if (bookingRef.type.endsWith("_video")) {
return deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
}
}
});
} catch (error) { } catch (error) {
// FIXME: error logging - non-Error type errors are currently discarded
if (error instanceof Error) { if (error instanceof Error) {
logger.error(error.message); logger.error(error.message);
} }

View File

@ -121,17 +121,19 @@ const Reschedule = async (bookingUid: string, cancellationReason: string) => {
const bookingRefsFiltered: BookingReference[] = bookingToReschedule.references.filter( const bookingRefsFiltered: BookingReference[] = bookingToReschedule.references.filter(
(ref) => !!credentialsMap.get(ref.type) (ref) => !!credentialsMap.get(ref.type)
); );
const promises = bookingRefsFiltered.map(async (bookingRef) => {
if (!bookingRef.uid) return;
if (bookingRef.type.endsWith("_calendar")) {
const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent);
} else if (bookingRef.type.endsWith("_video")) {
return deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
}
});
try { try {
bookingRefsFiltered.forEach(async (bookingRef) => { await Promise.all(promises);
if (bookingRef.uid) {
if (bookingRef.type.endsWith("_calendar")) {
const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent);
} else if (bookingRef.type.endsWith("_video")) {
return deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
}
}
});
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
logger.error(error.message); logger.error(error.message);

View File

@ -10,6 +10,7 @@ export async function scheduleTrigger(
) { ) {
try { try {
//schedule job to call subscriber url at the end of meeting //schedule job to call subscriber url at the end of meeting
// FIXME: in-process scheduling - job will vanish on server crash / restart
const job = schedule.scheduleJob( const job = schedule.scheduleJob(
`${subscriber.appId}_${subscriber.id}`, `${subscriber.appId}_${subscriber.id}`,
booking.endTime, booking.endTime,
@ -57,38 +58,39 @@ export async function cancelScheduledJobs(
appId?: string | null, appId?: string | null,
isReschedule?: boolean isReschedule?: boolean
) { ) {
try { if (!booking.scheduledJobs) return;
let scheduledJobs = booking.scheduledJobs || [];
if (booking.scheduledJobs) { let scheduledJobs = booking.scheduledJobs || [];
booking.scheduledJobs.forEach(async (scheduledJob) => { const promises = booking.scheduledJobs.map(async (scheduledJob) => {
if (appId) { if (appId) {
if (scheduledJob.startsWith(appId)) { if (scheduledJob.startsWith(appId)) {
if (schedule.scheduledJobs[scheduledJob]) { if (schedule.scheduledJobs[scheduledJob]) {
schedule.scheduledJobs[scheduledJob].cancel(); schedule.scheduledJobs[scheduledJob].cancel();
}
scheduledJobs = scheduledJobs?.filter((job) => scheduledJob !== job) || [];
}
} else {
//if no specific appId given, delete all scheduled jobs of booking
if (schedule.scheduledJobs[scheduledJob]) {
schedule.scheduledJobs[scheduledJob].cancel();
}
scheduledJobs = [];
} }
scheduledJobs = scheduledJobs?.filter((job) => scheduledJob !== job) || [];
}
} else {
//if no specific appId given, delete all scheduled jobs of booking
if (schedule.scheduledJobs[scheduledJob]) {
schedule.scheduledJobs[scheduledJob].cancel();
}
scheduledJobs = [];
}
if (!isReschedule) { if (!isReschedule) {
await prisma.booking.update({ await prisma.booking.update({
where: { where: {
uid: booking.uid, uid: booking.uid,
}, },
data: { data: {
scheduledJobs: scheduledJobs, scheduledJobs: scheduledJobs,
}, },
});
}
}); });
} }
});
try {
await Promise.all(promises);
} catch (error) { } catch (error) {
console.error("Error cancelling scheduled jobs", error); console.error("Error cancelling scheduled jobs", error);
} }

View File

@ -12,7 +12,7 @@ const libraries = [
}, },
]; ];
libraries.forEach(async (lib) => { const promises = libraries.map(async (lib) => {
await build({ await build({
build: { build: {
outDir: `./dist/${lib.fileName}`, outDir: `./dist/${lib.fileName}`,
@ -29,3 +29,4 @@ libraries.forEach(async (lib) => {
}, },
}); });
}); });
await Promise.all(promises);

View File

@ -430,9 +430,9 @@ async function handler(req: CustomRequest) {
bookingToDelete.recurringEventId && bookingToDelete.recurringEventId &&
allRemainingBookings allRemainingBookings
) { ) {
bookingToDelete.user.credentials const promises = bookingToDelete.user.credentials
.filter((credential) => credential.type.endsWith("_calendar")) .filter((credential) => credential.type.endsWith("_calendar"))
.forEach(async (credential) => { .map(async (credential) => {
const calendar = await getCalendar(credential); const calendar = await getCalendar(credential);
for (const updBooking of updatedBookings) { for (const updBooking of updatedBookings) {
const bookingRef = updBooking.references.find((ref) => ref.type.includes("_calendar")); const bookingRef = updBooking.references.find((ref) => ref.type.includes("_calendar"));
@ -443,6 +443,13 @@ async function handler(req: CustomRequest) {
} }
} }
}); });
try {
await Promise.all(promises);
} catch (error) {
if (error instanceof Error) {
logger.error(error.message);
}
}
} else { } else {
apiDeletes.push(calendar?.deleteEvent(uid, evt, externalCalendarId) as Promise<unknown>); apiDeletes.push(calendar?.deleteEvent(uid, evt, externalCalendarId) as Promise<unknown>);
} }
@ -603,11 +610,13 @@ async function handler(req: CustomRequest) {
}); });
// delete scheduled jobs of cancelled bookings // delete scheduled jobs of cancelled bookings
// FIXME: async calls into ether
updatedBookings.forEach((booking) => { updatedBookings.forEach((booking) => {
cancelScheduledJobs(booking); cancelScheduledJobs(booking);
}); });
//Workflows - cancel all reminders for cancelled bookings //Workflows - cancel all reminders for cancelled bookings
// FIXME: async calls into ether
updatedBookings.forEach((booking) => { updatedBookings.forEach((booking) => {
booking.workflowReminders.forEach((reminder) => { booking.workflowReminders.forEach((reminder) => {
if (reminder.method === WorkflowMethods.EMAIL) { if (reminder.method === WorkflowMethods.EMAIL) {
@ -622,11 +631,14 @@ async function handler(req: CustomRequest) {
const prismaPromises: Promise<unknown>[] = [bookingReferenceDeletes]; const prismaPromises: Promise<unknown>[] = [bookingReferenceDeletes];
// @TODO: find a way in the future if a promise fails don't stop the rest of the promises
// Also if emails fails try to requeue them
try { try {
await Promise.all(prismaPromises.concat(apiDeletes)); const settled = await Promise.allSettled(prismaPromises.concat(apiDeletes));
const rejected = settled.filter(({ status }) => status === "rejected") as PromiseRejectedResult[];
if (rejected.length) {
throw new Error(`Reasons: ${rejected.map(({ reason }) => reason)}`);
}
// TODO: if emails fail try to requeue them
await sendCancelledEmails(evt, { eventName: bookingToDelete?.eventType?.eventName }); await sendCancelledEmails(evt, { eventName: bookingToDelete?.eventType?.eventName });
} catch (error) { } catch (error) {
console.error("Error deleting event", error); console.error("Error deleting event", error);

View File

@ -102,171 +102,172 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule
throw new TRPCError({ code: "FORBIDDEN", message: "User isn't owner of the current booking" }); throw new TRPCError({ code: "FORBIDDEN", message: "User isn't owner of the current booking" });
} }
if (bookingToReschedule) { if (!bookingToReschedule) return;
let event: Partial<EventType> = {};
if (bookingToReschedule.eventTypeId) { let event: Partial<EventType> = {};
event = await prisma.eventType.findFirstOrThrow({ if (bookingToReschedule.eventTypeId) {
select: { event = await prisma.eventType.findFirstOrThrow({
title: true, select: {
users: true, title: true,
schedulingType: true, users: true,
recurringEvent: true, schedulingType: true,
}, recurringEvent: true,
where: { },
id: bookingToReschedule.eventTypeId,
},
});
}
await prisma.booking.update({
where: { where: {
id: bookingToReschedule.id, id: bookingToReschedule.eventTypeId,
},
data: {
rescheduled: true,
cancellationReason,
status: BookingStatus.CANCELLED,
updatedAt: dayjs().toISOString(),
}, },
}); });
// delete scheduled jobs of previous booking
cancelScheduledJobs(bookingToReschedule);
//cancel workflow reminders of previous booking
bookingToReschedule.workflowReminders.forEach((reminder) => {
if (reminder.method === WorkflowMethods.EMAIL) {
deleteScheduledEmailReminder(reminder.id, reminder.referenceId);
} else if (reminder.method === WorkflowMethods.SMS) {
deleteScheduledSMSReminder(reminder.id, reminder.referenceId);
} else if (reminder.method === WorkflowMethods.WHATSAPP) {
deleteScheduledWhatsappReminder(reminder.id, reminder.referenceId);
}
});
const [mainAttendee] = bookingToReschedule.attendees;
// @NOTE: Should we assume attendees language?
const tAttendees = await getTranslation(mainAttendee.locale ?? "en", "common");
const usersToPeopleType = (
users: PersonAttendeeCommonFields[],
selectedLanguage: TFunction
): Person[] => {
return users?.map((user) => {
return {
email: user.email || "",
name: user.name || "",
username: user?.username || "",
language: { translate: selectedLanguage, locale: user.locale || "en" },
timeZone: user?.timeZone,
};
});
};
const userTranslation = await getTranslation(user.locale ?? "en", "common");
const [userAsPeopleType] = usersToPeopleType([user], userTranslation);
const builder = new CalendarEventBuilder();
builder.init({
title: bookingToReschedule.title,
type: event && event.title ? event.title : bookingToReschedule.title,
startTime: bookingToReschedule.startTime.toISOString(),
endTime: bookingToReschedule.endTime.toISOString(),
attendees: usersToPeopleType(
// username field doesn't exists on attendee but could be in the future
bookingToReschedule.attendees as unknown as PersonAttendeeCommonFields[],
tAttendees
),
organizer: userAsPeopleType,
});
const director = new CalendarEventDirector();
director.setBuilder(builder);
director.setExistingBooking(bookingToReschedule);
cancellationReason && director.setCancellationReason(cancellationReason);
if (event) {
await director.buildForRescheduleEmail();
} else {
await director.buildWithoutEventTypeForRescheduleEmail();
}
// Handling calendar and videos cancellation
// This can set previous time as available, until virtual calendar is done
const credentials = await getUsersCredentials(user.id);
const credentialsMap = new Map();
credentials.forEach((credential) => {
credentialsMap.set(credential.type, credential);
});
const bookingRefsFiltered: BookingReference[] = bookingToReschedule.references.filter((ref) =>
credentialsMap.has(ref.type)
);
bookingRefsFiltered.forEach(async (bookingRef) => {
if (bookingRef.uid) {
if (bookingRef.type.endsWith("_calendar")) {
const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent, bookingRef.externalCalendarId);
} else if (bookingRef.type.endsWith("_video")) {
return deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
}
}
});
// Send emails
await sendRequestRescheduleEmail(builder.calendarEvent, {
rescheduleLink: builder.rescheduleLink,
});
const evt: CalendarEvent = {
title: bookingToReschedule?.title,
type: event && event.title ? event.title : bookingToReschedule.title,
description: bookingToReschedule?.description || "",
customInputs: isPrismaObjOrUndefined(bookingToReschedule.customInputs),
...getCalEventResponses({
booking: bookingToReschedule,
bookingFields: bookingToReschedule.eventType?.bookingFields ?? null,
}),
startTime: bookingToReschedule?.startTime ? dayjs(bookingToReschedule.startTime).format() : "",
endTime: bookingToReschedule?.endTime ? dayjs(bookingToReschedule.endTime).format() : "",
organizer: userAsPeopleType,
attendees: usersToPeopleType(
// username field doesn't exists on attendee but could be in the future
bookingToReschedule.attendees as unknown as PersonAttendeeCommonFields[],
tAttendees
),
uid: bookingToReschedule?.uid,
location: bookingToReschedule?.location,
destinationCalendar:
bookingToReschedule?.destinationCalendar || bookingToReschedule?.destinationCalendar,
cancellationReason: `Please reschedule. ${cancellationReason}`, // TODO::Add i18-next for this
};
// Send webhook
const eventTrigger: WebhookTriggerEvents = "BOOKING_CANCELLED";
const teamId = await getTeamIdFromEventType({
eventType: {
team: { id: bookingToReschedule.eventType?.teamId ?? null },
parentId: bookingToReschedule?.eventType?.parentId ?? null,
},
});
const triggerForUser = !teamId || (teamId && bookingToReschedule.eventType?.parentId);
// Send Webhook call if hooked to BOOKING.CANCELLED
const subscriberOptions = {
userId: triggerForUser ? bookingToReschedule.userId : null,
eventTypeId: bookingToReschedule.eventTypeId as number,
triggerEvent: eventTrigger,
teamId,
};
const webhooks = await getWebhooks(subscriberOptions);
const promises = webhooks.map((webhook) =>
sendPayload(webhook.secret, eventTrigger, new Date().toISOString(), webhook, {
...evt,
smsReminderNumber: bookingToReschedule.smsReminderNumber || undefined,
}).catch((e) => {
console.error(`Error executing webhook for event: ${eventTrigger}, URL: ${webhook.subscriberUrl}`, e);
})
);
await Promise.all(promises);
} }
await prisma.booking.update({
where: {
id: bookingToReschedule.id,
},
data: {
rescheduled: true,
cancellationReason,
status: BookingStatus.CANCELLED,
updatedAt: dayjs().toISOString(),
},
});
// delete scheduled jobs of previous booking
// FIXME: async fn off into the ether
cancelScheduledJobs(bookingToReschedule);
//cancel workflow reminders of previous booking
// FIXME: more async fns off into the ether
bookingToReschedule.workflowReminders.forEach((reminder) => {
if (reminder.method === WorkflowMethods.EMAIL) {
deleteScheduledEmailReminder(reminder.id, reminder.referenceId);
} else if (reminder.method === WorkflowMethods.SMS) {
deleteScheduledSMSReminder(reminder.id, reminder.referenceId);
} else if (reminder.method === WorkflowMethods.WHATSAPP) {
deleteScheduledWhatsappReminder(reminder.id, reminder.referenceId);
}
});
const [mainAttendee] = bookingToReschedule.attendees;
// @NOTE: Should we assume attendees language?
const tAttendees = await getTranslation(mainAttendee.locale ?? "en", "common");
const usersToPeopleType = (users: PersonAttendeeCommonFields[], selectedLanguage: TFunction): Person[] => {
return users?.map((user) => {
return {
email: user.email || "",
name: user.name || "",
username: user?.username || "",
language: { translate: selectedLanguage, locale: user.locale || "en" },
timeZone: user?.timeZone,
};
});
};
const userTranslation = await getTranslation(user.locale ?? "en", "common");
const [userAsPeopleType] = usersToPeopleType([user], userTranslation);
const builder = new CalendarEventBuilder();
builder.init({
title: bookingToReschedule.title,
type: event && event.title ? event.title : bookingToReschedule.title,
startTime: bookingToReschedule.startTime.toISOString(),
endTime: bookingToReschedule.endTime.toISOString(),
attendees: usersToPeopleType(
// username field doesn't exists on attendee but could be in the future
bookingToReschedule.attendees as unknown as PersonAttendeeCommonFields[],
tAttendees
),
organizer: userAsPeopleType,
});
const director = new CalendarEventDirector();
director.setBuilder(builder);
director.setExistingBooking(bookingToReschedule);
cancellationReason && director.setCancellationReason(cancellationReason);
if (event) {
await director.buildForRescheduleEmail();
} else {
await director.buildWithoutEventTypeForRescheduleEmail();
}
// Handling calendar and videos cancellation
// This can set previous time as available, until virtual calendar is done
const credentials = await getUsersCredentials(user.id);
const credentialsMap = new Map();
credentials.forEach((credential) => {
credentialsMap.set(credential.type, credential);
});
const bookingRefsFiltered: BookingReference[] = bookingToReschedule.references.filter((ref) =>
credentialsMap.has(ref.type)
);
// FIXME: error-handling
await Promise.allSettled(
bookingRefsFiltered.map(async (bookingRef) => {
if (!bookingRef.uid) return;
if (bookingRef.type.endsWith("_calendar")) {
const calendar = await getCalendar(credentialsMap.get(bookingRef.type));
return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent, bookingRef.externalCalendarId);
} else if (bookingRef.type.endsWith("_video")) {
return deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
}
})
);
// Send emails
await sendRequestRescheduleEmail(builder.calendarEvent, {
rescheduleLink: builder.rescheduleLink,
});
const evt: CalendarEvent = {
title: bookingToReschedule?.title,
type: event && event.title ? event.title : bookingToReschedule.title,
description: bookingToReschedule?.description || "",
customInputs: isPrismaObjOrUndefined(bookingToReschedule.customInputs),
...getCalEventResponses({
booking: bookingToReschedule,
bookingFields: bookingToReschedule.eventType?.bookingFields ?? null,
}),
startTime: bookingToReschedule?.startTime ? dayjs(bookingToReschedule.startTime).format() : "",
endTime: bookingToReschedule?.endTime ? dayjs(bookingToReschedule.endTime).format() : "",
organizer: userAsPeopleType,
attendees: usersToPeopleType(
// username field doesn't exists on attendee but could be in the future
bookingToReschedule.attendees as unknown as PersonAttendeeCommonFields[],
tAttendees
),
uid: bookingToReschedule?.uid,
location: bookingToReschedule?.location,
destinationCalendar: bookingToReschedule?.destinationCalendar || bookingToReschedule?.destinationCalendar,
cancellationReason: `Please reschedule. ${cancellationReason}`, // TODO::Add i18-next for this
};
// Send webhook
const eventTrigger: WebhookTriggerEvents = "BOOKING_CANCELLED";
const teamId = await getTeamIdFromEventType({
eventType: {
team: { id: bookingToReschedule.eventType?.teamId ?? null },
parentId: bookingToReschedule?.eventType?.parentId ?? null,
},
});
const triggerForUser = !teamId || (teamId && bookingToReschedule.eventType?.parentId);
// Send Webhook call if hooked to BOOKING.CANCELLED
const subscriberOptions = {
userId: triggerForUser ? bookingToReschedule.userId : null,
eventTypeId: bookingToReschedule.eventTypeId as number,
triggerEvent: eventTrigger,
teamId,
};
const webhooks = await getWebhooks(subscriberOptions);
const promises = webhooks.map((webhook) =>
sendPayload(webhook.secret, eventTrigger, new Date().toISOString(), webhook, {
...evt,
smsReminderNumber: bookingToReschedule.smsReminderNumber || undefined,
}).catch((e) => {
console.error(`Error executing webhook for event: ${eventTrigger}, URL: ${webhook.subscriberUrl}`, e);
})
);
await Promise.all(promises);
}; };

View File

@ -264,13 +264,13 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
}, },
}); });
steps.forEach(async (step) => { const promiseSteps = steps.map(async (step) => {
if ( if (
step.action !== WorkflowActions.SMS_ATTENDEE && step.action !== WorkflowActions.SMS_ATTENDEE &&
step.action !== WorkflowActions.WHATSAPP_ATTENDEE step.action !== WorkflowActions.WHATSAPP_ATTENDEE
) { ) {
//as we do not have attendees phone number (user is notified about that when setting this action) //as we do not have attendees phone number (user is notified about that when setting this action)
bookingsForReminders.forEach(async (booking) => { const promiseScheduleReminders = bookingsForReminders.map(async (booking) => {
const defaultLocale = "en"; const defaultLocale = "en";
const bookingInfo = { const bookingInfo = {
uid: booking.uid, uid: booking.uid,
@ -367,29 +367,28 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
); );
} }
}); });
await Promise.all(promiseScheduleReminders);
} }
}); });
await Promise.all(promiseSteps);
} }
//create all workflow - eventtypes relationships //create all workflow - eventtypes relationships
activeOnEventTypes.forEach(async (eventType) => { await ctx.prisma.workflowsOnEventTypes.createMany({
await ctx.prisma.workflowsOnEventTypes.createMany({ data: activeOnEventTypes.map((eventType) => ({
data: { workflowId: id,
workflowId: id, eventTypeId: eventType.id,
eventTypeId: eventType.id, })),
},
});
if (eventType.children.length) {
eventType.children.forEach(async (chEventType) => {
await ctx.prisma.workflowsOnEventTypes.createMany({
data: {
workflowId: id,
eventTypeId: chEventType.id,
},
});
});
}
}); });
await Promise.all(
activeOnEventTypes.map((eventType) =>
ctx.prisma.workflowsOnEventTypes.createMany({
data: eventType.children.map((chEventType) => ({
workflowId: id,
eventTypeId: chEventType.id,
})),
})
)
);
} }
userWorkflow.steps.map(async (oldStep) => { userWorkflow.steps.map(async (oldStep) => {
@ -465,11 +464,14 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
}); });
//cancel all workflow reminders from steps that were edited //cancel all workflow reminders from steps that were edited
remindersToUpdate.forEach(async (reminder) => { // FIXME: async calls into ether
remindersToUpdate.forEach((reminder) => {
if (reminder.method === WorkflowMethods.EMAIL) { if (reminder.method === WorkflowMethods.EMAIL) {
deleteScheduledEmailReminder(reminder.id, reminder.referenceId); deleteScheduledEmailReminder(reminder.id, reminder.referenceId);
} else if (reminder.method === WorkflowMethods.SMS) { } else if (reminder.method === WorkflowMethods.SMS) {
deleteScheduledSMSReminder(reminder.id, reminder.referenceId); deleteScheduledSMSReminder(reminder.id, reminder.referenceId);
} else if (reminder.method === WorkflowMethods.WHATSAPP) {
deleteScheduledWhatsappReminder(reminder.id, reminder.referenceId);
} }
}); });
const eventTypesToUpdateReminders = activeOn.filter((eventTypeId) => { const eventTypesToUpdateReminders = activeOn.filter((eventTypeId) => {
@ -497,7 +499,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
user: true, user: true,
}, },
}); });
bookingsOfEventTypes.forEach(async (booking) => { const promiseScheduleReminders = bookingsOfEventTypes.map(async (booking) => {
const defaultLocale = "en"; const defaultLocale = "en";
const bookingInfo = { const bookingInfo = {
uid: booking.uid, uid: booking.uid,
@ -594,6 +596,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
); );
} }
}); });
await Promise.all(promiseScheduleReminders);
} }
} }
}); });
@ -617,7 +620,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
return activeEventType; return activeEventType;
} }
}); });
addedSteps.forEach(async (step) => { const promiseAddedSteps = addedSteps.map(async (step) => {
if (step) { if (step) {
const { senderName, ...newStep } = step; const { senderName, ...newStep } = step;
newStep.sender = getSender({ newStep.sender = getSender({
@ -749,6 +752,7 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
} }
} }
}); });
await Promise.all(promiseAddedSteps);
} }
//update trigger, name, time, timeUnit //update trigger, name, time, timeUnit