2012-08-13 11 views
9

Ho una funzione che è contrassegnato essere gestita in modo asincrono da delayed_job:Passando un blocco ad un delayed_job

class CapJobs 
    def execute(params, id) 
    begin 
     unless Rails.env == "test" 
     Capistrano::CLI.parse(params).execute! 
     end 
    rescue 
     site = Site.find(id) 
     site.records.create!(:date => DateTime.now, :action => "Task Failure: #{params[0]}", :type => :failure)  
     site.save 
    ensure 
     yield id 
    end 
    end 
    handle_asynchronously :execute 
end 

Quando eseguo questa funzione passo in un blocco:

capjobs = CapJobs.new 
capjobs.execute(parameters, @site.id) do |id| 
    asite = Site.find(id) 
    asite.records.create!(:date => DateTime.now, :action => "Created", :type => :init) 
    asite.status = "On Demo" 
    asite.dev = true 
    asite.save 
end 

questo funziona bene quando corro senza delayed_job ma quando correre con esso ottengo il seguente errore

2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] SitesHelper::CapJobs#execute_without_delay failed with LocalJumpError: no block given (yield) - 0 failed attempts 
2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] PERMANENTLY removing SitesHelper::CapJobs#execute_without_delay because of 1 consecutive failures. 
2012-08-13T09:24:36-0300: [Worker(delayed_job host:eagle pid:12089)] 1 jobs processed at 0.0572 j/s, 1 failed ... 

non sembra raccogliere il blocco che è stato passato. Non è questo il modo corretto di farlo o dovrei trovare un metodo diverso?

risposta

1

Ho trovato un metodo per farlo. È un po 'hacky ma funziona bene. Ho trovato this article che parla della creazione di una classe SerializableProc. Se passo questo alla funzione, allora tutto funziona alla grande.

+2

la prego di inviare ciò che il codice è stato utilizzato? – brauliobo

8

delayed_job funziona salvando i lavori in un archivio dati (spesso il database principale) e quindi caricando i lavori da questo archivio dati in un processo in background, dove viene gestito/eseguito.

Per salvare un lavoro nel database, delayed_job deve in qualche modo salvare quale metodo chiamare su quale oggetto con quali argomenti. Questo viene fatto serializzando tutto in una stringa (delayed_job usa yaml per quello). Sfortunatamente, i blocchi non possono essere serializzati. Quindi il lavoratore in background non conosce l'argomento del blocco e chiama il metodo senza di esso. Ciò risulta nello LocalJumpError quando il metodo sta tentando di arrendersi al blocco.

0

La maggior parte delle persone considererebbe questo come un problema di astrazione.

Il codice proc non sta probabilmente cambiando da run-to-run (ad eccezione di vars) e quindi è necessario creare il codice di blocco in un metodo di classe o istanza. Passare il nome di tale metodo, e quindi chiamare nel vostro metodo di execute, come

@some_data = CapJobs.send(target_method)

o forse-better, anche

@some_data = DomainSpecificModel.send(target_method)

Problemi correlati