Throttle email notifications upon updating document frequently (#4026)
* feat: add needed columns for throttling notifs * feat: update model * feat: deliver only one notif in a 12 hour window * fix: address review comments * prevent retry if notification update fails * fix type compatibility instead of circumventing it * add index for emailedAt * fix: add metadata attr to EmailProps * chore: decouple metadata from EmailProps * chore: add test * chore: revert sending metadata in props
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
import mailer from "@server/emails/mailer";
|
||||
import Logger from "@server/logging/Logger";
|
||||
import Metrics from "@server/logging/metrics";
|
||||
import Notification from "@server/models/Notification";
|
||||
import { taskQueue } from "@server/queues";
|
||||
import { TaskPriority } from "@server/queues/tasks/BaseTask";
|
||||
import { NotificationMetadata } from "@server/types";
|
||||
|
||||
interface EmailProps {
|
||||
to: string;
|
||||
}
|
||||
|
||||
export default abstract class BaseEmail<T extends EmailProps, S = any> {
|
||||
export default abstract class BaseEmail<T extends EmailProps, S = unknown> {
|
||||
private props: T;
|
||||
private metadata?: NotificationMetadata;
|
||||
|
||||
/**
|
||||
* Schedule this email type to be sent asyncronously by a worker.
|
||||
@@ -17,7 +20,7 @@ export default abstract class BaseEmail<T extends EmailProps, S = any> {
|
||||
* @param props Properties to be used in the email template
|
||||
* @returns A promise that resolves once the email is placed on the task queue
|
||||
*/
|
||||
public static schedule<T>(props: T) {
|
||||
public static schedule<T>(props: T, metadata?: NotificationMetadata) {
|
||||
const templateName = this.name;
|
||||
|
||||
Metrics.increment("email.scheduled", {
|
||||
@@ -31,6 +34,7 @@ export default abstract class BaseEmail<T extends EmailProps, S = any> {
|
||||
name: "EmailTask",
|
||||
props: {
|
||||
templateName,
|
||||
...metadata,
|
||||
props,
|
||||
},
|
||||
},
|
||||
@@ -45,8 +49,9 @@ export default abstract class BaseEmail<T extends EmailProps, S = any> {
|
||||
);
|
||||
}
|
||||
|
||||
constructor(props: T) {
|
||||
constructor(props: T, metadata?: NotificationMetadata) {
|
||||
this.props = props;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,6 +91,23 @@ export default abstract class BaseEmail<T extends EmailProps, S = any> {
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (this.metadata?.notificationId) {
|
||||
try {
|
||||
await Notification.update(
|
||||
{
|
||||
emailedAt: new Date(),
|
||||
},
|
||||
{
|
||||
where: {
|
||||
id: this.metadata.notificationId,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (err) {
|
||||
Logger.error(`Failed to update notification`, err, this.metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user