Module: Delayed::Backend::Base
- Included in:
- ActiveRecord::Job, ActiveRecord::Job::Failed, Redis::Job, Redis::Job::Failed
- Defined in:
- lib/delayed/backend/base.rb
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- ON_HOLD_LOCKED_BY =
'on hold'
- ON_HOLD_COUNT =
50
Class Method Summary collapse
Instance Method Summary collapse
- #batch? ⇒ Boolean
- #expired? ⇒ Boolean
- #failed? ⇒ Boolean (also: #failed)
- #full_name ⇒ Object
- #hold! ⇒ Object
- #inferred_max_attempts ⇒ Object
- #initialize_defaults ⇒ Object
-
#invoke_job ⇒ Object
Moved into its own method so that new_relic can trace it.
- #locked? ⇒ Boolean
- #name ⇒ Object
- #on_hold? ⇒ Boolean
- #payload_object ⇒ Object
- #payload_object=(object) ⇒ Object
- #permanent_failure(error) ⇒ Object
-
#reschedule(error = nil, time = nil) ⇒ Object
Reschedule the job in the future (when a job fails).
- #reschedule_at ⇒ Object
- #unhold! ⇒ Object
-
#unlock ⇒ Object
Unlock this job (note: not saved to DB).
Class Method Details
.included(base) ⇒ Object
18 19 20 21 22 |
# File 'lib/delayed/backend/base.rb', line 18 def self.included(base) base.extend ClassMethods base.default_priority = Delayed::NORMAL_PRIORITY base.before_save :initialize_defaults end |
Instance Method Details
#batch? ⇒ Boolean
280 281 282 |
# File 'lib/delayed/backend/base.rb', line 280 def batch? payload_object.is_a?(Delayed::Batch::PerformableBatch) end |
#expired? ⇒ Boolean
177 178 179 |
# File 'lib/delayed/backend/base.rb', line 177 def expired? expires_at && (self.class.db_time_now >= expires_at) end |
#failed? ⇒ Boolean Also known as: failed
172 173 174 |
# File 'lib/delayed/backend/base.rb', line 172 def failed? failed_at end |
#full_name ⇒ Object
246 247 248 249 250 251 252 253 |
# File 'lib/delayed/backend/base.rb', line 246 def full_name obj = payload_object rescue nil if obj && obj.respond_to?(:full_name) obj.full_name else name end end |
#hold! ⇒ Object
307 308 309 310 311 312 |
# File 'lib/delayed/backend/base.rb', line 307 def hold! self.locked_by = ON_HOLD_LOCKED_BY self.locked_at = self.class.db_time_now self.attempts = ON_HOLD_COUNT self.save! end |
#inferred_max_attempts ⇒ Object
181 182 183 |
# File 'lib/delayed/backend/base.rb', line 181 def inferred_max_attempts self.max_attempts || Delayed::Settings.max_attempts end |
#initialize_defaults ⇒ Object
363 364 365 366 |
# File 'lib/delayed/backend/base.rb', line 363 def initialize_defaults self.queue ||= Delayed::Settings.queue self.run_at ||= self.class.db_time_now end |
#invoke_job ⇒ Object
Moved into its own method so that new_relic can trace it.
268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/delayed/backend/base.rb', line 268 def invoke_job Delayed::Worker.lifecycle.run_callbacks(:invoke_job, self) do Delayed::Job.in_delayed_job = true begin payload_object.perform ensure Delayed::Job.in_delayed_job = false ::ActiveRecord::Base.clear_active_connections! unless Rails.env.test? end end end |
#locked? ⇒ Boolean
290 291 292 |
# File 'lib/delayed/backend/base.rb', line 290 def locked? !!(self.locked_at || self.locked_by) end |
#name ⇒ Object
235 236 237 238 239 240 241 242 243 244 |
# File 'lib/delayed/backend/base.rb', line 235 def name @name ||= begin payload = payload_object if payload.respond_to?(:display_name) payload.display_name else payload.class.name end end end |
#on_hold? ⇒ Boolean
323 324 325 |
# File 'lib/delayed/backend/base.rb', line 323 def on_hold? self.locked_by == 'on hold' && self.locked_at && self.attempts == ON_HOLD_COUNT end |
#payload_object ⇒ Object
231 232 233 |
# File 'lib/delayed/backend/base.rb', line 231 def payload_object @payload_object ||= deserialize(self['handler'].untaint) end |
#payload_object=(object) ⇒ Object
255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/delayed/backend/base.rb', line 255 def payload_object=(object) @payload_object = object self['handler'] = object.to_yaml self['tag'] = if object.respond_to?(:tag) object.tag elsif object.is_a?(Module) "#{object}.perform" else "#{object.class}#perform" end end |
#permanent_failure(error) ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/delayed/backend/base.rb', line 209 def permanent_failure(error) begin # notify the payload_object of a permanent failure obj = payload_object obj.on_permanent_failure(error) if obj && obj.respond_to?(:on_permanent_failure) rescue # don't allow a failed deserialization to prevent destroying the job end # optionally destroy the object destroy_self = true if Delayed::Worker.on_max_failures destroy_self = Delayed::Worker.on_max_failures.call(self, error) end if destroy_self self.destroy else self.fail! end end |
#reschedule(error = nil, time = nil) ⇒ Object
Reschedule the job in the future (when a job fails). Uses an exponential scale depending on the number of failed attempts.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/delayed/backend/base.rb', line 187 def reschedule(error = nil, time = nil) begin obj = payload_object return_code = obj.on_failure(error) if obj && obj.respond_to?(:on_failure) rescue # don't allow a failed deserialization to prevent rescheduling end self.attempts += 1 unless return_code == :unlock if self.attempts >= self.inferred_max_attempts permanent_failure error || "max attempts reached" elsif expired? permanent_failure error || "job has expired" else time ||= self.reschedule_at self.run_at = time self.unlock self.save! end end |
#reschedule_at ⇒ Object
294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/delayed/backend/base.rb', line 294 def reschedule_at new_time = self.class.db_time_now + (attempts ** 4) + 5 begin if payload_object.respond_to?(:reschedule_at) new_time = payload_object.reschedule_at( self.class.db_time_now, attempts) end rescue # TODO: just swallow errors from reschedule_at ? end new_time end |
#unhold! ⇒ Object
314 315 316 317 318 319 320 321 |
# File 'lib/delayed/backend/base.rb', line 314 def unhold! self.locked_by = nil self.locked_at = nil self.attempts = 0 self.run_at = [self.class.db_time_now, self.run_at].max self.failed_at = nil self.save! end |
#unlock ⇒ Object
Unlock this job (note: not saved to DB)
285 286 287 288 |
# File 'lib/delayed/backend/base.rb', line 285 def unlock self.locked_at = nil self.locked_by = nil end |