Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
class JobSchedule
# External interface for calling the service
def self.call(object_id, opts={})
if perform_asynchronously?
Delayed::Job.enqueue(EnqueuedJob.new(name, object_id, opts))
else
perform(object_id, opts)
end
end
# Internal interface for calling the service
def self.perform(object_id, opts={})
new(object_id, opts).call
end
# Run jobs asynchronously only when load would be a factor
def self.perform_asynchronously?
Rails.env.in?(%w(production staging))
end
# Class that holds error detail for exception_notification
JobError = Struct.new(:message, :backtrace)
# Class that holds failure detail for exception_notification
JobFailure = Struct.new(:message, :backtrace)
# Class that holds success detail for exception_notification
JobSuccess = Struct.new(:message, :backtrace)
# Class that serializes well for Delayed::Job
EnqueuedJob = Struct.new(:klass, :object_id, :opts) do
# The method that Delayed::Job calls, which then invokes the actual job class
def perform
klass.constantize.perform(object_id, opts)
end
# Delayed::Job hook fired upon each run of the job if it results in a failure
def error(job, original_exception)
return unless job.attempts.zero? # Only notify upon first failure
message = "Job ##{job.id} Error (First Run)"
exception = JobError.new(message, [original_exception.backtrace])
deliver_notification(exception, exception_data(job))
end
# Delayed::Job hook fired upon final run of the job if it results in a failure
def failure(job)
message = "Job ##{job.id} Failure (Final)"
exception = JobFailure.new(message, [job.last_error])
deliver_notification(exception, exception_data(job))
end
# Delayed::Job hook fired upon success of the job
def success(job)
return unless job.attempts > 0 # Only notify on actual retry success
message = "Job ##{job.id} Success (Upon Retry)"
exception = JobSuccess.new(message, [""])
deliver_notification(exception, exception_data(job))
end
private
def deliver_notification(exception, data={})
ExceptionNotifier::Notifier
.background_exception_notification(exception, data: data).deliver
end
def exception_data(job)
{
job_id: job.id,
klass: klass,
object_id: object_id,
opts: opts
}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment