Ghost/core/server/services/email-analytics/lib/event-processing-result.js
Kevin Ansfield 717543835c
Added email analytics service (#12393)
no issue

- added `EmailAnalyticsService`
  - `.fetchAll()` grabs and processes all available events
  - `.fetchLatest()` grabs and processes all events since the last seen event timestamp
  - `EventProcessor` passed event objects and updates `email_recipients` or `members` records depending on the event being analytics or list hygiene
    - always returns a `EventProcessingResult` instance so that progress can be tracked and merged across individual events, batches (pages of events), and total runs
    - adds email_id and member_id to the returned result where appropriate so that the stats aggregator can limit processing to data that has changed
    - sets `email_recipients.{delivered_at, opened_at, failed_at}` for analytics events
    - sets `members.subscribed = false` for permanent failure/unsubscribed/complained list hygiene events
  - `StatsAggregator` takes an `EventProcessingResult`-like object containing arrays of email ids and member ids on which to aggregate statistics.
  - jobs for `fetch-latest` and `fetch-all` ready for use with the JobsService
- added `initialiseRecurringJobs()` function to Ghost bootup procedure that schedules the email analytics "fetch latest" job to run every minute
2020-11-26 13:09:38 +00:00

46 lines
1.3 KiB
JavaScript

const _ = require('lodash');
class EventProcessingResult {
constructor(result = {}) {
// counts
this.delivered = 0;
this.opened = 0;
this.failed = 0;
this.unsubscribed = 0;
this.complained = 0;
this.unhandled = 0;
this.unprocessable = 0;
// ids seen whilst processing ready for passing to the stats aggregator
this.emailIds = [];
this.memberIds = [];
this.merge(result);
}
get totalEvents() {
return this.delivered
+ this.opened
+ this.failed
+ this.unsubscribed
+ this.complained
+ this.unhandled
+ this.unprocessable;
}
merge(other = {}) {
this.delivered += other.delivered || 0;
this.opened += other.opened || 0;
this.failed += other.failed || 0;
this.unsubscribed += other.unsubscribed || 0;
this.complained += other.complained || 0;
this.unhandled += other.unhandled || 0;
this.unprocessable += other.unprocessable || 0;
this.emailIds = _.compact(_.union(this.emailIds, other.emailIds || []));
this.memberIds = _.compact(_.union(this.memberIds, other.memberIds || []));
}
}
module.exports = EventProcessingResult;