diff options
Diffstat (limited to 'activejob/lib')
25 files changed, 868 insertions, 0 deletions
diff --git a/activejob/lib/active_job.rb b/activejob/lib/active_job.rb new file mode 100644 index 0000000000..ef92406725 --- /dev/null +++ b/activejob/lib/active_job.rb @@ -0,0 +1,33 @@ +#-- +# Copyright (c) 2014 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +require 'active_support' +require 'active_support/rails' +require 'active_job/version' +require 'global_id' + +module ActiveJob + extend ActiveSupport::Autoload + + autoload :Base +end
\ No newline at end of file diff --git a/activejob/lib/active_job/arguments.rb b/activejob/lib/active_job/arguments.rb new file mode 100644 index 0000000000..369e716912 --- /dev/null +++ b/activejob/lib/active_job/arguments.rb @@ -0,0 +1,62 @@ +module ActiveJob + class DeserializationError < StandardError + attr_reader :original_exception + + def initialize(e) + super ("Error while trying to deserialize arguments: #{e.message}") + @original_exception = e + set_backtrace e.backtrace + end + end + + module Arguments + extend self + TYPE_WHITELIST = [ NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ] + + def serialize(arguments) + arguments.map { |argument| serialize_argument(argument) } + end + + def deserialize(arguments) + arguments.map { |argument| deserialize_argument(argument) } + end + + private + def serialize_argument(argument) + case argument + when GlobalID::Identification + argument.global_id.to_s + when *TYPE_WHITELIST + argument + when Array + serialize(argument) + when Hash + Hash[ argument.map { |key, value| [ serialize_hash_key(key), serialize_argument(value) ] } ] + else + raise "Unsupported argument type: #{argument.class.name}" + end + end + + def deserialize_argument(argument) + case argument + when Array + deserialize(argument) + when Hash + Hash[ argument.map { |key, value| [ key, deserialize_argument(value) ] } ].with_indifferent_access + else + GlobalID::Locator.locate(argument) || argument + end + rescue => e + raise DeserializationError.new(e) + end + + def serialize_hash_key(key) + case key + when String, Symbol + key.to_s + else + raise "Unsupported hash key type: #{key.class.name}" + end + end + end +end diff --git a/activejob/lib/active_job/base.rb b/activejob/lib/active_job/base.rb new file mode 100644 index 0000000000..d5ba253016 --- /dev/null +++ b/activejob/lib/active_job/base.rb @@ -0,0 +1,22 @@ +require 'active_job/queue_adapter' +require 'active_job/queue_name' +require 'active_job/enqueuing' +require 'active_job/execution' +require 'active_job/callbacks' +require 'active_job/identifier' +require 'active_job/logging' + +module ActiveJob + class Base + extend QueueAdapter + + include QueueName + include Enqueuing + include Execution + include Callbacks + include Identifier + include Logging + + ActiveSupport.run_load_hooks(:active_job, self) + end +end diff --git a/activejob/lib/active_job/callbacks.rb b/activejob/lib/active_job/callbacks.rb new file mode 100644 index 0000000000..8901fa77f2 --- /dev/null +++ b/activejob/lib/active_job/callbacks.rb @@ -0,0 +1,144 @@ +require 'active_support/callbacks' + +module ActiveJob + # = Active Job Callbacks + # + # Active Job provides hooks during the lifecycle of a job. Callbacks allow you to trigger + # logic during the lifecycle of a job. Available callbacks: + # + # * <tt>before_enqueue</tt> + # * <tt>around_enqueue</tt> + # * <tt>after_enqueue</tt> + # * <tt>before_perform</tt> + # * <tt>around_perform</tt> + # * <tt>after_perform</tt> + # + module Callbacks + extend ActiveSupport::Concern + include ActiveSupport::Callbacks + + included do + define_callbacks :perform + define_callbacks :enqueue + end + + module ClassMethods + # Defines a callback that will get called right before the + # job's perform method is executed. + # + # class VideoProcessJob < ActiveJob::Base + # queue_as :default + # + # before_perform do |job| + # UserMailer.notify_video_started_processing(job.arguments.first) + # end + # + # def perform(video_id) + # Video.find(video_id).process + # end + # end + # + def before_perform(*filters, &blk) + set_callback(:perform, :before, *filters, &blk) + end + + # Defines a callback that will get called right after the + # job's perform method has finished. + # + # class VideoProcessJob < ActiveJob::Base + # queue_as :default + # + # after_perform do |job| + # UserMailer.notify_video_processed(job.arguments.first) + # end + # + # def perform(video_id) + # Video.find(video_id).process + # end + # end + # + def after_perform(*filters, &blk) + set_callback(:perform, :after, *filters, &blk) + end + + # Defines a callback that will get called around the job's perform method. + # + # class VideoProcessJob < ActiveJob::Base + # queue_as :default + # + # around_perform do |job, block| + # UserMailer.notify_video_started_processing(job.arguments.first) + # block.call + # UserMailer.notify_video_processed(job.arguments.first) + # end + # + # def perform(video_id) + # Video.find(video_id).process + # end + # end + # + def around_perform(*filters, &blk) + set_callback(:perform, :around, *filters, &blk) + end + + # Defines a callback that will get called right before the + # job is enqueued. + # + # class VideoProcessJob < ActiveJob::Base + # queue_as :default + # + # before_enqueue do |job| + # $statsd.increment "enqueue-video-job.try" + # end + # + # def perform(video_id) + # Video.find(video_id).process + # end + # end + # + def before_enqueue(*filters, &blk) + set_callback(:enqueue, :before, *filters, &blk) + end + + # Defines a callback that will get called right after the + # job is enqueued. + # + # class VideoProcessJob < ActiveJob::Base + # queue_as :default + # + # after_enqueue do |job| + # $statsd.increment "enqueue-video-job.success" + # end + # + # def perform(video_id) + # Video.find(video_id).process + # end + # end + # + def after_enqueue(*filters, &blk) + set_callback(:enqueue, :after, *filters, &blk) + end + + # Defines a callback that will get called before and after the + # job is enqueued. + # + # class VideoProcessJob < ActiveJob::Base + # queue_as :default + # + # around_enqueue do |job, block| + # $statsd.time "video-job.process" do + # block.call + # end + # end + # + # def perform(video_id) + # Video.find(video_id).process + # end + # end + # + def around_enqueue(*filters, &blk) + set_callback(:enqueue, :around, *filters, &blk) + end + end + end +end diff --git a/activejob/lib/active_job/enqueuing.rb b/activejob/lib/active_job/enqueuing.rb new file mode 100644 index 0000000000..3d00d51867 --- /dev/null +++ b/activejob/lib/active_job/enqueuing.rb @@ -0,0 +1,71 @@ +require 'active_job/arguments' + +module ActiveJob + module Enqueuing + extend ActiveSupport::Concern + + module ClassMethods + # Push a job onto the queue. The arguments must be legal JSON types + # (string, int, float, nil, true, false, hash or array) or + # GlobalID::Identification instances. Arbitrary Ruby objects + # are not supported. + # + # Returns an instance of the job class queued with args available in + # Job#arguments. + def enqueue(*args) + new(args).tap do |job| + job.run_callbacks :enqueue do + queue_adapter.enqueue self, job.job_id, *Arguments.serialize(args) + end + end + end + + # Enqueue a job to be performed at +interval+ from now. + # + # enqueue_in(1.week, "mike") + # + # Returns an instance of the job class queued with args available in + # Job#arguments and the timestamp in Job#enqueue_at. + def enqueue_in(interval, *args) + enqueue_at interval.seconds.from_now, *args + end + + # Enqueue a job to be performed at an explicit point in time. + # + # enqueue_at(Date.tomorrow.midnight, "mike") + # + # Returns an instance of the job class queued with args available in + # Job#arguments and the timestamp in Job#enqueue_at. + def enqueue_at(timestamp, *args) + new(args).tap do |job| + job.enqueued_at = timestamp + + job.run_callbacks :enqueue do + queue_adapter.enqueue_at self, timestamp.to_f, job.job_id, *Arguments.serialize(args) + end + end + end + end + + included do + attr_accessor :arguments + attr_accessor :enqueued_at + end + + def initialize(arguments = nil) + @arguments = arguments + end + + def retry_now + self.class.enqueue(*arguments) + end + + def retry_in(interval) + self.class.enqueue_in interval, *arguments + end + + def retry_at(timestamp) + self.class.enqueue_at timestamp, *arguments + end + end +end diff --git a/activejob/lib/active_job/execution.rb b/activejob/lib/active_job/execution.rb new file mode 100644 index 0000000000..0e7b5bdd72 --- /dev/null +++ b/activejob/lib/active_job/execution.rb @@ -0,0 +1,33 @@ +require 'active_support/rescuable' +require 'active_job/arguments' + +module ActiveJob + module Execution + extend ActiveSupport::Concern + + included do + include ActiveSupport::Rescuable + end + + def execute(job_id, *serialized_args) + self.job_id = job_id + self.arguments = deserialize_arguments(serialized_args) + + run_callbacks :perform do + perform(*arguments) + end + rescue => exception + rescue_with_handler(exception) || raise(exception) + end + + def perform(*) + fail NotImplementedError + end + + private + def deserialize_arguments(serialized_args) + Arguments.deserialize(serialized_args) + end + + end +end diff --git a/activejob/lib/active_job/gem_version.rb b/activejob/lib/active_job/gem_version.rb new file mode 100644 index 0000000000..c166020b28 --- /dev/null +++ b/activejob/lib/active_job/gem_version.rb @@ -0,0 +1,15 @@ +module ActiveJob + # Returns the version of the currently loaded ActiveJob as a <tt>Gem::Version</tt> + def self.gem_version + Gem::Version.new VERSION::STRING + end + + module VERSION + MAJOR = 4 + MINOR = 2 + TINY = 0 + PRE = "alpha" + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") + end +end diff --git a/activejob/lib/active_job/identifier.rb b/activejob/lib/active_job/identifier.rb new file mode 100644 index 0000000000..c7f522087d --- /dev/null +++ b/activejob/lib/active_job/identifier.rb @@ -0,0 +1,15 @@ +require 'active_job/arguments' + +module ActiveJob + module Identifier + extend ActiveSupport::Concern + + included do + attr_writer :job_id + end + + def job_id + @job_id ||= SecureRandom.uuid + end + end +end diff --git a/activejob/lib/active_job/logging.rb b/activejob/lib/active_job/logging.rb new file mode 100644 index 0000000000..d9e544acf5 --- /dev/null +++ b/activejob/lib/active_job/logging.rb @@ -0,0 +1,90 @@ +require 'active_support/core_ext/string/filters' +require 'active_support/tagged_logging' +require 'active_support/logger' + +module ActiveJob + module Logging + extend ActiveSupport::Concern + + included do + cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) } + + around_enqueue do |_, block, _| + tag_logger do + block.call + end + end + + around_perform do |job, block, _| + tag_logger(job.class.name, job.job_id) do + payload = {adapter: job.class.queue_adapter, job: job.class, args: job.arguments} + ActiveSupport::Notifications.instrument("perform_start.active_job", payload.dup) + ActiveSupport::Notifications.instrument("perform.active_job", payload) do + block.call + end + end + end + + before_enqueue do |job| + if job.enqueued_at + ActiveSupport::Notifications.instrument "enqueue_at.active_job", + adapter: job.class.queue_adapter, job: job.class, job_id: job.job_id, args: job.arguments, timestamp: job.enqueued_at + else + ActiveSupport::Notifications.instrument "enqueue.active_job", + adapter: job.class.queue_adapter, job: job.class, job_id: job.job_id, args: job.arguments + end + end + end + + private + def tag_logger(*tags) + if logger.respond_to?(:tagged) + tags.unshift "ActiveJob" unless logger_tagged_by_active_job? + ActiveJob::Base.logger.tagged(*tags){ yield } + else + yield + end + end + + def logger_tagged_by_active_job? + logger.formatter.current_tags.include?("ActiveJob") + end + + class LogSubscriber < ActiveSupport::LogSubscriber + def enqueue(event) + info "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)}" + args_info(event) + end + + def enqueue_at(event) + info "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)} at #{enqueued_at(event)}" + args_info(event) + end + + def perform_start(event) + info "Performing #{event.payload[:job].name} from #{queue_name(event)}" + args_info(event) + end + + def perform(event) + info "Performed #{event.payload[:job].name} from #{queue_name(event)} in #{event.duration.round(2).to_s}ms" + end + + private + def queue_name(event) + event.payload[:adapter].name.demodulize.remove('Adapter') + "(#{event.payload[:job].queue_name})" + end + + def args_info(event) + event.payload[:args].any? ? " with arguments: #{event.payload[:args].map(&:inspect).join(", ")}" : "" + end + + def enqueued_at(event) + Time.at(event.payload[:timestamp]).utc + end + + def logger + ActiveJob::Base.logger + end + end + end +end + +ActiveJob::Logging::LogSubscriber.attach_to :active_job diff --git a/activejob/lib/active_job/queue_adapter.rb b/activejob/lib/active_job/queue_adapter.rb new file mode 100644 index 0000000000..8f2f8b86ea --- /dev/null +++ b/activejob/lib/active_job/queue_adapter.rb @@ -0,0 +1,24 @@ +require 'active_job/queue_adapters/inline_adapter' +require 'active_support/core_ext/string/inflections' + +module ActiveJob + module QueueAdapter + mattr_reader(:queue_adapter) { ActiveJob::QueueAdapters::InlineAdapter } + + def queue_adapter=(name_or_adapter) + @@queue_adapter = \ + case name_or_adapter + when Symbol, String + load_adapter(name_or_adapter) + when Class + name_or_adapter + end + end + + private + def load_adapter(name) + require "active_job/queue_adapters/#{name}_adapter" + "ActiveJob::QueueAdapters::#{name.to_s.camelize}Adapter".constantize + end + end +end
\ No newline at end of file diff --git a/activejob/lib/active_job/queue_adapters/backburner_adapter.rb b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb new file mode 100644 index 0000000000..6fe2d4eb53 --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb @@ -0,0 +1,25 @@ +require 'backburner' + +module ActiveJob + module QueueAdapters + class BackburnerAdapter + class << self + def enqueue(job, *args) + Backburner::Worker.enqueue JobWrapper, [ job.name, *args ], queue: job.queue_name + end + + def enqueue_at(job, timestamp, *args) + raise NotImplementedError + end + end + + class JobWrapper + class << self + def perform(job_name, *args) + job_name.constantize.new.execute(*args) + end + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb new file mode 100644 index 0000000000..a00569833a --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb @@ -0,0 +1,23 @@ +require 'delayed_job' + +module ActiveJob + module QueueAdapters + class DelayedJobAdapter + class << self + def enqueue(job, *args) + JobWrapper.new.delay(queue: job.queue_name).perform(job, *args) + end + + def enqueue_at(job, timestamp, *args) + JobWrapper.new.delay(queue: job.queue_name, run_at: Time.at(timestamp)).perform(job, *args) + end + end + + class JobWrapper + def perform(job, *args) + job.new.execute(*args) + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/inline_adapter.rb b/activejob/lib/active_job/queue_adapters/inline_adapter.rb new file mode 100644 index 0000000000..5805340fb0 --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/inline_adapter.rb @@ -0,0 +1,15 @@ +module ActiveJob + module QueueAdapters + class InlineAdapter + class << self + def enqueue(job, *args) + job.new.execute(*args) + end + + def enqueue_at(*) + raise NotImplementedError.new("Use a queueing backend to enqueue jobs in the future. Read more at https://github.com/rails/activejob") + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/qu_adapter.rb b/activejob/lib/active_job/queue_adapters/qu_adapter.rb new file mode 100644 index 0000000000..5cb741c094 --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/qu_adapter.rb @@ -0,0 +1,30 @@ +require 'qu' + +module ActiveJob + module QueueAdapters + class QuAdapter + class << self + def enqueue(job, *args) + Qu::Payload.new(klass: JobWrapper, args: [job.name, *args]).tap do |payload| + payload.instance_variable_set(:@queue, job.queue_name) + end.push + end + + def enqueue_at(job, timestamp, *args) + raise NotImplementedError + end + end + + class JobWrapper < Qu::Job + def initialize(job_name, *args) + @job = job_name.constantize + @args = args + end + + def perform + @job.new.execute(*@args) + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/que_adapter.rb b/activejob/lib/active_job/queue_adapters/que_adapter.rb new file mode 100644 index 0000000000..0b87deb4e0 --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/que_adapter.rb @@ -0,0 +1,23 @@ +require 'que' + +module ActiveJob + module QueueAdapters + class QueAdapter + class << self + def enqueue(job, *args) + JobWrapper.enqueue job.name, *args, queue: job.queue_name + end + + def enqueue_at(job, timestamp, *args) + raise NotImplementedError + end + end + + class JobWrapper < Que::Job + def run(job_name, *args) + job_name.constantize.new.execute(*args) + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb new file mode 100644 index 0000000000..d74f8cf90e --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb @@ -0,0 +1,25 @@ +require 'queue_classic' + +module ActiveJob + module QueueAdapters + class QueueClassicAdapter + class << self + def enqueue(job, *args) + QC::Queue.new(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.name, *args) + end + + def enqueue_at(job, timestamp, *args) + raise NotImplementedError + end + end + + class JobWrapper + class << self + def perform(job_name, *args) + job_name.constantize.new.execute(*args) + end + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/resque_adapter.rb b/activejob/lib/active_job/queue_adapters/resque_adapter.rb new file mode 100644 index 0000000000..da8212fc9b --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/resque_adapter.rb @@ -0,0 +1,41 @@ +require 'resque' +require 'active_support/core_ext/enumerable' +require 'active_support/core_ext/array/access' + +begin + require 'resque-scheduler' +rescue LoadError + begin + require 'resque_scheduler' + rescue LoadError + false + end +end + +module ActiveJob + module QueueAdapters + class ResqueAdapter + class << self + def enqueue(job, *args) + Resque.enqueue_to job.queue_name, JobWrapper, job.name, *args + end + + def enqueue_at(job, timestamp, *args) + unless Resque.respond_to?(:enqueue_at_with_queue) + raise NotImplementedError, "To be able to schedule jobs with Resque you need the " \ + "resque-scheduler gem. Please add it to your Gemfile and run bundle install" + end + Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.name, *args + end + end + + class JobWrapper + class << self + def perform(job_name, *args) + job_name.constantize.new.execute(*args) + end + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb new file mode 100644 index 0000000000..3e20bec44c --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb @@ -0,0 +1,35 @@ +require 'sidekiq' + +module ActiveJob + module QueueAdapters + class SidekiqAdapter + class << self + def enqueue(job, *args) + #Sidekiq::Client does not support symbols as keys + Sidekiq::Client.push \ + 'class' => JobWrapper, + 'queue' => job.queue_name, + 'args' => [ job, *args ], + 'retry' => true + end + + def enqueue_at(job, timestamp, *args) + Sidekiq::Client.push \ + 'class' => JobWrapper, + 'queue' => job.queue_name, + 'args' => [ job, *args ], + 'retry' => true, + 'at' => timestamp + end + end + + class JobWrapper + include Sidekiq::Worker + + def perform(job_name, *args) + job_name.constantize.new.execute(*args) + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb new file mode 100644 index 0000000000..48b3df6a46 --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb @@ -0,0 +1,34 @@ +require 'sneakers' +require 'thread' + +module ActiveJob + module QueueAdapters + class SneakersAdapter + @monitor = Monitor.new + + class << self + def enqueue(job, *args) + @monitor.synchronize do + JobWrapper.from_queue job.queue_name + JobWrapper.enqueue ActiveSupport::JSON.encode([ job.name, *args ]) + end + end + + def enqueue_at(job, timestamp, *args) + raise NotImplementedError + end + end + + class JobWrapper + include Sneakers::Worker + from_queue 'active_jobs_default' + + def work(msg) + job_name, *args = ActiveSupport::JSON.decode(msg) + job_name.constantize.new.execute(*args) + ack! + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb new file mode 100644 index 0000000000..16f05744f3 --- /dev/null +++ b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb @@ -0,0 +1,25 @@ +require 'sucker_punch' + +module ActiveJob + module QueueAdapters + class SuckerPunchAdapter + class << self + def enqueue(job, *args) + JobWrapper.new.async.perform job, *args + end + + def enqueue_at(job, timestamp, *args) + raise NotImplementedError + end + end + + class JobWrapper + include SuckerPunch::Job + + def perform(job, *args) + job.new.execute(*args) + end + end + end + end +end diff --git a/activejob/lib/active_job/queue_name.rb b/activejob/lib/active_job/queue_name.rb new file mode 100644 index 0000000000..9698835b6e --- /dev/null +++ b/activejob/lib/active_job/queue_name.rb @@ -0,0 +1,21 @@ +module ActiveJob + module QueueName + extend ActiveSupport::Concern + + module ClassMethods + mattr_accessor(:queue_name_prefix) + mattr_accessor(:default_queue_name) { "default" } + + def queue_as(part_name) + queue_name = part_name.to_s.presence || default_queue_name + name_parts = [queue_name_prefix.presence, queue_name] + self.queue_name = name_parts.compact.join('_') + end + end + + included do + class_attribute :queue_name + self.queue_name = default_queue_name + end + end +end diff --git a/activejob/lib/active_job/railtie.rb b/activejob/lib/active_job/railtie.rb new file mode 100644 index 0000000000..6538ac1b30 --- /dev/null +++ b/activejob/lib/active_job/railtie.rb @@ -0,0 +1,23 @@ +require 'global_id/railtie' +require 'active_job' + +module ActiveJob + # = Active Job Railtie + class Railtie < Rails::Railtie # :nodoc: + config.active_job = ActiveSupport::OrderedOptions.new + + initializer 'active_job.logger' do + ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger } + end + + initializer "active_job.set_configs" do |app| + options = app.config.active_job + options.queue_adapter ||= :inline + + ActiveSupport.on_load(:active_job) do + options.each { |k,v| send("#{k}=", v) } + end + end + + end +end diff --git a/activejob/lib/active_job/version.rb b/activejob/lib/active_job/version.rb new file mode 100644 index 0000000000..7e646fa3c4 --- /dev/null +++ b/activejob/lib/active_job/version.rb @@ -0,0 +1,8 @@ +require_relative 'gem_version' + +module ActiveJob + # Returns the version of the currently loaded ActiveJob as a <tt>Gem::Version</tt> + def self.version + gem_version + end +end diff --git a/activejob/lib/rails/generators/job/job_generator.rb b/activejob/lib/rails/generators/job/job_generator.rb new file mode 100644 index 0000000000..78a9c27606 --- /dev/null +++ b/activejob/lib/rails/generators/job/job_generator.rb @@ -0,0 +1,22 @@ +require 'rails/generators/named_base' + +module Rails + module Generators # :nodoc: + class JobGenerator < Rails::Generators::NamedBase # :nodoc: + desc 'This generator creates an active job file at app/jobs' + + class_option :queue, type: :string, default: 'default', desc: 'The queue name for the generated job' + + def self.default_generator_root + File.dirname(__FILE__) + end + + check_class_collision suffix: 'Job' + + def create_job_file + template 'job.rb', File.join('app/jobs', class_path, "#{file_name}_job.rb") + end + + end + end +end diff --git a/activejob/lib/rails/generators/job/templates/job.rb b/activejob/lib/rails/generators/job/templates/job.rb new file mode 100644 index 0000000000..462c71d917 --- /dev/null +++ b/activejob/lib/rails/generators/job/templates/job.rb @@ -0,0 +1,9 @@ +<% module_namespacing do -%> +class <%= class_name %>Job < ActiveJob::Base + queue_as :<%= options[:queue] %> + + def perform(*args) + # Do something later + end +end +<% end -%> |