Class: MailyHerald::Sequence
- Includes:
- Autonaming
- Defined in:
- app/models/maily_herald/sequence.rb
Instance Attribute Summary
Attributes inherited from Dispatch
#absolute_delay, #conditions, #from, #list_id, #mailer_name, #name, #override_subscription, #period, #sequence_id, #state, #subject, #template, #title, #type
Instance Method Summary collapse
-
#calculate_processing_time_for(entity, mailing = nil) ⇒ Object
Calculates processing time for given entity.
-
#last_processed_mailing(entity) ⇒ Object
Gets last SequenceMailing object delivered to user.
-
#last_processing_time(entity) ⇒ Object
Gets the timestamp of last processed email for given entity.
-
#mailing(name, options = {}) ⇒ Object
Fetches or defines an SequenceMailing.
- #mailing_processing_log_for(entity, mailing) ⇒ Object
-
#next_mailing(entity) ⇒ Object
Gets next SequenceMailing object to be delivered to user.
-
#next_processing_time(entity) ⇒ Object
Get next email processing time for given entity.
-
#pending_mailings(entity) ⇒ Object
Gets collection of SequenceMailing objects that are to be sent to entity.
-
#processed_logs(entity) ⇒ Object
Returns collection of processed Logs for given entity.
-
#processed_logs_for(entity, mailing) ⇒ Object
Returns collection of processed Logs for given entity and mailing.
-
#processed_mailings(entity) ⇒ Object
Gets collection of SequenceMailing objects that were sent to entity.
-
#run ⇒ Object
Sends sequence mailings to all subscribed entities.
-
#schedule_for(entity) ⇒ Object
Returns Log object which is the delivery schedule for given entity.
-
#schedules ⇒ Object
Returns collection of all delivery schedules (Log collection).
-
#set_schedule_for(entity) ⇒ Object
Sets the delivery schedule for given entity.
-
#set_schedules ⇒ Object
Sets delivery schedules of all entities in mailing scope.
- #to_s ⇒ Object
- #update_schedules_callback ⇒ Object
Methods included from Autonaming
Methods inherited from Dispatch
#archive, #archive!, #archived?, #disable, #disable!, #disabled?, #enable, #enable!, #enabled?, #has_start_at_proc?, #in_scope?, #list=, #locked?, #processable?, #start_at, #start_at=, #start_at_changed?, #subscription_valid?
Instance Method Details
#calculate_processing_time_for(entity, mailing = nil) ⇒ Object
Calculates processing time for given entity.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'app/models/maily_herald/sequence.rb', line 181 def calculate_processing_time_for entity, mailing = nil mailing ||= next_mailing(entity) ls = processed_logs(entity) if ls.first ls.last.processing_at + (mailing.absolute_delay - ls.last.mailing.absolute_delay) else subscription = self.list.subscription_for(entity) if has_start_at_proc? evaluated_start = start_at.call(entity, subscription) else evaluator = Utils::MarkupEvaluator.new(self.list.context.drop_for(entity, subscription)) evaluated_start = evaluator.evaluate_start_at(self.start_at) end evaluated_start ? evaluated_start + mailing.absolute_delay : nil end end |
#last_processed_mailing(entity) ⇒ Object
Gets last MailyHerald::SequenceMailing object delivered to user.
113 114 115 |
# File 'app/models/maily_herald/sequence.rb', line 113 def last_processed_mailing entity processed_mailings(entity).last end |
#last_processing_time(entity) ⇒ Object
Gets the timestamp of last processed email for given entity.
95 96 97 98 |
# File 'app/models/maily_herald/sequence.rb', line 95 def last_processing_time entity ls = processed_logs(entity) ls.last.processing_at if ls.last end |
#mailing(name, options = {}) ⇒ Object
Fetches or defines an MailyHerald::SequenceMailing.
If no block provided, MailyHerald::SequenceMailing with given name
is returned.
If block provided, MailyHerald::SequenceMailing with given name
is created or edited and block is evaluated within that mailing.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'app/models/maily_herald/sequence.rb', line 41 def mailing name, = {} if SequenceMailing.table_exists? mailing = SequenceMailing.find_by_name(name) lock = .delete(:locked) if block_given? && !MailyHerald.dispatch_locked?(name) && (!mailing || lock) mailing ||= self.mailings.build(name: name) mailing.sequence = self yield(mailing) mailing.skip_updating_schedules = true if self.new_record? mailing.save! MailyHerald.lock_dispatch(name) if lock end mailing end end |
#mailing_processing_log_for(entity, mailing) ⇒ Object
122 123 124 |
# File 'app/models/maily_herald/sequence.rb', line 122 def mailing_processing_log_for entity, mailing Log.ordered.processed.for_entity(entity).for_mailing(mailing).last end |
#next_mailing(entity) ⇒ Object
Gets next MailyHerald::SequenceMailing object to be delivered to user.
118 119 120 |
# File 'app/models/maily_herald/sequence.rb', line 118 def next_mailing entity pending_mailings(entity).first end |
#next_processing_time(entity) ⇒ Object
Get next email processing time for given entity.
203 204 205 |
# File 'app/models/maily_herald/sequence.rb', line 203 def next_processing_time entity schedule_for(entity).try(:processing_at) end |
#pending_mailings(entity) ⇒ Object
Gets collection of MailyHerald::SequenceMailing objects that are to be sent to entity.
101 102 103 104 |
# File 'app/models/maily_herald/sequence.rb', line 101 def pending_mailings entity ls = processed_logs(entity) ls.empty? ? self.mailings.enabled : self.mailings.enabled.where("id not in (?)", ls.map(&:mailing_id)) end |
#processed_logs(entity) ⇒ Object
Returns collection of processed Logs for given entity.
82 83 84 |
# File 'app/models/maily_herald/sequence.rb', line 82 def processed_logs entity Log.ordered.processed.for_entity(entity).for_mailings(self.mailings.select(:id)) end |
#processed_logs_for(entity, mailing) ⇒ Object
Returns collection of processed Logs for given entity and mailing.
90 91 92 |
# File 'app/models/maily_herald/sequence.rb', line 90 def processed_logs_for entity, mailing Log.ordered.processed.for_entity(entity).for_mailing(self.mailings.find(mailing)) end |
#processed_mailings(entity) ⇒ Object
Gets collection of MailyHerald::SequenceMailing objects that were sent to entity.
107 108 109 110 |
# File 'app/models/maily_herald/sequence.rb', line 107 def processed_mailings entity ls = processed_logs(entity) ls.empty? ? self.mailings.where(id: nil) : self.mailings.where("id in (?)", ls.map(&:mailing_id)) end |
#run ⇒ Object
Sends sequence mailings to all subscribed entities.
Performs actual sending of emails; should be called in background.
Returns array of Log with actual ‘Mail::Message` objects stored in Log.mail attributes.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'app/models/maily_herald/sequence.rb', line 66 def run # TODO better scope here to exclude schedules for users outside context scope schedules.where("processing_at <= (?)", Time.now).each do |schedule| if schedule.entity mail = schedule.mailing.send(:deliver, schedule) schedule.reload schedule.mail = mail schedule else MailyHerald.logger.log_processing(schedule.mailing, {class: schedule.entity_type, id: schedule.entity_id}, prefix: "Removing schedule for non-existing entity") schedule.destroy end end end |
#schedule_for(entity) ⇒ Object
Returns Log object which is the delivery schedule for given entity.
171 172 173 |
# File 'app/models/maily_herald/sequence.rb', line 171 def schedule_for entity schedules.for_entity(entity).first end |
#schedules ⇒ Object
Returns collection of all delivery schedules (Log collection).
176 177 178 |
# File 'app/models/maily_herald/sequence.rb', line 176 def schedules Log.ordered.scheduled.for_mailings(self.mailings.select(:id)) end |
#set_schedule_for(entity) ⇒ Object
Sets the delivery schedule for given entity
New schedule will be created or existing one updated.
Schedule is Log object of type “schedule”.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'app/models/maily_herald/sequence.rb', line 131 def set_schedule_for entity # TODO handle override subscription? subscribed = self.list.subscribed?(entity) mailing = next_mailing(entity) start_time = calculate_processing_time_for(entity, mailing) if mailing if !subscribed || !self.start_at || !enabled? || !mailing || !start_time log = schedule_for(entity) log.try(:destroy) return end log = schedule_for(entity) log ||= Log.new log.with_lock do log.set_attributes_for(mailing, entity, { status: :scheduled, processing_at: start_time, }) log.save! end log end |
#set_schedules ⇒ Object
Sets delivery schedules of all entities in mailing scope.
New schedules will be created or existing ones updated.
159 160 161 162 163 164 |
# File 'app/models/maily_herald/sequence.rb', line 159 def set_schedules self.list.context.scope_with_subscription(self.list, :outer).each do |entity| MailyHerald.logger.debug "Updating schedule of #{self} sequence for entity ##{entity.id} #{entity}" set_schedule_for entity end end |
#to_s ⇒ Object
207 208 209 |
# File 'app/models/maily_herald/sequence.rb', line 207 def to_s "<Sequence: #{self.title || self.name}>" end |
#update_schedules_callback ⇒ Object
166 167 168 |
# File 'app/models/maily_herald/sequence.rb', line 166 def update_schedules_callback Rails.env.test? ? set_schedules : MailyHerald::ScheduleUpdater.perform_in(10.seconds, self.id) end |