Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latest sidekiq breaks Sentrys assumption of ActiveJob being loaded #2517

Open
jgraichen opened this issue Jan 23, 2025 · 3 comments
Open

Latest sidekiq breaks Sentrys assumption of ActiveJob being loaded #2517

jgraichen opened this issue Jan 23, 2025 · 3 comments
Assignees

Comments

@jgraichen
Copy link

jgraichen commented Jan 23, 2025

Issue Description

Sidekiq v7.3.8 always requires its ActiveJob adapter now. That means that a top-level ActiveJob module will be defined, even if active_job itself isn't loaded nor configured at all.

Since Sentry tries to load its ActiveJob job when the top-level ActiveJob constant exists, this error happens:

Failure/Error: require File.expand_path('../config/environment', __dir__)

NameError:
  uninitialized constant ActiveJob::Base
# ~/.gem/ruby/3.3.0/gems/sentry-rails-5.22.1/app/jobs/sentry/send_event_job.rb:9:in `<module:Sentry>'
# ~/.gem/ruby/3.3.0/gems/sentry-rails-5.22.1/app/jobs/sentry/send_event_job.rb:4:in `<top (required)>'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/core_ext/kernel.rb:26:in `require'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/cref.rb:60:in `const_get'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/cref.rb:60:in `get'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/eager_load.rb:173:in `block in actual_eager_load_dir'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/helpers.rb:47:in `block in ls'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/helpers.rb:25:in `each'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/helpers.rb:25:in `ls'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/eager_load.rb:168:in `actual_eager_load_dir'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/eager_load.rb:17:in `block (2 levels) in eager_load'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/eager_load.rb:16:in `each'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/eager_load.rb:16:in `block in eager_load'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/eager_load.rb:10:in `synchronize'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader/eager_load.rb:10:in `eager_load'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader.rb:413:in `block in eager_load_all'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader.rb:411:in `each'
# ~/.gem/ruby/3.3.0/gems/zeitwerk-2.7.1/lib/zeitwerk/loader.rb:411:in `eager_load_all'
# ~/.gem/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application/finisher.rb:80:in `block in <module:Finisher>'
# ~/.gem/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `instance_exec'
# ~/.gem/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:32:in `run'
# ~/.gem/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:61:in `block in run_initializers'
# ~/.gem/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/initializable.rb:60:in `run_initializers'
# ~/.gem/ruby/3.3.0/gems/railties-7.2.2.1/lib/rails/application.rb:435:in `initialize!'
# ./config/environment.rb:7:in `<top (required)>'

See sidekiq/sidekiq#6584 too.

Reproduction Steps

Try to start a demo Rails application that does not load ActiveJob but Sidekiq 7.3.8.

To not load ActiveJob, adjust application.rb like this:

# frozen_string_literal: true

require_relative 'boot'

require 'rails'
# Pick the frameworks you want:
require 'active_model/railtie'
# require 'active_job/railtie'
require 'active_record/railtie'
# require 'active_storage/engine'
require 'action_controller/railtie'
# require 'action_mailer/railtie'
# require 'action_mailbox/engine'
# require 'action_text/engine'
require 'action_view/railtie'
# require 'action_cable/engine'
require 'rails/test_unit/railtie'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

Expected Behavior

Not to break.

Actual Behavior

Apps don't boot anymore (sidekiq/sidekiq#6584).

Ruby Version

3.3.5

SDK Version

5.22.1

Integration and Its Version

Rails, Sidekiq

Sentry Config

Sentry.init do |config|
  # Far too many exception when sidekiq workers are just reconnecting
  config.excluded_exceptions += %w[Redis::CannotConnectError RedisClient::CannotConnectError]

  # Do not send full list of gems with each event
  config.send_modules = false
end
@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jan 23, 2025
@solnic
Copy link
Collaborator

solnic commented Jan 23, 2025

Ohhhh so that's why I had to disable eager loading in our spec suite the other day. Thanks for reporting this. I'll figure out a solution.

@piotr-switlicki
Copy link

piotr-switlicki commented Jan 27, 2025

Ohhhh so that's why I had to disable eager loading in our spec suite the other day. Thanks for reporting this. I'll figure out a solution.

What about Object.const_defined?("ActiveJob::Base")? Maybe it wouldn't be much smarter, but at least:

  1. A name clash would be way less likely to happen
  2. It would be more logical (since that's the actual constant this code is referring to)

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 3 Jan 27, 2025
@solnic
Copy link
Collaborator

solnic commented Jan 27, 2025

@piotr-switlicki I need to double check but I tried all kinds of approaches and this code just breaks in various ways because ActiveJob itself crashes internally as it's not loading correctly when there's already a top level ActiveJob constant defined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

When branches are created from issues, their pull requests are automatically linked.

3 participants