Skip to content

Commit ffc2bc9

Browse files
committed
chore(rails): patch AJ test adapter for 5.2
1 parent d61680a commit ffc2bc9

1 file changed

Lines changed: 58 additions & 2 deletions

File tree

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

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
# frozen_string_literal: true
22

3+
# Rails 5.2's TestAdapter stores a minimal hash per enqueued job (only job
4+
# class, args, queue) and its instantiate_job recreates jobs via `.new(*args)`
5+
# — never calling our `deserialize` override. That means the `_sentry`
6+
# payload injected by `serialize` is silently discarded before the consumer
7+
# ever sees it, breaking distributed-tracing propagation.
8+
#
9+
# This adapter subclass calls `job.serialize` a second time after `super` has
10+
# stored the minimal hash and saves the full output alongside it. The drain
11+
# then drives each job through `ActiveJob::Base.execute(full_payload)`, which
12+
# goes through the normal deserialize → perform_now path and picks up the
13+
# Sentry trace headers and user context that were captured at enqueue time.
14+
class Rails52FullPayloadTestAdapter < ::ActiveJob::QueueAdapters::TestAdapter
15+
def enqueue(job)
16+
prev = enqueued_jobs.length
17+
super
18+
enqueued_jobs.last[:_sentry_full_payload] = job.serialize if enqueued_jobs.length > prev
19+
end
20+
21+
def enqueue_at(job, timestamp)
22+
prev = enqueued_jobs.length
23+
super
24+
enqueued_jobs.last[:_sentry_full_payload] = job.serialize if enqueued_jobs.length > prev
25+
end
26+
end
27+
328
RSpec.shared_context "active_job backend harness" do |adapter:|
429
let(:adapter) { adapter }
530
let(:configure_sentry) { proc { } }
@@ -8,12 +33,33 @@
833
make_basic_app(&configure_sentry)
934
setup_sentry_test
1035

11-
::ActiveJob::Base.queue_adapter = adapter
36+
# Rails 5.2's TestAdapter discards the full serialize output (including the
37+
# _sentry payload) when deferring jobs. Use our augmented subclass instead
38+
# so the drain can replay jobs through the proper deserialize path.
39+
#
40+
# NOTE: In Rails 5.2 test specs, ActiveJob::TestHelper installs a
41+
# _test_adapter on ActiveJob::Base via an outer around hook (before_setup).
42+
# The queue_adapter class method returns _test_adapter when present, so we
43+
# must use enable_test_adapter (not queue_adapter=) to override it.
44+
if RAILS_VERSION < 6.0 && adapter == :test
45+
@_original_test_adapter = ::ActiveJob::Base._test_adapter
46+
::ActiveJob::Base.enable_test_adapter(Rails52FullPayloadTestAdapter.new)
47+
else
48+
::ActiveJob::Base.queue_adapter = adapter
49+
end
1250

1351
boot_adapter(adapter)
1452

1553
example.run
1654
ensure
55+
if RAILS_VERSION < 6.0 && adapter == :test
56+
if @_original_test_adapter
57+
::ActiveJob::Base.enable_test_adapter(@_original_test_adapter)
58+
else
59+
::ActiveJob::Base.disable_test_adapter
60+
end
61+
end
62+
1763
reset_adapter(adapter)
1864

1965
teardown_sentry_test
@@ -35,9 +81,19 @@ def drain(at: nil)
3581
if RAILS_VERSION < 6.0
3682
# Rails 5.2: perform_enqueued_jobs always requires a block and only runs
3783
# jobs enqueued *inside* the block. Manually flush already-enqueued jobs.
84+
# When using Rails52FullPayloadTestAdapter, each payload also carries a
85+
# :_sentry_full_payload key with the complete serialize output. Drive
86+
# those jobs through Base.execute so our deserialize override runs and
87+
# populates @_sentry_trace_headers / @_sentry_user before perform_now.
3888
jobs = queue_adapter.enqueued_jobs.dup
3989
queue_adapter.enqueued_jobs.clear
40-
jobs.each { |payload| send(:instantiate_job, payload).perform_now }
90+
jobs.each do |payload|
91+
if (full = payload[:_sentry_full_payload])
92+
::ActiveJob::Base.execute(full)
93+
else
94+
send(:instantiate_job, payload).perform_now
95+
end
96+
end
4197
else
4298
kwargs = at ? { at: at } : {}
4399
perform_enqueued_jobs(**kwargs)

0 commit comments

Comments
 (0)