-
-
Save defunkt/cda3a6a1d039398f09ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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