Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated notification support #131

Closed
wants to merge 13 commits into from
Closed

Updated notification support #131

wants to merge 13 commits into from

Conversation

solocommand
Copy link
Contributor

Resolves #49

  • When creating or modifying a campaign, all configured notifications are created or updated to be sent in the future.
  • If an email has already been sent, the notification is updated but the status is left unchanged.
  • If an email errored on send, it is recreated to retry sending.
  • If an email has not yet been sent, the dates and other fields are updated to match the latest change.
  • A node cron process checks every 10 minutes to see if there are any unsent notifications
    • If any are found, they are findAndModified within a loop to start the async send handler
  • Updates to use account service data and virtual fields for URIs
  • Remove link-to handler

@@ -20,6 +20,12 @@ const getNotifyDefaults = async (advertiserId, user) => {
return notify;
};

const updateNotifications = async (campaignId) => {
contactNotifier.scheduleCampaignCreated({ campaignId });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updateNotifications isn't awaiting the scheduled email calls, is that intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

@@ -20,6 +20,12 @@ const getNotifyDefaults = async (advertiserId, user) => {
return notify;
};

const updateNotifications = async (campaignId) => {
contactNotifier.scheduleCampaignCreated({ campaignId });
contactNotifier.scheduleCampaignStarted({ campaignId });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, have a look at the each function within the async package. These are probably a good candidates for running in parallel.
https://caolan.github.io/async/docs.html#each

@@ -148,16 +159,20 @@ module.exports = {
const campaign = await Campaign.findById(campaignId);
if (!campaign) throw new Error(`Unable to set campaign URL: no campaign found for '${campaignId}'`);
campaign.url = url;
return campaign.save();
await campaign.save();
await updateNotifications(campaignId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does updateNotifications need to be called on every mutation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO yes, as any campaign field could be used within the email message itself, and changes to criteria would necessitate changes to delivery

required: true,
validate: {
async validator(v) {
const doc = await connection.model('campaign').findOne({ _id: v }, { _id: 1 });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to .findById(v, { _id: 1 })
My bad for not doing that before you Cmd C+V

cc: [String],
bcc: [String],

subject: String,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should subject, text, and html all be required? Well, maybe not text

// Run every 10 minutes
const job = new CronJob({
cronTime: '* */10 * * * *',
onTick: this.check,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need a bind?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the context: this parameter handles the binding

async sendInternalCampaignCreated({ campaign }) {
const html = await emailTemplates.render('internal/campaign.created', { campaign });
async scheduleCampaignCreated({ campaignId }) {
const campaign = await Campaign.findOne({ _id: campaignId });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findById

},

async scheduleCampaignEnded({ campaignId }) {
const campaign = await Campaign.findOne({ _id: campaignId });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findById

const html = await emailTemplates.render('external/campaign.created', { campaign });
const subject = 'A new campaign was created!';
async scheduleCampaignStarted({ campaignId }) {
const campaign = await Campaign.findOne({ _id: campaignId });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findById

const to = await this.resolveAddresses(campaign.get('notify.internal'));
return this.send({ to, subject, html });
const to = await this.resolveAddresses(campaign.get('notify.external'));
const cc = await this.resolveAddresses(campaign.get('notify.internal'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these functions seem pretty repetitive... any way we can clean them up / consolidate?

notification.set('status', 'Sent');
output.write('✉️ ✉️ ✉️ Successfully sent a notification!');
} catch (e) {
notification.set('error', e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to make it more clear... e.message please :)

} catch (e) {
notification.set('error', e);
notification.set('status', 'Errored');
notification.save();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants