sidekiq
                                
                                
                                
                                    sidekiq copied to clipboard
                            
                            
                            
                        Unclear how to add automated test ensuring that Periodic Jobs configuration can be processed
Ruby version: 3.1.2 Rails version: 7.0.3.1 Sidekiq / Pro / Enterprise version(s): 6.5.1/ 5.5.1 / 2.5.1
We recently had an issue with Periodic Jobs where a typo in a single entry of our Periodic Jobs configuration caused our whole configuration to not be able to be processed. I'm looking for a way that we could add automated testing to ensure that our configuration can be processed. We've followed the testing instructions in https://github.com/mperham/sidekiq/wiki/Ent-Periodic-Jobs and no error is raised with our bad configuration.
The typo itself was that we passed a symbol to the tz: argument instead of a ActiveSupport::TimeZone instance. The error we observed was the following:
  WARN: NoMethodError: undefined method `now' for :pt:Symbol
4
5      def next_occurrence(now = @src.now, time_now = Time.now)
6                                    ^^^^
  WARN: /app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic/static_loop.rb:26:in `next_occurrence'
                                    
                                    
                                    
                                
Can you give me the entire error backtrace?
@mperham sure thing, here you go:
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic/static_loop.rb:26:in `next_occurrence'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic/config.rb:107:in `block in queue_for'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic/config.rb:106:in `each'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic/config.rb:106:in `queue_for'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic/config.rb:99:in `finish!'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic/manager.rb:56:in `persist'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/periodic.rb:95:in `block (2 levels) in <top (required)>'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-6.5.1/lib/sidekiq/component.rb:56:in `block in fire_event'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-6.5.1/lib/sidekiq/component.rb:55:in `each'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-6.5.1/lib/sidekiq/component.rb:55:in `fire_event'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/senate.rb:85:in `stage_coup!'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-ent-2.5.1/lib/sidekiq-ent/senate.rb:93:in `cycle'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-6.5.1/lib/sidekiq/component.rb:8:in `watchdog'
/app/vendor/bundle/ruby/3.1.0/gems/sidekiq-6.5.1/lib/sidekiq/component.rb:17:in `block in safe_thread'
                                    
                                    
                                    
                                
I guess I'm unclear on something: why doesn't the developer test this by simply starting Sidekiq? It sounds like someone changed the periodic configuration and those changes were pushed straight to production without any staging or integration testing. Is your deployment process "if CI is green, push to production"?
@mperham you're right, this definitely could be caught by manual testing. Just looking for a way to catch it via automated testing if that's possible.
@f1sherman We only enable certain crons in prod, so we had issues similar. Similar to the wiki guide, we have a class
class PeriodicJobsRegistration
  def self.call(mgr)
    # ...
    mgr.register('0 7 * * *', 'OurDailyWorker') # Daily at 7:00AM UTC
  end
and a verifier class defined at the top of our rspec periodic_jobs_registration_spec.rb
class PeriodicJobVerifier
  # raise an error to fail the spec.
  def register(_sched, klass, args: nil, **_rest)
    # Will raise if the constant is not defined.
    klass_constant = klass.constantize if klass.is_a?(String)
    raise 'Passing constants to periodic job registrations is deprecated, pass a String' if klass.is_a?(Class)
    raise 'Worker must include Sidekiq::Worker or inherit ApplicationWorker' unless klass_constant.ancestors.include?(Sidekiq::Worker)
  end
end
# ...
RSpec.describe PeriodicJobsRegistration do
  it 'does not raise an error for any job registration' do
    expect { described_class.call(PeriodicJobVerifier.new) }.not_to raise_error
  end
end
You could add a check in the verifier that the :tz arg is an ActiveSupport::TimeZone instance.
@BobbyMcWho thank you, that’s helpful. I think what would be more useful IMO would be a way to test that Sidekiq can process our configuration successfully. That way if there are any other issues that might cause Sidekiq to fail to process the config we could catch it in automated testing.
Unfortunately I don't have a better solution than "start Sidekiq" right now.