lib/sucker_punch/job.rb
module SuckerPunch
# Include this module in your job class
# to create asynchronous jobs:
#
# class LogJob
# include SuckerPunch::Job
# workers 4
#
# def perform(*args)
# # log the things
# end
# end
#
# To trigger asynchronous job:
#
# LogJob.perform_async(1, 2, 3)
# LogJob.perform_in(60, 1, 2, 3) # `perform` will be executed 60 sec. later
#
# Note that perform_async is a class method, perform is an instance method.
module Job
def self.included(base)
base.extend(ClassMethods)
base.class_attribute :num_workers
base.class_attribute :num_jobs_max
base.num_workers = 2
base.num_jobs_max = nil
end
def logger
SuckerPunch.logger
end
module ClassMethods
def perform_async(*args)
return unless SuckerPunch::RUNNING.true?
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers, num_jobs_max)
queue.post { __run_perform(*args) }
end
ruby2_keywords(:perform_async) if respond_to?(:ruby2_keywords, true)
def perform_in(interval, *args)
return unless SuckerPunch::RUNNING.true?
queue = SuckerPunch::Queue.find_or_create(self.to_s, num_workers, num_jobs_max)
job = Concurrent::ScheduledTask.execute(interval.to_f, args: args, executor: queue) do
__run_perform(*args)
end
job.pending?
end
ruby2_keywords(:perform_in) if respond_to?(:ruby2_keywords, true)
def workers(num)
self.num_workers = num
end
def max_jobs(num)
self.num_jobs_max = num
end
def __run_perform(*args)
SuckerPunch::Counter::Busy.new(self.to_s).increment
result = self.new.perform(*args)
SuckerPunch::Counter::Processed.new(self.to_s).increment
result
rescue => ex
SuckerPunch::Counter::Failed.new(self.to_s).increment
SuckerPunch.exception_handler.call(ex, self, [*args])
ensure
SuckerPunch::Counter::Busy.new(self.to_s).decrement
end
ruby2_keywords(:__run_perform) if respond_to?(:ruby2_keywords, true)
end
end
end