Skip to content

Resolve code-reloading issues in usage data specs

What does this MR do?

This should fix a version of this issue, but involving usage ping specs:

ArgumentError:
       A copy of Gitlab::SidekiqMiddleware::DuplicateJobs::Client has been removed from the module tree but is still active!
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:529:in `load_missing_constant'
     # /Users/gary/.gem/ruby/2.6.6/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/active_support.rb:61:in `block in load_missing_constant'
     # /Users/gary/.gem/ruby/2.6.6/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/active_support.rb:17:in `allow_bootsnap_retry'
     # /Users/gary/.gem/ruby/2.6.6/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/active_support.rb:60:in `load_missing_constant'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:214:in `const_missing'
     # ./lib/gitlab/sidekiq_middleware/duplicate_jobs/client.rb:8:in `call'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/middleware/chain.rb:130:in `block in invoke'
     # /Users/gary/.gem/ruby/2.6.6/gems/gitlab-labkit-0.12.1/lib/labkit/middleware/sidekiq/client.rb:21:in `block in call'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/middleware/chain.rb:128:in `block in invoke'
     # /Users/gary/.gem/ruby/2.6.6/gems/gitlab-labkit-0.12.1/lib/labkit/middleware/sidekiq/context/client.rb:15:in `block in call'
     # /Users/gary/.gem/ruby/2.6.6/gems/gitlab-labkit-0.12.1/lib/labkit/context.rb:32:in `with_context'
     # /Users/gary/.gem/ruby/2.6.6/gems/gitlab-labkit-0.12.1/lib/labkit/middleware/sidekiq/context/client.rb:12:in `call'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/middleware/chain.rb:130:in `block in invoke'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/middleware/chain.rb:133:in `invoke'
     # /Users/gary/.gem/ruby/2.6.6/gems/gitlab-labkit-0.12.1/lib/labkit/middleware/sidekiq/client.rb:20:in `call'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/middleware/chain.rb:130:in `block in invoke'
     # ./lib/gitlab/sidekiq_middleware/worker_context.rb:9:in `wrap_in_optional_context'
     # ./lib/gitlab/sidekiq_middleware/worker_context/client.rb:18:in `call'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/middleware/chain.rb:130:in `block in invoke'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/middleware/chain.rb:133:in `invoke'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/client.rb:212:in `process_single'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/client.rb:71:in `push'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/worker.rb:149:in `client_push'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/worker.rb:108:in `perform_in'
     # ./config/initializers/forbid_sidekiq_in_transactions.rb:36:in `block (2 levels) in <module:NoEnqueueingFromTransactions>'
     # ./app/models/concerns/update_highest_role.rb:29:in `block in update_highest_role'
     # ./lib/after_commit_queue.rb:29:in `instance_eval'
     # ./lib/after_commit_queue.rb:29:in `run_after_commit_or_now'
     # ./app/models/concerns/update_highest_role.rb:24:in `update_highest_role'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:428:in `block in make_lambda'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:273:in `block in simple'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:517:in `block in invoke_after'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:517:in `each'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:517:in `invoke_after'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:136:in `run_callbacks'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/callbacks.rb:825:in `_run_commit_callbacks'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/transactions.rb:339:in `committed!'
     # ./config/initializers/forbid_sidekiq_in_transactions.rb:50:in `block in committed!'
     # ./config/initializers/forbid_sidekiq_in_transactions.rb:8:in `skipping_transaction_check'
     # ./config/initializers/forbid_sidekiq_in_transactions.rb:50:in `committed!'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:127:in `commit_records'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:265:in `block in commit_transaction'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:255:in `commit_transaction'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:293:in `block in within_new_transaction'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in `block (2 levels) in synchronize'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:278:in `within_new_transaction'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:280:in `transaction'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/transactions.rb:212:in `transaction'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/transactions.rb:366:in `with_transaction_returning_status'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/transactions.rb:318:in `save!'
     # /Users/gary/.gem/ruby/2.6.6/gems/activerecord-6.0.3.1/lib/active_record/suppressor.rb:48:in `save!'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-activerecord-0.6.0/lib/state_machines/integrations/active_record.rb:515:in `block in save!'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-activerecord-0.6.0/lib/state_machines/integrations/active_record.rb:530:in `block in around_save'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:150:in `block in run_actions'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:170:in `catch_exceptions'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:148:in `run_actions'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:133:in `run_callbacks'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:212:in `run_callbacks'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:63:in `block (2 levels) in perform'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:63:in `catch'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:63:in `block in perform'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:186:in `within_transaction'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-0.5.0/lib/state_machines/transition_collection.rb:62:in `perform'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-activerecord-0.6.0/lib/state_machines/integrations/active_record.rb:530:in `around_save'
     # /Users/gary/.gem/ruby/2.6.6/gems/state_machines-activerecord-0.6.0/lib/state_machines/integrations/active_record.rb:515:in `save!'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/evaluation.rb:18:in `create'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/strategy/create.rb:12:in `block in result'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/strategy/create.rb:9:in `tap'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/strategy/create.rb:9:in `result'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/factory.rb:43:in `run'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/factory_runner.rb:29:in `block in run'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/notifications.rb:182:in `instrument'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/factory_runner.rb:28:in `run'
     # /Users/gary/.gem/ruby/2.6.6/gems/factory_bot-5.1.0/lib/factory_bot/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
     # ./ee/spec/lib/ee/gitlab/usage_data_spec.rb:291:in `block (4 levels) in <main>'
     # ./spec/support/helpers/usage_data_helpers.rb:239:in `block (2 levels) in for_defined_days_back'
     # /Users/gary/.gem/ruby/2.6.6/gems/timecop-0.9.1/lib/timecop/timecop.rb:201:in `travel'
     # /Users/gary/.gem/ruby/2.6.6/gems/timecop-0.9.1/lib/timecop/timecop.rb:129:in `send_travel'
     # /Users/gary/.gem/ruby/2.6.6/gems/timecop-0.9.1/lib/timecop/timecop.rb:62:in `travel'
     # ./spec/support/helpers/usage_data_helpers.rb:238:in `block in for_defined_days_back'
     # ./spec/support/helpers/usage_data_helpers.rb:237:in `each'
     # ./spec/support/helpers/usage_data_helpers.rb:237:in `for_defined_days_back'
     # ./ee/spec/lib/ee/gitlab/usage_data_spec.rb:290:in `block (3 levels) in <main>'
     # ./spec/spec_helper.rb:324:in `block (3 levels) in <main>'
     # /Users/gary/.gem/ruby/2.6.6/gems/sidekiq-5.2.9/lib/sidekiq/testing.rb:55:in `server_middleware'
     # ./spec/support/sidekiq_middleware.rb:9:in `with_sidekiq_server_middleware'
     # ./spec/spec_helper.rb:315:in `block (2 levels) in <main>'
     # ./spec/spec_helper.rb:311:in `block (3 levels) in <main>'
     # /Users/gary/.gem/ruby/2.6.6/gems/gitlab-labkit-0.12.1/lib/labkit/context.rb:32:in `with_context'
     # ./spec/spec_helper.rb:311:in `block (2 levels) in <main>'
     # /Users/gary/.gem/ruby/2.6.6/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:123:in `block in run'
     # /Users/gary/.gem/ruby/2.6.6/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `loop'
     # /Users/gary/.gem/ruby/2.6.6/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `run'
     # /Users/gary/.gem/ruby/2.6.6/gems/rspec-retry-0.6.1/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
     # /Users/gary/.gem/ruby/2.6.6/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:37:in `block (2 levels) in setup'
     # /Users/gary/.gem/ruby/2.6.6/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
     # /Users/gary/.gem/ruby/2.6.6/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:55:in `load'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:318:in `block in load'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:291:in `load_dependency'
     # /Users/gary/.gem/ruby/2.6.6/gems/activesupport-6.0.3.1/lib/active_support/dependencies.rb:318:in `load'
     # /Users/gary/.gem/ruby/2.6.6/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call'
     # /Users/gary/.gem/ruby/2.6.6/gems/nakayoshi_fork-0.0.4/lib/nakayoshi_fork.rb:23:in `fork'
     # /Users/gary/.gem/ruby/2.6.6/gems/nakayoshi_fork-0.0.4/lib/nakayoshi_fork.rb:23:in `fork'
     # -e:1:in `<main>'

Thanks to @engwan for the solution here

Screenshots

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • Label as security and @ mention @gitlab-com/gl-security/appsec
  • The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • Security reports checked/validated by a reviewer from the AppSec team
Edited by Gary Holtz

Merge request reports

Loading