2014-09-11 5 views
28

Ho trovato questo Schedule one-time jobs in Rails ma questo mostra solo la pianificazione una tantum. Sono interessato a pianificare un lavoro ricorrente.Come pianificare i lavori ricorrenti in Job attivo (Rails 4.2)?

Delayed_job ha questo

self.delay(:run_at => 1.minute.from_now) 

Come faccio a fare una cosa del genere in Rails 4.2/Lavoro attivo?

+1

L'esempio di DelayedJob che hai postato sarebbe un lavoro una tantum in futuro rispetto a un lavoro ricorrente, che verrebbe ripetuto più e più volte. Che intendi? – rossta

+0

Ne voglio uno che funzioni di nuovo e di nuovo. –

+0

Non credo ci sia un'API ActiveJob per questo. A seconda del tuo sistema di background, ci sono estensioni (https://github.com/resque/resque-scheduler, https://github.com/ondrejbartas/sidekiq-cron) o semplicemente usa cron (https://github.com)/tomykaira/clockwork, https://github.com/javan/whenever) – rossta

risposta

11

Si può solo ri-accodare il lavoro al termine dell'esecuzione

class MyJob < ActiveJob::Base 
    RUN_EVERY = 1.hour 

    def perform 
    # do your thing 

    self.class.perform_later(wait: RUN_EVERY) 
    end 
end 
+8

Questa non è una soluzione affidabile: se si verifica un'eccezione, la catena si interrompe e alcuni adattatori di back-end non sembrano accettare gli argomenti di ActiveSupport :: Duration. È inoltre necessario avviare manualmente i lavori la prima volta. – Pak

+1

@Pak Si aggiunge sempre un blocco 'ensure' a livello di metodo o in una callback' after_perform'. –

+0

Lo facevamo, non è affidabile per alcuni motivi. 1) non tiene conto del tempo che impiega il tuo lavoro. Se il tuo lavoro richiede 5 minuti, sono 2 ore al giorno, il che significa che esegui circa 22 lavori/24 ore. (questo è risolvibile con clock matematico) 2) c'è la possibilità che un lavoro non venga eseguito a causa dell'arresto di un lavoratore. Se hai un lavoro che guarda "l'ora più recente di x" quando è in esecuzione, non si aggiornerà mai. 3) il blocco di garanzia non è garantito per l'esecuzione in caso di rimbalzo. se stai lavorando su heroku e fai una distribuzione mentre un lavoro è in esecuzione, c'è una buona possibilità che tu uccida il processo. –

20

Se si vuole ritardare l'esecuzione del lavoro a 10 minuti più tardi, due opzioni:

  1. SomeJob.set(wait: 10.minutes).perform_later(record)

  2. SomeJob.new(record).enqueue(wait: 10.minutes)

Ritardare a un momento specifico da ora utilizzare wait_until.

  1. SomeJob.set(wait_until: Date.tomorrow.noon).perform_later(record)

  2. SomeJob.new(record).enqueue(wait_until: Date.tomorrow.noon)

dettagli si rimanda al http://api.rubyonrails.org/classes/ActiveJob/Base.html.

Per lavori ricorrenti, è sufficiente inserire SomeJob.perform_now(record) in un cronjob (whenever).

Se si utilizza Heroku, è sufficiente inserire SomeJob.perform_now(record) in un'attività di rake programmata. Si prega di leggere ulteriori informazioni sul rake programmato qui: Heroku scheduler.

+2

Si noti che 'wait_until' si aspetta un'istanza di' ActiveSupport :: TimeWithZone' mentre 'wait' si aspetta un'istanza di' Date'. Piuttosto, l'oggetto passato a 'wait_until' deve rispondere a': to_f' e restituire i "secondi d'epoca" a cui attendere (secondi dal 1 gennaio 1970) – sameers

15

Simile alla risposta di Rab3, dal momento che ActiveJob ha il supporto per i callback, stavo pensando di fare qualcosa di simile

class MyJob < ActiveJob::Base 
    after_perform do |job| 
    # invoke another job at your time of choice 
    self.class.set(:wait => 10.minutes).perform_later(job.arguments.first) 
    end 

    def perform(the_argument) 
    # do your thing 
    end 
end 

activejob callbacks

+0

Mi piace un po 'di più; sembra più simile a rotaie. – deefour

2

Se stai usando resque come backend ActiveJob, è possibile utilizzare un combinazione di lavori pianificati di resque-scheduler e active_scheduler (https://github.com/JustinAiken/active_scheduler, che avvolge i lavori pianificati per funzionare correttamente con ActiveJob).