diff --git a/lib/delayed/job_wrapper.rb b/lib/delayed/job_wrapper.rb index 4cb2b5e..9beec95 100644 --- a/lib/delayed/job_wrapper.rb +++ b/lib/delayed/job_wrapper.rb @@ -21,9 +21,7 @@ def display_name end def perform - ActiveJob::Callbacks.run_callbacks(:execute) do - job.perform_now - end + ActiveJob::Base.execute(job_data) end def encode_with(coder) diff --git a/spec/delayed/job_spec.rb b/spec/delayed/job_spec.rb index 7260970..90a1be3 100644 --- a/spec/delayed/job_spec.rb +++ b/spec/delayed/job_spec.rb @@ -549,6 +549,38 @@ def create_job(opts = {}) expect(job).to be_failed end end + + describe 'handing off to ActiveJob' do + around do |example| + old_adapter = ActiveJob::Base.queue_adapter + ActiveJob::Base.queue_adapter = :delayed + + example.run + ensure + ActiveJob::Base.queue_adapter = old_adapter + end + + it 'runs everything under the same executor block' do + # Ensure the current attributes are persisted in the job, but then reset in this process + ActiveJobAttributesJob.results.clear + ActiveJobAttributesJob::Current.user_id = 0xC0FFEE + ActiveJobAttributesJob.perform_later + ActiveJobAttributesJob::Current.clear_all + + # In a rails app this is in ActiveJob's railtie, wrapping the execute in an around callback that + # leans on the Rails executor to reset things in jobs. Fake it here with execute around callback + # setup the same, and only clear CurrentAttributes directly. + ActiveJob::Callbacks.singleton_class.set_callback(:execute, :around, prepend: true) do |_, inner| + ActiveSupport::CurrentAttributes.clear_all + inner.call + end + + worker.work_off + + expect(ActiveJobAttributesJob::Current.user_id).to be_nil + expect(ActiveJobAttributesJob.results).to eq([0xC0FFEE]) + end + end end describe 'failed jobs' do diff --git a/spec/sample_jobs.rb b/spec/sample_jobs.rb index f98e579..2dc0480 100644 --- a/spec/sample_jobs.rb +++ b/spec/sample_jobs.rb @@ -115,3 +115,26 @@ def enqueue(job) class ActiveJobJob < ActiveJob::Base # rubocop:disable Rails/ApplicationJob def perform; end end + +class ActiveJobAttributesJob < ActiveJobJob + class Current < ActiveSupport::CurrentAttributes + attribute :user_id + end + + def self.results + @results ||= [] + end + + def serialize + super.merge("user_id" => Current.user_id) + end + + def deserialize(job_data) + super + Current.user_id = job_data["user_id"] + end + + def perform + self.class.results << Current.user_id + end +end