Próbuję walczyć z niektórymi sprawami z moim menedżerem zadań w tle. Zasadniczo posiadam obiekt Thing
(już istnieje) i przypisuję mu kilka właściwości, a następnie zapisz go. Po zapisaniu z nowymi właściwościami, umieszczam je w kolejce w Resque, przekazując identyfikator.Uruchomienie kodu rails po zatwierdzeniu aktualizacji bazy danych, bez after_commit
thing = Thing.find(1)
puts thing.foo # outputs "old value"
thing.foo = "new value"
thing.save
ThingProcessor.queue_job(thing.id)
Zadanie w tle spowoduje załadowanie obiektu z bazy danych za pomocą Thing.find(thing_id)
.
Problem polega na tym, że znaleźliśmy Resque tak szybko w pobieraniu pracy i ładowaniu obiektu Thing
z ID, że ładuje nieaktualny obiekt. Tak więc w ramach zadania wywołanie thing.foo
nadal będzie zwracało "starą wartość", np. 1/100 (nie rzeczywiste dane, ale nie zdarza się to często).
Wiemy, że jest to przypadek wyścigowy, ponieważ szyny powracają z thing.save
, zanim dane rzeczywiście zostaną zatwierdzone do bazy danych (w tym przypadku postgresql).
Czy istnieje sposób w Railsach do wykonywania kodu PO operacji bazy danych zatwierdza? Zasadniczo chcę się upewnić, że zanim Resque załaduje obiekt, otrzyma najświeższy obiekt. Wiem, że można to osiągnąć za pomocą haka after_commit
w modelu Thing
, ale nie chcę go tam. Potrzebuję tego tylko w tym konkretnym kontekście, nie za każdym razem, gdy model zatwierdza się do DB.
Więc uruchomienie transakcji zablokuje wykonanie 'ThingProcessor.queue_job (thing.id)' dopóki wszystkie zapytania w bloku transakcji nie zostaną zatwierdzone? Myślałem, że bloki transakcyjne po prostu zapewniły, że jeśli wystąpi awaria w jakichkolwiek operacjach bazy danych w bloku, wszystko zostanie wycofane. Funkcja bazy danych. Not a ruby feature. – Brian
Uważam, że tak. Spróbuj i daj mi znać, jeśli działa. –
Nie można znaleźć żadnej dokumentacji Railsowej, która mówi, że blokowanie wykonywania bloków transakcji. Ktoś wie na pewno? – Ben