From 6631071dd353675107e4b983c969320820ccad25 Mon Sep 17 00:00:00 2001 From: Simon Backx Date: Thu, 26 Jan 2023 16:06:15 +0100 Subject: [PATCH] Improved handling large amounts of email events (#16189) refs https://github.com/TryGhost/Team/issues/2486 Stop the event fetching loop as soon as we receive events that were created later then when we started the loop. This ensures that we don't miss events if we receive a giant batch of events that take a long time to process. --- ghost/mailgun-client/lib/mailgun-client.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ghost/mailgun-client/lib/mailgun-client.js b/ghost/mailgun-client/lib/mailgun-client.js index f56d0343ac..5ede93ef03 100644 --- a/ghost/mailgun-client/lib/mailgun-client.js +++ b/ghost/mailgun-client/lib/mailgun-client.js @@ -119,13 +119,16 @@ module.exports = class MailgunClient { debug(`fetchEvents: starting fetching first events page`); const mailgunConfig = this.#getConfig(); let startTime = Date.now(); + const startDate = new Date(); try { let page = await mailgunInstance.events.get(mailgunConfig.domain, mailgunOptions); metrics.metric('mailgun-get-events', { value: Date.now() - startTime, statusCode: 200 }); - let events = (page?.items?.map(this.normalizeEvent) || []).filter(e => !!e); + // By limiting the processed events to ones created before this job started we cancel early ready for the next job run. + // Avoids chance of events being missed in long job runs due to mailgun's eventual-consistency creating events outside of our 30min sliding re-check window + let events = (page?.items?.map(this.normalizeEvent) || []).filter(e => !!e && e.timestamp <= startDate); debug(`fetchEvents: finished fetching first page with ${events.length} events`); let eventCount = 0; @@ -152,7 +155,8 @@ module.exports = class MailgunClient { value: Date.now() - startTime, statusCode: 200 }); - events = (page?.items?.map(this.normalizeEvent) || []).filter(e => !!e); + // We need to cap events at the time we started fetching them (see comment above) + events = (page?.items?.map(this.normalizeEvent) || []).filter(e => !!e && e.timestamp <= startDate); debug(`fetchEvents: finished fetching next page with ${events.length} events`); }