diff --git a/lib/good_job/adapter.rb b/lib/good_job/adapter.rb index 667cd181a..f21194a32 100644 --- a/lib/good_job/adapter.rb +++ b/lib/good_job/adapter.rb @@ -64,10 +64,12 @@ def enqueue_at(active_job, timestamp) if execute_inline? begin - execution.perform + result = execution.perform ensure execution.advisory_unlock end + + raise result.unhandled_error if result.unhandled_error else job_state = { queue_name: execution.queue_name } job_state[:scheduled_at] = execution.scheduled_at if execution.scheduled_at diff --git a/spec/app/jobs/example_job_spec.rb b/spec/app/jobs/example_job_spec.rb index c8d1e22da..c0be3d459 100644 --- a/spec/app/jobs/example_job_spec.rb +++ b/spec/app/jobs/example_job_spec.rb @@ -36,8 +36,14 @@ describe "DEAD_TYPE" do it 'errors but does not retry' do - active_job = described_class.perform_later(described_class::DEAD_TYPE) - executions = GoodJob::Execution.where(active_job_id: active_job.job_id).order(created_at: :asc) + begin + described_class.perform_later(described_class::DEAD_TYPE) + rescue ExampleJob::DeadError + nil + end + active_job_id = GoodJob::Execution.last.active_job_id + + executions = GoodJob::Execution.where(active_job_id: active_job_id).order(created_at: :asc) expect(executions.size).to eq 3 expect(executions.last.error).to be_present end diff --git a/spec/engine/filters/good_job/executions_filter_spec.rb b/spec/engine/filters/good_job/executions_filter_spec.rb index f4c2dd7be..d0d306dc5 100644 --- a/spec/engine/filters/good_job/executions_filter_spec.rb +++ b/spec/engine/filters/good_job/executions_filter_spec.rb @@ -13,7 +13,11 @@ ExampleJob.set(queue: 'default').perform_later('success') ExampleJob.set(queue: 'mice').perform_later('error_once') - ExampleJob.set(queue: 'elephants').perform_later('dead') + begin + ExampleJob.set(queue: 'elephants').perform_later('dead') + rescue ExampleJob::DeadError + nil + end running_job = ExampleJob.perform_later('success') running_execution = GoodJob::Execution.find(running_job.provider_job_id) diff --git a/spec/engine/filters/good_job/jobs_filter_spec.rb b/spec/engine/filters/good_job/jobs_filter_spec.rb index d314a52cc..f300e9f38 100644 --- a/spec/engine/filters/good_job/jobs_filter_spec.rb +++ b/spec/engine/filters/good_job/jobs_filter_spec.rb @@ -13,7 +13,11 @@ ExampleJob.set(queue: 'default').perform_later('success') ExampleJob.set(queue: 'mice').perform_later('error_once') - ExampleJob.set(queue: 'elephants').perform_later('dead') + begin + ExampleJob.set(queue: 'elephants').perform_later('dead') + rescue ExampleJob::DeadError + nil + end running_job = ExampleJob.perform_later('success') running_execution = GoodJob::Execution.find(running_job.provider_job_id) diff --git a/spec/integration/adapter_spec.rb b/spec/integration/adapter_spec.rb index f7cfc52ef..2e150a9e1 100644 --- a/spec/integration/adapter_spec.rb +++ b/spec/integration/adapter_spec.rb @@ -94,4 +94,28 @@ def perform(*_args, **_kwargs) end end end + + context 'when inline adapter' do + let(:adapter) { GoodJob::Adapter.new(execution_mode: :inline) } + + before do + stub_const 'PERFORMED', [] + stub_const 'JobError', Class.new(StandardError) + stub_const 'TestJob', (Class.new(ActiveJob::Base) do + retry_on JobError, attempts: 3 + + def perform + PERFORMED << Time.current + raise JobError + end + end) + end + + it 'raises unhandled exceptions' do + expect do + TestJob.perform_later + end.to raise_error JobError + expect(PERFORMED.size).to eq 3 + end + end end diff --git a/spec/lib/good_job/adapter_spec.rb b/spec/lib/good_job/adapter_spec.rb index d308f46e0..7167e00cc 100644 --- a/spec/lib/good_job/adapter_spec.rb +++ b/spec/lib/good_job/adapter_spec.rb @@ -27,6 +27,33 @@ ) end + context 'when inline' do + let(:adapter) { described_class.new(execution_mode: :inline) } + + before do + stub_const 'PERFORMED', [] + stub_const 'JobError', Class.new(StandardError) + stub_const 'TestJob', (Class.new(ActiveJob::Base) do + def perform(succeed: true) + PERFORMED << Time.current + + raise JobError unless succeed + end + end) + end + + it 'executes the job immediately' do + adapter.enqueue(TestJob.new(succeed: true)) + expect(PERFORMED.size).to eq 1 + end + + it "raises unhandled exceptions" do + expect do + adapter.enqueue(TestJob.new(succeed: false)) + end.to raise_error(JobError) + end + end + context 'when async' do it 'triggers an execution thread and the notifier' do allow(GoodJob::Execution).to receive(:enqueue).and_return(good_job)