class BatchGenerateWeatherArtsWorker include Sidekiq::Worker GENERATION_INTERVAL = 24.hours MAX_DURATION = 50.minutes SLEEP_DURATION = 120.seconds def perform(*args) start_time = Time.current cities_to_process = get_eligible_cities cities_to_process.each do |city| break if Time.current - start_time > MAX_DURATION Rails.logger.info "Generating weather art for #{city.name}" GenerateWeatherArtWorker.perform_async(city.id) sleep SLEEP_DURATION end end private def get_eligible_cities cutoff_time = Time.current - GENERATION_INTERVAL City.active .joins("LEFT JOIN ( SELECT city_id, MAX(created_at) as last_generation_time FROM weather_arts GROUP BY city_id ) latest_arts ON cities.id = latest_arts.city_id") .where("latest_arts.last_generation_time IS NULL OR latest_arts.last_generation_time < ?", cutoff_time) .order(:priority) end end