1module EmailAllPetitionSignatories
 
2  # Concern to add shared functionality to ActiveJob classes
 
3  # that are responsible for enqueuing send email jobs
 
4
 
5  extend ActiveSupport::Concern
 
6
 
7  included do
 
8    before_perform :set_appsignal_namespace
 
 9
 
10    class_attribute :email_delivery_job_class
 
11    class_attribute :timestamp_name
 
 
13    attr_reader :petition, :requested_at
 
 
15    queue_as :high_priority
 
16  end
 
 
18  module ClassMethods
 
19    def run_later_tonight(**args)
 
20      petition, @requested_at = args[:petition], nil
 
 
22      petition.set_email_requested_at_for(timestamp_name, to: requested_at)
 
23      set(wait_until: later_tonight).perform_later(**args.merge(requested_at: requested_at_iso8601))
 
24    end
 
 
26    private
 
 
28    def requested_at
 
29      @requested_at ||= Time.current
 
30    end
 
 
32    def requested_at_iso8601
 
33      requested_at.getutc.iso8601(6)
 
34    end
 
 
36    def later_tonight
 
37      midnight + random_interval
 
38    end
 
 
40    def midnight
 
41      requested_at.end_of_day
 
42    end
 
 
44    def random_interval
 
45      rand(240).minutes + rand(60).seconds
 
46    end
 
47  end
 
  • Complexity 2 » saikuro
49  def perform(**args)
 
50    @petition, @requested_at = args[:petition], args[:requested_at]
 
 
52    # If the petition has been updated since the job
 
53    # was queued then don't send the emails.
 
54    unless petition_has_been_updated?
 
55      enqueue_send_email_jobs
 
56    end
 
57  end
 
 
59  private
 
 
61  # Batches the signataries to send emails to in groups of 1000
 
62  # and enqueues a job to do the actual sending
  • Complexity 3 » saikuro
63  def enqueue_send_email_jobs
 
64    Appsignal.without_instrumentation do
 
65      signatures_to_email.find_each do |signature|
 
66        email_delivery_job_class.perform_later(**mailer_arguments(signature))
 
67      end
 
68    end
 
69  end
 
  • Complexity 1 » saikuro
71  def mailer_arguments(signature)
 
72    {
 
73      signature:      signature,
 
74      timestamp_name: timestamp_name,
 
75      petition:       petition,
 
76      requested_at:   requested_at
 
77    }
 
78  end
 
 
80  # admins can ask to send the email multiple times and each time they
 
81  # ask we enqueues a new job to send out emails with a new timestamp
 
82  # we want to execute only the latest job enqueued
  • Complexity 1 » saikuro
83  def petition_has_been_updated?
 
84    (petition_timestamp - requested_at.in_time_zone).abs > 1
 
85  end
 
  • Complexity 1 » saikuro
87  def petition_timestamp
 
88    petition.get_email_requested_at_for(timestamp_name)
 
89  end
 
  • Complexity 1 » saikuro
91  def signatures_to_email
 
92    petition.signatures_to_email_for(timestamp_name)
 
93  end
 
  • UtilityFunction - doesn't depend on instance state (maybe move it to another class?) » reek
  • Complexity 1 » saikuro
95  def set_appsignal_namespace
 
96    Appsignal.set_namespace("email")
 
97  end
 
98end