|
| 1 | +module EmailAllPetitionSignatories |
| 2 | + extend ActiveSupport::Concern |
| 3 | + |
| 4 | + # |
| 5 | + # Concern to add shared functionality to ActiveJob classes that are responsible |
| 6 | + # for enqueuing send email jobs |
| 7 | + # |
| 8 | + |
| 9 | + included do |
| 10 | + queue_as :default |
| 11 | + |
| 12 | + def self.run_later_tonight(petition) |
| 13 | + requested_at = Time.current |
| 14 | + |
| 15 | + petition.set_email_requested_at_for(new.timestamp_name, to: requested_at) |
| 16 | + |
| 17 | + set(wait_until: later_tonight). |
| 18 | + perform_later(petition, requested_at.getutc.iso8601(6)) |
| 19 | + end |
| 20 | + |
| 21 | + def self.later_tonight |
| 22 | + 1.day.from_now.at_midnight + rand(240).minutes + rand(60).seconds |
| 23 | + end |
| 24 | + private_class_method :later_tonight |
| 25 | + |
| 26 | + end |
| 27 | + |
| 28 | + |
| 29 | + |
| 30 | + def perform(petition, requested_at_string) |
| 31 | + @petition = petition |
| 32 | + @requested_at = requested_at_string.in_time_zone |
| 33 | + do_work! |
| 34 | + end |
| 35 | + |
| 36 | + def timestamp_name |
| 37 | + raise NotImplementedError.new "Including classes must implement #timestamp_name method" |
| 38 | + end |
| 39 | + |
| 40 | + private |
| 41 | + |
| 42 | + attr_reader :petition, :requested_at |
| 43 | + |
| 44 | + def do_work! |
| 45 | + return if petition_has_been_updated? |
| 46 | + |
| 47 | + logger.info("Starting #{self.class.name} for petition '#{petition.action}' with email requested at: #{petition_timestamp}") |
| 48 | + enqueue_send_email_jobs |
| 49 | + logger.info("Finished #{self.class.name} for petition '#{petition.action}'") |
| 50 | + |
| 51 | + end |
| 52 | + |
| 53 | + # |
| 54 | + # Batches the signataries to send emails to in groups of 1000 |
| 55 | + # and enqueues a job to do the actual sending |
| 56 | + # |
| 57 | + def enqueue_send_email_jobs |
| 58 | + signatures_to_email.find_each do |signature| |
| 59 | + email_delivery_job_class.perform_later( |
| 60 | + signature: signature, |
| 61 | + timestamp_name: timestamp_name, |
| 62 | + petition: petition, |
| 63 | + requested_at_as_string: requested_at.getutc.iso8601(6) |
| 64 | + ) |
| 65 | + end |
| 66 | + end |
| 67 | + |
| 68 | + # admins can ask to send the email multiple times and each time they |
| 69 | + # ask we enqueues a new job to send out emails with a new timestamp |
| 70 | + # we want to execute only the latest job enqueued |
| 71 | + def petition_has_been_updated? |
| 72 | + (petition_timestamp - requested_at).abs > 1 |
| 73 | + end |
| 74 | + |
| 75 | + def petition_timestamp |
| 76 | + petition.get_email_requested_at_for(timestamp_name) |
| 77 | + end |
| 78 | + |
| 79 | + def signatures_to_email |
| 80 | + petition.signatures_to_email_for(timestamp_name) |
| 81 | + end |
| 82 | + |
| 83 | + # The job class that handles the actual email sending for this job type |
| 84 | + def email_delivery_job_class |
| 85 | + raise NotImplementedError.new "Including classes must implement #email_delivery_job_class method" |
| 86 | + end |
| 87 | +end |
| 88 | + |
| 89 | + |
0 commit comments