Ich versuche, einige Rennen Fällen mit meinem Hintergrund Task Manager zu kämpfen. Im Wesentlichen habe ich ein Thing
Objekt (bereits existiert) und ordnen Sie ihm einige Eigenschaften zu und dann speichern Sie es. Nachdem es mit den neuen Eigenschaften gespeichert wurde, stelle ich es in Resque ein und übergebe die ID.Run Rails Code nach einem Update auf die Datenbank hat sich verpflichtet, ohne after_commit
thing = Thing.find(1)
puts thing.foo # outputs "old value"
thing.foo = "new value"
thing.save
ThingProcessor.queue_job(thing.id)
Der Hintergrundjob lädt das Objekt mit Thing.find(thing_id)
aus der Datenbank.
Das Problem ist, dass wir gefunden haben Resque ist so schnell beim Abholen des Jobs und Laden der Thing
Objekt von der ID, dass es ein veraltetes Objekt lädt. Innerhalb des Jobs ruft der Aufruf thing.foo
immer noch den "alten Wert" wie 1/100 (nicht echte Daten, aber es passiert nicht oft).
Wir wissen, dass dies ein Rennfall ist, weil Schienen von thing.save
zurückkommen werden, bevor die Daten tatsächlich in die Datenbank (Postgresql in diesem Fall) festgeschrieben wurden.
Gibt es einen Weg in Rails, Code nur auszuführen, nachdem eine Datenbankaktion festgeschrieben wurde? Im Wesentlichen möchte ich sicherstellen, dass zu dem Zeitpunkt, zu dem Resque das Objekt lädt, es das frischeste Objekt erhält. Ich weiß, dass dies mit einem after_commit
Haken auf dem Thing
Modell erreicht werden kann, aber ich will es nicht dort. Ich brauche das nur in diesem einen spezifischen Kontext, nicht jedes Mal, wenn das Modell Commit in die DB geändert hat.
So blockiert die Ausführung einer Transaktion die Ausführung von 'ThingProcessor.queue_job (thing.id)', bis alle Abfragen im Transaktionsblock Commit haben? Ich dachte, dass Transaktionsblöcke nur sicherstellen, dass bei einem Datenbankfehler innerhalb des Blocks alles zurückgenommen wird. Eine Datenbankfunktion. Nicht ein Ruby-Feature – Brian
Ich glaube es ist. Probieren Sie es aus und lassen Sie mich wissen, ob es funktioniert. –
Keine Rails-Dokumentation gefunden, die besagt, dass ein Transaktionsblock die Ausführung blockiert. Wer weiß es definitiv? – Ben