2012-08-13 13 views
9

Tengo una función que está marcado para ser manejado de forma asíncrona por delayed_job:El paso de un bloque a 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 

Cuando ejecuto esta función que pase en un bloque:

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 

Estos trabajos bien cuando corro sin delayed_job pero cuando correr con ella me sale el siguiente error

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 ... 

no parece para recoger el bloque que se pasó. ¿No es esta la forma correcta de hacerlo o debería encontrar un método diferente?

Respuesta

1

He encontrado un método de hacer esto. Es un poco hacky pero funciona bien. He encontrado this article que habla de la creación de una clase SerializableProc. Si paso esto a la función, todo funciona bien.

+2

¿podría publicar lo que el código que utilizó? – brauliobo

8

delayyed_job funciona guardando sus trabajos en un almacén de datos (generalmente su base de datos principal) y luego cargando los trabajos fuera de este almacén de datos en un proceso en segundo plano, donde se maneja/ejecuta.

Para guardar un trabajo en la base de datos, delayed_job necesita salvar de alguna manera lo que el método de llamada en la que se opone con qué argumentos. Esto se hace serializando todo en una cadena (el trabajo demorado usa yaml para eso). Desafortunadamente, los bloques no se pueden serializar. Por lo tanto, el trabajador de segundo plano no conoce el argumento del bloque y llama al método sin él. Esto da como resultado el LocalJumpError cuando el método intenta ceder al bloque.

0

mayoría de la gente tratar esto como un problema de la abstracción.

El código proc es, probablemente, no cambiando de gestión a plazo (excepto VARs) y lo que debe hacer que el código de bloque en un método de clase o instancia. Pase el nombre de ese método, y luego lo haga en su método execute, como

@some_data = CapJobs.send(target_method)

-o tal vez mejor, incluso

@some_data = DomainSpecificModel.send(target_method)

Cuestiones relacionadas