2015-10-15 9 views
12

Od API Rails, znalazłem ActiveJob może retry_job przedziale:Jak ustawić liczbę ponownych prób dla Sidekiq przy pomocy ActiveJob?

my_job_instance.enqueue 
my_job_instance.enqueue wait: 5.minutes 
my_job_instance.enqueue queue: :important 
my_job_instance.enqueue wait_until: Date.tomorrow.midnight 

http://api.rubyonrails.org/classes/ActiveJob/Enqueuing.html

Ale jeśli chcę ustawić liczbę ponownych prób, takich jak Sidekiq to:

include Sidekiq::Worker 
sidekiq_options :retry => 5 

https://github.com/mperham/sidekiq/wiki/Error-Handling

Jak wykonać ten przykładowy kod?

class SiteScrapperJob < ActiveJob::Base 
    rescue_from(ErrorLoadingSite) do 
    retry_job queue: :low_priority 
    end 

    def perform(*args) 
    # raise ErrorLoadingSite if cannot scrape 
    end 
end 

Teraz dodałem to do mojej klasy pracy:

Sidekiq.default_worker_options = { retry: 5 } 

Ale to nie wydaje się być bardzo dobre.

Odpowiedz

2

Domyślnymi wartościami dla Sidekiq są here. Atrybut retry "akceptuje" wartość boolowską, a nie liczbę, jak zakładałeś.

Od scalenia active_job z Rails to other file widać, że po raz kolejny retry nie przyjmuje liczby ponownych prób.

Co to jest documentation says to zadanie, które można zdefiniować, jeśli zadanie zostanie ponowione lub nie.

Próbowałem również znaleźć, czy plik config/sidekiq.yml może otrzymać ten numer, i wydaje się, że nie może.

Wreszcie

Jeśli nie naprawić błąd w ciągu 25 prób (około 21 dni), Sidekiq zatrzyma powtórzeń i przenieść zadanie do kolejki zadań Martwego. Możesz naprawić błąd i ponownie spróbować go ręcznie w dowolnym czasie w ciągu najbliższych 6 miesięcy za pomocą interfejsu internetowego.

+0

Jesteś niepoprawny. "Ponów" może być liczbą. https://github.com/mperham/sidekiq/wiki/Error-Handling#configuration –

+1

Tytuł twojego pytania mówi "z ActiveJob". Adres URL wysłany nie pochodzi z ActiveJob. Właściciel repo (@MikePerham) odpowiedział również, że nie możesz –

+0

Dziękuję. Dodałem 'Sidekiq.default_worker_options = {retry: 5}' do mojej klasy. Ale wydaje się, że praca jest gorsza (spróbuj ponownie wiele razy dziennie!). Domyślne czasy ponowienia to 25. Czy nie mogę go dostosować? – scho

8

Nie możesz. Jeśli chcesz używać rzeczy specyficznych dla Sidekiq, musisz użyć interfejsów API specyficznych dla Sidekiq. ActiveJob nie ujawnia mechanizmu ponownej próby Sidekiq.

+0

Dziękuję. Co to jest "specyficzny dla Sidekiq"? Czy możesz mi powiedzieć, jak go używać w klasie ActiveJob? – scho

+1

Metoda 'sidekiq_options' dla jednego! –

+0

Dziękuję bardzo. – scho

0

jeśli wystarczy użyć sidekiq, zmiana nerver backend, małpa poprawka może pomóc

module ActiveJob 
    module QueueAdapters 
    class SidekiqAdapter 
     def enqueue(job) 
     JobWrapper.sidekiq_options job.sidekiq_options_hash if job.sidekiq_options_hash 
     JobWrapper.sidekiq_retry_in job.sidekiq_retry_in_block if job.sidekiq_retry_in_block 
     Sidekiq::Client.push(
      'class' => JobWrapper, 
      'wrapped' => job.class.to_s, 
      'queue' => job.queue_name, 
      'args' => [ job.serialize ] 
     ) 
     end 

     def enqueue_at(job, timestamp) 
     JobWrapper.sidekiq_options job.sidekiq_options_hash if job.sidekiq_options_hash 
     JobWrapper.sidekiq_retry_in job.sidekiq_retry_in_block if job.sidekiq_retry_in_block 
     Sidekiq::Client.push(
      'class' => JobWrapper, 
      'wrapped' => job.class.to_s, 
      'queue' => job.queue_name, 
      'args' => [ job.serialize ], 
      'at' => timestamp 
     ) 
     end 
    end 
    end 

    class Base 
    class_attribute :sidekiq_options_hash 
    class_attribute :sidekiq_retry_in_block 

    def self.sidekiq_options(opts={}) 
     self.sidekiq_options_hash = opts 
    end 

    def self.sidekiq_retry_in(&block) 
     self.sidekiq_retry_in_block = block 
    end 
    end 
end 

następnie można napisać jak poniżej:

class BaseJob < ActiveJob::Base 

    sidekiq_options retry: 2, queue: :low 
    sidekiq_retry_in { |count, _| 3 * count } 

    def perform; end 
end 

szczęśliwy kodowania

12

też może być zainteresowanym tym rozwiązaniem, które używa api serialize i deserialize do przechowywania liczby prób.

class DeliverWebhookJob < ActiveJob::Base 
    def serialize 
    super.merge('attempt_number' => (@attempt_number || 0) + 1) 
    end 

    def deserialize(job_data) 
    super 
    @attempt_number = job_data['attempt_number'] 
    end 

    rescue_from(ErrorLoadingSite) do |exception| 
    retry_job(wait: 10) if @attempt_number < 5 
    end 

    def perform(*args) 
    # raise ErrorLoadingSite if cannot scrape 
    end 
end 

Weź od here.

1

Jest sidekiq-retry klejnot, który spełnia swoje zadanie

class SiteScrapperJob < ActiveJob::Base 
    include ActiveJob::Retry.new(limit: 5, strategy: :exponential) 

    def perform(*args) 
    # raise ErrorLoadingSite if cannot scrape 
    end 
end 

Inną opcją jest użycie sidekiq middleware:

pierwsze zdefiniować job_options klasy metodę, która będzie dostępna w podklasach:

class ApplicationJob < ActiveJob::Base 
    def self.job_options(options) 
    @job_options = options 
    end 

    def self.get_job_options 
    @job_options || {} 
    end 
end 

Dodaj oprogramowanie pośrednie, które czyta jo b_options z klasy zadania i zapisuje je do pozycji pracy dla sidekiq:

module Sidekiq 
class JobOptionsMiddleware 

    def call(job_wrapper, item, queue, redis_pool) 
    job = item['args'][0]['job_class'].constantize 

    job.get_job_options 
     .each{ |option, value| item[option] = value if item[option].nil? } 

    yield 
    end 

end 

# in sidekiq initializer 

Sidekiq.configure_client do |config| 
    config.client_middleware do |chain| 
    chain.add Sidekiq::JobOptionsMiddleware 
    end 
end 

I wreszcie

class SiteScrapperJob < ApplicationJob 
    job_options retry: 5 

    def perform 
    # your code 
    end 
end 
1

Ponieważ Rails 5.1, nie ma wbudowanego sposób to zrobić przy użyciu metody retry_on. Jest to ogólna metoda ActiveJob, więc będzie działać z każdym backendem kolejkowania, a nie tylko z Sidekiq.

Na przykład dla konkretnego zadania można zrobić:

class SiteScraperJob < ActiveJob::Base 
    retry_on ErrorLoadingSite, queue: :low_priority, attempts: 5 

    def perform(*args) 
    # raise ErrorLoadingSite if cannot scrape 
    end 
end 

Można również ustawić stały interwał oczekiwania lub wykładniczy strategię oczekiwania, jak wyjaśniono w docs.

Powiązane problemy