Class: EmailEngagementRollupWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job
Defined in:
app/workers/email_engagement_rollup_worker.rb

Overview

Rolls a day's email engagement into EmailTemplateDataPoint.

webhook_events retains ~3 months. Counts survive that (terminal state on
communication_recipients is durable) but timing does not — median
hours-to-open and the within-24h rate are unrecoverable once the events age
out. This runs nightly so that history accrues instead of rolling off.

Idempotent: Models::DataPointMetrics.upsert_data_points! upserts on
(email_template_id, metric_type, period, reference), so re-running a day
overwrites rather than duplicates. Safe to backfill by looping days.

Constant Summary collapse

DELIVERED_STATES =

Recipient states that mean the message reached the mailbox.

%w[processed delivered opened clicked spammed unsubscribed ok].freeze
OPENED_STATES =

Recipient states that count as having been opened at least once.

%w[opened clicked].freeze

Instance Method Summary collapse

Instance Method Details

#perform(date = nil) ⇒ Object

Parameters:

  • date (String, nil) (defaults to: nil)

    ISO date to roll up; defaults to yesterday



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'app/workers/email_engagement_rollup_worker.rb', line 24

def perform(date = nil)
  day = date.present? ? Date.parse(date) : Date.current - 1
  batch_id = SecureRandom.uuid

  # One query for all of them — find_by per id added a round trip per
  # template on top of the two aggregates each already costs.
  templates = EmailTemplate.where(id: template_ids(day)).to_a

  templates.each do |template|
    EmailTemplateDataPoint.bulk_record!(
      email_template: template,
      period_start: day,
      period_end: day,
      metrics: metrics_for(template.id, day),
      source_batch_id: batch_id
    )
  end

  Rails.logger.info "[EmailEngagementRollup] #{day}: rolled up #{templates.size} template(s)"
end