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>
This commit is contained in:
Vishnu Narayanan
2026-03-17 14:57:49 +05:30
committed by GitHub
parent a8d53a6df4
commit 688218de0a
4 changed files with 71 additions and 3 deletions

View File

@@ -34,5 +34,7 @@ end
# https://github.com/ondrejbartas/sidekiq-cron
Rails.application.reloader.to_prepare do
# TODO: Switch to `load_from_hash!(..., source: 'schedule')` once we have a
# safe cleanup path for YAML-backed cron jobs already persisted in Redis.
Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file) if File.exist?(schedule_file) && Sidekiq.server?
end

View File

@@ -2,10 +2,12 @@
# use https://crontab.guru/ to validate
# validations for this file exist in /spec/configs/schedule_spec.rb
# executed At 12:00 on every day-of-month.
# executed daily at 0000 UTC
# schedules daily deferred jobs at stable times for each installation
# keep the existing schedule key while the cron loader still uses load_from_hash
internal_check_new_versions_job:
cron: '0 12 */1 * *'
class: 'Internal::CheckNewVersionsJob'
cron: '0 0 * * *'
class: 'Internal::TriggerDailyScheduledItemsJob'
queue: scheduled_jobs
# # executed At every 5th minute..
trigger_scheduled_items_job: