2010-12-29 8 views
16

ho un fresco rotaie 3 app, ecco la mia Gemfile:Delayed_job non l'esecuzione del metodo eseguire, ma lo svuotamento della coda processi

source 'http://rubygems.org' 
gem 'rails', '3.0.0' gem 'delayed_job' 
gem 'sqlite3-ruby', :require => 'sqlite3' 

Ecco la classe che rappresenta il lavoro che voglio fare la fila:

class Me < Struct.new(:something) 
    def perform 
    puts "Hello from me" 
    logger.info "Hello from me" 
    logger.debug "Hello from me" 
    raise Exception.new 
    end 
end 

Dalla console senza lavoratori in esecuzione:

irb(main):002:0> Delayed::Job.enqueue Me.new(1) 
=> #<Delayed::Backend::ActiveRecord::Job id: 7, priority: 0, attempts: 0, handler: "--- !ruby/struct:Me \nsomething: 1\n", last_error: nil, run_at: "2010-12-29 07:24:11", locked_at: nil, failed_at: nil, locked_by: nil, created_at: "2010-12-29 07:24:11", updated_at: "2010-12-29 07:24:11"> 

Come ho già detto: non ci sono i lavoratori running:

irb(main):003:0> Delayed::Job.all 
=> [#<Delayed::Backend::ActiveRecord::Job id: 7, priority: 0, attempts: 0, handler: "--- !ruby/struct:Me \nsomething: 1\n", last_error: nil, run_at: "2010-12-29 07:24:11", locked_at: nil, failed_at: nil, locked_by: nil, created_at: "2010-12-29 07:24:11", updated_at: "2010-12-29 07:24:11">] 

mi metto un lavoratore con script/delayed_job run

La coda viene svuotata:

irb(main):006:0> Delayed::Job.all 
=> [] 

Tuttavia, nulla accade a seguito della puts, nulla viene registrato dalle logger chiamate, e non viene sollevata alcuna eccezione. Apprezzerei qualsiasi aiuto/intuizione o qualsiasi altra cosa da provare.

+0

Ho esattamente lo stesso problema. L'hai mai risolto? – Leddo

risposta

0

Ho appena copiato la classe in IRB e ha cercato di fare Me.new.perform:

Hello from me 
NameError: undefined local variable or method `logger' for #<struct Me something=nil> 
from (irb):6:in `perform' 
from (irb):14 

La vostra classe ha accesso a 'logger'?

Si potrebbe provare a fare qualcos'altro, come aprire e scrivere su un file?

File.open("testing.txt", 'w') {|f| f.write("hello") } 

Tenete a mente che il comando 'puts' del lavoratore di lavoro in ritardo sarà di output per la sua stdout quindi sarà probabilmente mai vedere questo. E se vuoi fare qualsiasi registrazione, penso che devi creare una nuova istanza di Logger all'interno del tuo metodo di esecuzione per farlo.

+0

Ho provato a rimuovere le chiamate del registratore e scrivere il file come descritto. Sto ancora vedendo lo stesso comportamento: il lavoro viene rimosso dalla coda ma il file non viene scritto. – James

0

controllare i log, si dovrebbe vedere qualcosa sui messaggi DelayedJob, almeno che lavoro viene avviato e che cosa è il suo stato di uscita

in un terminale, di lancio:

tail -f log/development.log 

poi riprovare da una console rotaie per controllare cosa succede facendo una semplice query ActiveRecord, quindi usando DelayedJob. è possibile leggere ciò che è connesso l'altro terminale

applausi, A.

12

Per impostazione predefinita, delayed_job distrugge posti di lavoro non riusciti:

Quindi il primo passo è quello di configurare un inizializzatore e disattivare tale comportamento

Delayed::Worker.destroy_failed_jobs = false 

Inoltre, se si verifica un errore di deserializzazione, si tratta di un errore di processo istantaneo.

Questo innesca la cancellazione del lavoro (se non lo si è cancellato).

in modo da provare l'aggiunta di questo attorno alla riga 120 del worker.rb

rescue DeserializationError => error 
    say "DeserializationError: #{error.message}" 
    job.last_error = "{#{error.message}\n#{error.backtrace.join('\n')}" 
    failed(job) 

E 'abbastanza inutile, ma almeno saprete che è un errore di deserializzazione poi.

Ho finito per usare solo il lavoro w. Costruisci il costrutto del metodo. Molto più affidabile. Ricorda inoltre di inserire la definizione del lavoro come un file separato in modo che il programma di caricamento classi possa trovarlo quando è in esecuzione (piuttosto che solo la definizione della classe nel modello da qualche parte).

6

Ben W è assolutamente giusto, Assicurarsi di avere un file sotto

"#{Rails.root}/config/initializers/delayed_job_worker.rb" 

Questo definisce come il lavoratore deve comportarsi. Il lavoratore sta per tranquillamente rimuovere gli errori in caso contrario.

Una volta fatto questo, dovresti essere in grado di scoprire di più sul tuo errore. Per il mio esempio, stavo usando delayed_job_mongoid, quindi ho aggiunto una voce di "last_error" (che penso dovresti avere nella tua tabella mysql per delayed_job a prescindere ..)

E come Ben W ha concluso, è necessario assicurarsi l'oggetto che stai creando è noto all'applicazione (o al lavoratore per quella materia). Il mio problema era che ero in Rails Console per testare un oggetto di classe. Il lavoratore non sapeva di questa classe, quindi è stato gonfiato.

Nel mio file application.rb:

module TextSender 
    class Application < Rails::Application 
    require "#{Rails.root.to_s}/lib/SendTextJob.rb" 

e il mio file lib:

class SendTextJob < Struct.new(:text, :number) 
    def perform 
    Rails.logger.info "Sending #{text} to #{number}" 
    puts "Successfully sent text" 
    end 
end 

Poi esecuzione

Delayed::Job.enqueue SendTextJob.new("Work on this text NOW, please?", "5551231234") 

è stato confermato nel mio log file/development.log che questo ha avuto successo Ho anche testato la creazione e l'oggetto (un oggetto utente o qualsiasi modello che possiedi) in questo metodo di esecuzione, e ha funzionato.

2

Ho avuto questo problema e ho scoperto che era perché nei file Rails 3 nella directory lib/ non sono caricati automaticamente. Per diagnosticare, ho aggiunto:

# application.rb 
Delayed::Worker.destroy_failed_jobs = false 

come detto da Ben W. Questo mi ha detto cosa stava succedendo, come ho potuto ispezionare il last_error.

Quindi, per risolvere il problema caricamento automatico, ho trovato un paio di risposte su SO, ma il succo è l'aggiunta di questo:

# application.rb 

# Custom directories with classes and modules you want to be autoloadable. 
# config.autoload_paths += %W(#{config.root}/extras) 
config.autoload_paths += %W(#{config.root}/lib) 
config.autoload_paths += Dir["#{config.root}/lib/**/"] 

Che è stato gentilmente fornito da http://hemju.com/2010/09/22/rails-3-quicktip-autoload-lib-directory-including-all-subdirectories/.

Sarei interessato a vedere come è possibile risolvere questo senza attivare autoloading per la directory lib. qualche idea?