Files
leadchat/spec/jobs/internal/trigger_daily_scheduled_items_job_spec.rb
Vishnu Narayanan 688218de0a feat: distributed scheduling for version check job (#13042)
This change spreads Chatwoot Hub version checks across the day by
scheduling each installation at a stable minute derived from its
installation identifier, instead of having all instances check at the
same fixed time.

Closes
-
https://linear.app/chatwoot/issue/CW-6107/handle-the-spike-at-12-utc-on-chatwoot-hub

What changed
- Added `Internal::TriggerDailyScheduledItemsJob` to act as the daily
trigger for deferred internal jobs.
- Updated the version check cron entry to run once daily at `00:00 UTC`
and enqueue the actual version check for that installation’s assigned
minute of the day.
- Used a deterministic minute-of-day derived from
`ChatwootHub.installation_identifier` so the check time stays stable
across deploys and restarts.
- Kept the existing cron schedule key while switching it to the new
orchestrator job.

How to test
- Run `bundle exec rspec
spec/jobs/internal/check_new_versions_job_spec.rb
spec/jobs/internal/trigger_daily_scheduled_items_job_spec.rb
spec/configs/schedule_spec.rb`
- In a Rails console, run
`Internal::TriggerDailyScheduledItemsJob.perform_now` and verify
`Internal::CheckNewVersionsJob` is enqueued with a `wait_until` later
the same UTC day.
- In Super Admin settings, use Refresh and verify the version check
still runs immediately.

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-03-17 02:27:49 -07:00

40 lines
1.4 KiB
Ruby

require 'rails_helper'
RSpec.describe Internal::TriggerDailyScheduledItemsJob do
subject(:perform_job) { described_class.perform_now }
let(:installation_id) { 'test-installation-id' }
let(:designated_minute) { Digest::MD5.hexdigest(installation_id).hex % 1440 }
let(:scheduled_time) { Time.current.utc.beginning_of_day + designated_minute.minutes }
let(:configured_job) { instance_double(ActiveJob::ConfiguredJob, perform_later: true) }
before do
allow(ChatwootHub).to receive(:installation_identifier).and_return(installation_id)
allow(Internal::CheckNewVersionsJob).to receive(:set).and_return(configured_job)
end
it 'enqueues the job' do
expect { described_class.perform_later }.to have_enqueued_job(described_class)
.on_queue('scheduled_jobs')
end
it 'schedules the version check at a stable minute in production' do
allow(Rails.env).to receive(:production?).and_return(true)
travel_to Time.zone.parse('2026-03-17 08:00:00 UTC') do
perform_job
expect(Internal::CheckNewVersionsJob).to have_received(:set).with(wait_until: scheduled_time)
expect(configured_job).to have_received(:perform_later)
end
end
it 'does not schedule the version check outside production' do
allow(Rails.env).to receive(:production?).and_return(false)
perform_job
expect(Internal::CheckNewVersionsJob).not_to have_received(:set)
end
end