# frozen_string_literal: true # Una tarea que se corre periódicamente class PeriodicJob < ApplicationJob class RunAgainException < StandardError; end STARTING_INTERVAL = Stat::INTERVALS.first # Descartar y notificar si pasó algo más. # # XXX: En realidad deberíamos seguir reintentando? discard_on(StandardError) do |_, error| ExceptionNotifier.notify_exception(error) end # Correr indefinidamente una vez por hora. # # XXX: El orden importa, si el descarte viene después, nunca se va a # reintentar. retry_on(PeriodicJob::RunAgainException, wait: 1.try(STARTING_INTERVAL), attempts: Float::INFINITY, jitter: 0) private # Las clases que implementen esta tienen que usar este método al # terminar. def run_again! raise PeriodicJob::RunAgainException, 'Reintentando' end # El intervalo de inicio # # @return [Symbol] def starting_interval STARTING_INTERVAL end # La última recolección de estadísticas o empezar desde el principio # de los tiempos. # # @return [Stat] def last_stat @last_stat ||= site.stats.where(name: stat_name).last || site.stats.build(created_at: Time.new(1970, 1, 1)) end # Devuelve el comienzo del intervalo # # @return [Time] def beginning_of_interval @beginning_of_interval ||= last_stat.created_at.try(:"beginning_of_#{starting_interval}") end def stop_file @stop_file ||= Rails.root.join('tmp', self.class.to_s.tableize) end def stop? File.exist? stop_file end end