| 1 | # frozen_string_literal: true |
| 2 | |
| 3 | # Periodic sweep that enqueues a MirrorSyncJob for every mirror due for a |
| 4 | # refresh. Runs from Solid Queue's recurring schedule (config/recurring.yml). |
| 5 | # |
| 6 | # Fanning out one job per repo (rather than syncing inline) keeps any single |
| 7 | # slow/hung upstream from blocking the others and lets the queue spread the work |
| 8 | # across workers. "Due" means never-synced or last synced before the interval. |
| 9 | class MirrorSyncSchedulerJob < ApplicationJob |
| 10 | queue_as :default |
| 11 | |
| 12 | # How stale a mirror may get before we re-sync it on the schedule. Webhooks, |
| 13 | # when configured, sync sooner. |
| 14 | SYNC_INTERVAL = ActiveSupport::Duration.build(Integer(ENV.fetch("MIRROR_SYNC_INTERVAL_SECONDS", 3600))) |
| 15 | |
| 16 | # Don't pile up on a mirror that's already syncing. |
| 17 | def perform |
| 18 | cutoff = Time.current - SYNC_INTERVAL |
| 19 | |
| 20 | due = Repository.mirrors |
| 21 | .where.not(mirror_status: "syncing") |
| 22 | .where("mirror_synced_at IS NULL OR mirror_synced_at < ?", cutoff) |
| 23 | |
| 24 | due.find_each do |repo| |
| 25 | MirrorSyncJob.perform_later(repo.id) |
| 26 | end |
| 27 | end |
| 28 | end |