5

Haben Sie eine Idee, wie Sie die Delayed::Job ID aus dem ActiveJob in Warteschlange bekommen? Wenn ich einen Job in die Warteschlange einreibe, erhalte ich eine Instanz von ActiveJob::Base mit einer @job_id, aber diese Job-ID scheint für ActiveJob intern zu sein. Meine beste Vermutung ist bisher nur die zuletzt erstellten Jobs zu durchlaufen:Rails 4.2 erhalten Job ID verzögert von aktiven Job

aber das scheint alle Arten von Hacky. Art von überrascht ActiveJob gibt die ID von Delayed::Job nicht zurück, insbesondere da das explizit zurückgegeben wird, wenn der Auftrag in die Warteschlange eingereiht wird.

== EDIT

Sieht aus wie ich nicht der einzige bin (https://github.com/rails/rails/issues/18821)

+0

Ah, aber dann, dass einige vielleicht argumentieren zu müssen Holen Sie sich die Job-ID ist "alle Arten von Hacky" auch! Aus Neugier, und weil es die Tür zu einem alternativen Ansatz öffnen könnte, warum brauchen Sie die Job-ID? – Shadwell

+2

Sie können Berichte abbrechen, bevor sie ausgeführt werden, während sie sich in der Warteschlange befinden. – kddeisz

Antwort

6

Falls jemand dies in der Zukunft findet: Rails akzeptiert nur einen Patch Sie diese ID von provider_job_id in Rails 5. Sie es mit einem Patch wie

ActiveJob::QueueAdapters::DelayedJobAdapter.singleton_class.prepend(Module.new do 
    def enqueue(job) 
    provider_job = super 
    job.provider_job_id = provider_job.id 
    provider_job 
    end 

    def enqueue_at(job, timestamp) 
    provider_job = super 
    job.provider_job_id = provider_job.id 
    provider_job 
    end 
end) 
+0

Danke für die Antwort! Wo würde man diesen Code allerdings hinstellen? – Alexander

+0

@Alexander Normalerweise würde dies in einen Initialisierer gehen. Etwas wie config/initializers/delayed_job.rb – kddeisz

+0

Bevor dieser Patch kam, stieß ich auf dieses Problem, und machte ein Juwel, Job-Status über ActiveJob abzufragen: https://github.com/cdale77/active_job_status –

0

Statt den Auftrag aus der Warteschlange zu entfernen, wenn sie aufgehoben wird Sie selbst eine Stornierung des Auftrags modellieren können.

Dann, wenn Sie zum Ausführen der GenerateReportJob kommen, können Sie zuerst für eine Stornierung des Berichts überprüfen. Wenn es einen gibt, können Sie den Stornierungsdatensatz löschen und die Berichterstellung abbrechen. Wenn es keine Stornierung gibt, können Sie wie gewohnt weitermachen.

+0

Ja, könnte ich. Aber ... der Sinn von Delayed :: Job ist, dass es ein Nachkomme von ActiveRecord :: Base ist. Es hat eine ID auf dem Tisch - so scheint es albern, eine andere Spalte/Modell/Objekt/Konzept der Stornierung zu erstellen, wenn ich vor der Integration mit aktiven Job konnte ich nur die ID bekommen. – kddeisz

+0

Wie auch immer, der Punkt, an dem diese Frage gestellt wurde, war nur zu sehen, ob jemand wusste, wie man die ID bekommt. Hier jedoch zu schauen: (https://github.com/rails/rails/blob/master/activejob/lib/active_job/enqueuing.rb#L74) scheint anzuzeigen, dass dieser Job entweder im Gegensatz zu den verzögerten zurückgegeben wird Job. Und so werde ich hacken. – kddeisz

+0

Ja, tut mir leid, ich weiß es zu schätzen, dass ich eine etwas andere Frage beantwortet habe. – Shadwell

2

Ich habe an die Arbeit kann zu bekommen, damit es funktioniert in Rails 4.2 den neuen Patch von Rails 5 wie folgt aus:

erstellen sie die Datei lib/active_job/queue_adapters/delayed_job_adapter.rb

module ActiveJob 
    module QueueAdapters 
    class DelayedJobAdapter 
     class << self 
     def enqueue(job) #:nodoc: 
      delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name) 
      job.provider_job_id = delayed_job.id 
      delayed_job 
     end 

     def enqueue_at(job, timestamp) #:nodoc: 
      delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp)) 
      job.provider_job_id = delayed_job.id 
      delayed_job 
     end 
     end 

     class JobWrapper #:nodoc: 
     attr_accessor :job_data 

     def initialize(job_data) 
      @job_data = job_data 
     end 

     def perform 
      Base.execute(job_data) 
     end 
     end 
    end 
    end 
end 
3

Inspiriert durch die Antwort von Beguene und einige Rückwärts Engineering des ActiveJob Code Rails 5, ich habe es mit Rails 4.2 von

Zugabe

1) aus arbeitet folgenden Code in lib/active_job/queue_adapters/delayed_job_adapter.rb oder config/initializers/delayed_job.rb (beiden Standorte gearbeitet haben):

# file: lib/active_job/queue_adapters/delayed_job_adapter.rb 
module ActiveJob 
    module Core 
    # ID optionally provided by adapter 
    attr_accessor :provider_job_id 
    end 

    module QueueAdapters 
    class DelayedJobAdapter 
     class << self 
     def enqueue(job) #:nodoc: 
      delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name) 
      job.provider_job_id = delayed_job.id 
      delayed_job 
     end 

     def enqueue_at(job, timestamp) #:nodoc: 
      delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp)) 
      job.provider_job_id = delayed_job.id 
      delayed_job 
     end 
     end 
     class JobWrapper #:nodoc: 
     attr_accessor :job_data 

     def initialize(job_data) 
      @job_data = job_data 
     end 

     def perform 
      Base.execute(job_data) 
     end 
     end 
    end 
    end 
end 

Die attr_accessor :provider_job_id Anweisung in erforderlich Schienen 4.2, da es in der Enqueue-Methode verwendet wird und noch nicht in 4.2 definiert ist.

Dann können wir davon Gebrauch machen möchten folgt:

2) definieren unsere eigene ActiveJob Klasse:

# file: app/jobs/my_job.rb 
class MyJob < ActiveJob::Base 
    queue_as :default 

    def perform(object, performmethod = method(:method)) 
    # Do something later 
     returnvalue = object.send(performmethod) 
     returnvalue 
    end 

    end 
end 

3) Jetzt können wir einen neuen Job irgendwo im Code erstellen:

job = MyJob.perform_later(Myobject, "mymethod") 

Dadurch wird die Methode Myobject.mymethod in die Warteschlange gestellt.

4) Der Code in 1) hilft uns, die Verzögerte Job zu finden, die mit unserer Arbeit verbunden ist: schließlich

delayed_job = Delayed::Job.find(job.provider_job_id) 

5), was wir tun können, was wir mit dem delayed_job tun müssen, z.B.löschen:

delayed_job.delete 

Hinweis: in Rails 5, Schritt 1) ​​wird nicht mehr benötigt werden, da die exakt gleiche Code ist integraler Bestandteil der Schienen 5.

+0

Dies funktioniert alles in der akzeptierten Antwort bereits. – kddeisz

+0

@kddeisz: Ich habe nur die Antwort von Beguene getestet (weil es näher am Code von Rails 5 ist und Ihre Antwort zu schlau für mich war, aber es sieht gut aus!). In Beguenes Antwort fehlte nur eine winzige Zutat: die Anweisung '' 'attr_accessor: provider_job_id'''. Die bessere Option wäre gewesen, einen Kommentar zu Beguenes Antwort hinzuzufügen, aber da ich neu im stackoverflow bin und keine Reputation habe, hatte ich keine Erlaubnis Kommentare hinzuzufügen. Daher dachte ich mir, dass es sinnvoll ist, die Frage mit allen Zutaten zu beantworten, die ich brauche, um es zum Laufen zu bringen. – Olli

+0

Das ist nett, wenn Sie die Provider-ID (verzögerte Job-ID) in den 'Enqueue'-Callbacks erhalten möchten, aber es gibt Ihnen nicht die ID zum Zeitpunkt der Durchführung (in den' Ausführen'-Callbacks) – phil