2010-12-29 20 views
16

Ich habe eine frische Schienen 3 App Entleerung, hier ist mein Gemfile:Delayed_job nicht die Methode ausführen Ausführung aber der Job-Warteschlange

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

Hier ist die Klasse ist, die die Arbeit darstellt, die ich in die Warteschlange wollen:

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 

der Konsole ohne Arbeiter ausgeführt wird:

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

Wie ich schon erwähnt: es gibt keine Arbeiter Laufen:

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">] 

beginne ich einen Arbeiter mit script/delayed_job run

Die Warteschlange geleert wird:

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

jedoch nichts als ein Ergebnis des puts geschieht, nichts von den logger Anrufe protokolliert wird, und keine Ausnahme wird ausgelöst. Ich würde jede Hilfe/Einsicht oder irgendetwas zu versuchen schätzen.

+0

Ich habe genau das gleiche Problem. Hast du das jemals gelöst? – Leddo

Antwort

0

ich Ihre Klasse in irb nur kopiert und versucht Me.new.perform zu tun:

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

Hat Ihre Klasse Zugriff auf ‚Logger‘ haben?

Sie könnten versuchen, etwas anderes zu tun, wie das Öffnen und Schreiben in eine Datei?

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

Beachten Sie, dass der Befehl des Arbeitnehmers Job verzögert ‚puts‘ ausgegeben zu seine stdout so werden Sie wahrscheinlich nie sehen. Und wenn Sie Logging durchführen möchten, müssen Sie eine neue Logger-Instanz innerhalb Ihrer Perform-Methode erstellen, um dies zu tun.

+0

Ich habe versucht, die Logger-Aufrufe zu entfernen und die Datei wie beschrieben zu schreiben. Ich sehe immer noch das gleiche Verhalten - der Job wird aus der Warteschlange entfernt, aber die Datei wird nicht geschrieben. – James

0

Überprüfen Sie die Protokolle, sollten Sie etwas über DelayedJob Nachrichten, zumindest sehen die Job gestartet wird und was seine Exit-Status

in einem Terminal, Start:

tail -f log/development.log 

dann versuchen Sie es erneut von einem Schienen-Konsole Überprüfen Sie, was passiert, wenn Sie eine einfache ActiveRecord-Abfrage ausführen und dann DelayedJob verwenden. Sie können lesen, was auf den anderen Terminal

prost, A.

12

standardmäßig angemeldet ist, zerstört delayed_job fehlgeschlagene Jobs:

Der erste Schritt ist eine Initialisierung zu konfigurieren und dieses Verhalten

deaktivieren

Wenn Sie einen Fehler bei der Deserialisierung erhalten, ist dies ein sofortiger Jobfehler.

Dies löst Joblöschung aus (wenn Sie es nicht gelöscht haben).

versuchen also das Hinzufügen der folgenden Zeile um 120 des worker.rb

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

Es ist ziemlich wenig hilfreich, aber zumindest wissen Sie, es ist ein Deserialisierung Fehler ist dann.

Ich landete nur mit dem Job w. perform() - Methodenkonstrukt. Viel zuverlässiger. Denken Sie auch daran, Ihre Jobdefinition als separate Datei zu speichern, damit der Klassenlader sie bei der Ausführung finden kann (anstatt die Klassendefinition irgendwo in Ihr Modell zu integrieren).

6

Ben W ist absolut richtig, Vergewissern Sie sich, eine Datei unter

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

Dieser legt fest, wie der Arbeiter verhalten soll. Der Arbeiter wird in Ruhe nur Fehler entfernen.

Sobald Sie dies tun, sollten Sie in der Lage sein, mehr über Ihren Fehler zu erfahren. In meinem Beispiel verwendete ich delayed_job_mongoid, also fügte ich einen Eintrag von "last_error" hinzu (was ich denke, dass du in deiner mysql Tabelle für delayed_job haben solltest ...)

Und wie Ben W abschließend sagte, musst du sicherstellen Das Objekt, das Sie erstellen, ist der Anwendung (oder dem betreffenden Mitarbeiter) bekannt. Mein Problem war, dass ich in der Rails-Konsole ein Klassenobjekt getestet habe. Der Arbeiter kannte diese Klasse nicht, also wurde er barfüssig.

In meiner application.rb Datei:

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

und meine Lib-Datei:

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

Dann

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

war in meinem log/development.log Datei bestätigt, dass das war erfolgreich. Ich habe auch das Erstellen und Objekt (ein Benutzerobjekt oder welches Modell Sie auch haben mögen) in dieser Perform-Methode getestet, und es hat funktioniert.

2

Ich hatte dieses Problem, und ich fand, dass es in Rails 3 Dateien im Verzeichnis lib/ nicht automatisch geladen wurde. Zur Diagnose, fügte ich hinzu:

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

wie von Ben W. Dieser erwähnt hat mir gesagt, was los war, als ich die last_error inspizieren konnte.

So das automatische Laden von Problem zu lösen, fand ich ein paar Antworten auf SO, aber das Wesentliche ist das Hinzufügen dieser:

# 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/**/"] 

Welche freundlicherweise von http://hemju.com/2010/09/22/rails-3-quicktip-autoload-lib-directory-including-all-subdirectories/ zur Verfügung gestellt wurde.

Es würde mich interessieren zu sehen, wie Sie das lösen könnten, ohne automatisches Laden für das lib-Verzeichnis einzuschalten. Irgendwelche Gedanken?

Verwandte Themen