Skip to content

Commit 5360bcf

Browse files
committed
fix(active_job): use background: true like integration gems
1 parent c0f2680 commit 5360bcf

4 files changed

Lines changed: 61 additions & 2 deletions

File tree

sentry-rails/lib/sentry/rails/active_job.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ def capture_exception(job, e)
200200
tags: {
201201
job_id: job.job_id,
202202
provider_job_id: job.provider_job_id
203-
}
203+
},
204+
# Send synchronously: a worker process may exit before the async
205+
# background worker flushes its queue, which would drop the event.
206+
hint: { background: false }
204207
)
205208
end
206209

sentry-rails/spec/active_job/shared_examples/error_capture.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,28 @@ def perform
2020
exception = extract_sentry_exceptions(sentry_events.last).first
2121
expect(exception.value).to match(/boom from failing_job spec/)
2222
end
23+
24+
context "when the background worker exits before flushing" do
25+
let(:background_worker) { ManualBackgroundWorker.new }
26+
27+
let(:sentry_test_config) do
28+
proc { |config| config.background_worker_threads = 1 }
29+
end
30+
31+
before { Sentry.background_worker = background_worker }
32+
33+
it "captures the error synchronously so it survives the worker exiting" do
34+
expect do
35+
failing_job.perform_later
36+
drain
37+
end.to raise_error(RuntimeError, /boom from failing_job spec/)
38+
39+
expect(background_worker.pending).to be_empty
40+
expect(sentry_events.size).to eq(1)
41+
42+
background_worker.drop!
43+
44+
expect(sentry_events.size).to eq(1)
45+
end
46+
end
2347
end

sentry-rails/spec/active_job/support/harness.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
RSpec.shared_context "active_job backend harness" do |adapter:|
1717
let(:adapter) { adapter }
1818
let(:configure_sentry) { proc { } }
19+
let(:sentry_test_config) { nil }
1920

2021
# Boot the dummy Rails app ONCE per example group. Each +make_basic_app+
2122
# call creates a new +Rails::Application+ subclass and re-runs every
@@ -63,7 +64,7 @@
6364
Sentry::Rails::ActiveJobExtensions::SentryReporter.register_event_handlers
6465
end
6566

66-
setup_sentry_test
67+
setup_sentry_test(&sentry_test_config)
6768

6869
boot_adapter(adapter)
6970

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
# A background worker stand-in that captures posted work without running it,
4+
# so a spec can deterministically simulate a worker that exits before flushing
5+
# its queue (#drop!) versus one that drains cleanly (#flush).
6+
class ManualBackgroundWorker
7+
attr_reader :pending
8+
9+
def initialize
10+
@pending = []
11+
end
12+
13+
# Mirrors Sentry::BackgroundWorker#perform; a truthy return keeps
14+
# Client#capture_event from recording a :queue_overflow lost event.
15+
def perform(&block)
16+
@pending << block
17+
true
18+
end
19+
20+
def flush
21+
@pending.each(&:call)
22+
@pending.clear
23+
end
24+
25+
# Simulate a hard worker exit: queued events are lost.
26+
def drop!
27+
@pending.clear
28+
end
29+
30+
def shutdown; end
31+
end

0 commit comments

Comments
 (0)