Skip to content

Commit 4dcc2aa

Browse files
solnicclaude
andcommitted
perf(active_job): boot the dummy app once per spec group
The harness was calling make_basic_app in its around-each block, which creates a fresh Rails::Application subclass and runs every initializer on each example. With 98 AJ examples that overhead dwarfed the actual test work — and worse, it left behind state (Sidekiq's @config_blocks list, accumulated routes, lingering Rails::Application subclasses) that made each subsequent make_basic_app a little slower. Under Ruby 3.4 + Rails 8.1.3 the per-example time grew 3× over the run, pushing the full sentry-rails CI past the 15-min timeout. Hoist make_basic_app to before(:all) and replicate the per-example bits of Sentry::Rails::Railtie's after_initialize hook in the around block — re-init Sentry, re-activate tracing / structured logging, re-register the AJ event handlers. The one-time extensions (controller methods, streaming reporter, backtrace cleanup, etc.) were already installed by the initial make_basic_app and persist for the group. Also memoize the SidekiqAdapter instance in the :sidekiq context. Each SidekiqAdapter.new appended to Sidekiq's internal @config_blocks list and added an on(:quiet) callback; creating a fresh adapter per example was unnecessary global churn. Result: spec/active_job goes from 33s → 0.8s, and the full sentry-rails spec task (Ruby 3.4 + Rails 8.1.3) goes from 9:22 to 2:31 — well under the CI limit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e01fd1b commit 4dcc2aa

2 files changed

Lines changed: 53 additions & 2 deletions

File tree

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,52 @@
1717
let(:adapter) { adapter }
1818
let(:configure_sentry) { proc { } }
1919

20+
# Boot the dummy Rails app ONCE per example group. Each +make_basic_app+
21+
# call creates a new +Rails::Application+ subclass and re-runs every
22+
# initializer — including Sidekiq's railtie (which appends two entries
23+
# to +Sidekiq.@config_blocks+) and Rails' route-drawing (which also
24+
# accumulates). Repeating that for every example caused per-example
25+
# time to grow ~3× over the run, which is what pushed the
26+
# Ruby 3.4 + Rails 8.1.3 CI matrix past the 15-min timeout.
27+
#
28+
# We reproduce the relevant per-example pieces of the Sentry/Rails
29+
# railtie's +config.after_initialize+ block below (re-init Sentry,
30+
# re-activate tracing/structured logging, re-register AJ event
31+
# handlers) so each example still gets a fresh Sentry configuration.
32+
before(:all) do
33+
make_basic_app
34+
end
35+
2036
around do |example|
21-
make_basic_app(&configure_sentry)
37+
Sentry.init do |config|
38+
config.release = "beta"
39+
config.dsn = "http://12345:67890@sentry.localdomain:3000/sentry/42"
40+
config.transport.transport_class = Sentry::DummyTransport
41+
config.background_worker_threads = 0
42+
config.include_local_variables = true
43+
configure_sentry.call(config, ::Rails.application) if configure_sentry
44+
end
45+
46+
# Mirror the bits of Sentry::Rails::Railtie's after_initialize hook
47+
# that need to run AFTER Sentry.init each example — the one-time
48+
# extensions (controller methods, streaming reporter, backtrace
49+
# cleanup callback, etc.) were already wired up by the initial
50+
# make_basic_app in before(:all) and persist for the rest of the
51+
# group.
52+
if Sentry.configuration.tracing_enabled? && Sentry.configuration.instrumenter == :sentry
53+
Sentry::Rails::Tracing.register_subscribers(Sentry.configuration.rails.tracing_subscribers)
54+
Sentry::Rails::Tracing.subscribe_tracing_events
55+
Sentry::Rails::Tracing.patch_active_support_notifications
56+
end
57+
58+
if Sentry.configuration.rails.structured_logging.enabled? && Sentry.configuration.enable_logs
59+
Sentry::Rails::StructuredLogging.attach(Sentry.configuration.rails.structured_logging)
60+
end
61+
62+
if defined?(Sentry::Rails::ActiveJobExtensions)
63+
Sentry::Rails::ActiveJobExtensions::SentryReporter.register_event_handlers
64+
end
65+
2266
setup_sentry_test
2367

2468
boot_adapter(adapter)

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,15 @@
3030
end
3131

3232
RSpec.shared_context "sidekiq adapter" do
33+
# Instantiated once. Each SidekiqAdapter.new appends blocks to
34+
# Sidekiq's internal @config_blocks list (configure_server) and adds
35+
# an on(:quiet) callback (configure_client). Creating a fresh
36+
# adapter per example accumulated several hundred entries across a
37+
# full suite run and showed up as compounding per-example slowdown.
38+
SIDEKIQ_ADAPTER_FOR_TEST = ::ActiveJob::QueueAdapters::SidekiqAdapter.new
39+
3340
def queue_adapter_for_test
34-
::ActiveJob::QueueAdapters::SidekiqAdapter.new
41+
SIDEKIQ_ADAPTER_FOR_TEST
3542
end
3643

3744
# Scope fake mode to this example only — the block form of +fake!+

0 commit comments

Comments
 (0)