2013-04-16 13 views
8

Geçenlerde Sidekiq ile çalışmaya başladı ve uzun zamandır arıyordum müthiş bir özellik olduğunu fark: Ben gerek kalmazRuby on Rails + Sidekiq: Zamanlanmış bir iş başlangıç ​​saatini nasıl değiştirebilirim?

UserMailer.delay_until(5.days.from_now).find_more_friends_email 

Temelde gelecekte bir iş zamanlayabilirsiniz benim Yeni bir etkinlik için bir başlangıç ​​zamanı ile sürekli anket uygulaması.

Şimdi bu bir cazibe gibi çalışır, ama nasıl bir iş başlangıç ​​zamanı değiştirebilirim? Çoğu zaman zamanlanmış bazı etkinlikler başlangıç ​​saatlerini değiştirir. Bunu sidekiq'de nasıl kopyalarım? Sadece başlangıç ​​zamanını değiştirmek için

ben işi silmek ve yeni bir tane oluşturabilirsiniz biliyorum ama bu mümkün mü?

DÜZENLEME: Burada Oto Brglez fikri üzerine inşa edilmiş ve

belgelenmiş kod şudur: Şimdi eğer

module TaskStuff 
    class TaskSetter 
    include Sidekiq::Worker 
    sidekiq_options retry: false 

    def perform(task_id) 
     task = Task.find(task_id) 
     # Get the worker that's performing this job 
     if worker = AppHelpers.find_worker(jid) 
     # If the worker matches the "at" timestamp then this is the right one and we should execute it 
     if worker.last["payload"]["at"].to_s.match(/(\d*\.\d{0,3})\d*/)[1] == task.start.to_f.to_s.match(/(\d*\.\d{0,3})\d*/)[1] 
      task.execute 
     else 
      custom_logger.debug("This worker is the wrong one. Skipping...") 
     end 
     else 
     custom_logger.error("We couldn't find the worker") 
     end 
    end 
    end 
end 


module AppHelpers 

    [...] 

    def self.find_worker(jid) 
    Sidekiq::Workers.new.select {|e| e.last["payload"]["jid"] == jid}.first 
    end 

    [...] 

end 

> task = Task.create(start: 5.hours.from_now) 
> TaskStuff::TastSetter.perform_at(task.start, task.id) 

görev idam alacak bu

> task.update_attributes(start: 4.hours.from_now) 
> TaskStuff::TastSetter.perform_at(task.start, task.id) 
4 saat ve diğer iş (5 saat içinde gerçekleştirilecek) zamana ulaştığında yok sayılacak ve kaldırılacaktır.

Başlangıçta worker.last["payload"]["at"] yerine Time.now kullanmayı denedim, ancak zamanlanmış bir iş her zaman zamanında yürütülmeyeceğinden dolayı oldukça yanlış olabilirdi. 15 saniyelik bir kontrol aralığı vardır ve tüm işçiler başka yerlerde meşgulse, iş daha da gecikebilir.

task.start okunurken farklı bir ondalık sayıya sahip bir float almam ve koşulun geçmemesi nedeniyle Regexp kullanmak zorunda kaldım. Bu şekilde, her iki değeri de 3 ondalık olarak alıyorum.

ben buldum almanın tek yolu işinin niteliği görevlisi aracılığıyla bunu almak gereğidir "at". Eğer Redis'e sorsaydım ya da Mike'ın Sidekiq::ScheduledSet.new'unu kullanacak olsaydım, şu anki işi alamazdım çünkü Redis'ten çoktan çekilmiş olurdu.

DÜZENLEME 2: ilgilenen herkes için

, ben de benzer ancak farklı bir yaklaşımla gitti. Temel olarak, Task'un başlangıç ​​zamanını karşılaştırmak yerine, modele ve start_token adlı Sidekiq çağrısına fazladan bir alan ekledim. Eğer sidekiq işi nesnenin sahip olduğu aynı belirteçle çağrılmışsa, aksi halde işi atın ve atın. Model, start_time modelini her değiştirdiğinde jeton güncellenir.

+1

ikinci düzenleme doğrultusunda ve İşimle içinde bir ActiveRecord nesnesi kullanıyorum olarak olanlar için bu, yardımcı olabilir, ben updated_at alanını kullanıyorum. ActiveRecord kimliğimle işime aktarıyorum ve işim başladığında, updated_at'ın hala aynı olup olmadığını kontrol ediyorum – phyzalis

cevap

3

Ben iş güncellenmesi yoludur/düzenleme sanmıyorum. Genellikle her şey değiştiğinde yeni bir iş yaratırım. Ve belirli bir görevi yürütmek için doğru zaman o zaman işte kendisi zaman haklıysa Bu muhtemelen soruya cevap değil

+0

İlginç nokta. Bunu düşünmedim. İşin doğru olup olmadığını kontrol etmek için geçerli saati mi (Time.now) mi yoksa planlanan iş için tam başlangıç ​​saatini elde etmenin bir yolu var mı? – Oktav

+0

Fikrinizi üzerine inşa ettim ve kodumu – Oktav

+0

Ok. :) Amacım için zaman meselesi değildi. Tarih yeterliydi. Biraz kod koy ve göreceğiz .. –

26

... aksi takdirde sadece atlamak görevle devam ... işaretler ancak bu ilk "sidekiq için zaten planlanmış bir işin süresini arttırmak" için google'da.

Sidekiq bir SortedEntry iş bu yöntemi vardır.

iş bulun:

job = Sidekiq::ScheduledSet.new.find_job(job_id) 

işini zamanlamak:

job.reschedule(Time.now + 2.hours) 
+1

Bu adama a: bira: – user1262904

+1

Not Ayrıca belirli bir işin ne zaman çalıştırılacağını görebilirsiniz 'Sidekiq :: ScheduledSet.new.find {criteria} .at'. [Dökümantasyon burada] (http://www.rubydoc.info/github/mperham/sidekiq/Sidekiq/SortedEntry#at-instance_method) –