Tôi đang cố gắng chống lại một số trường hợp đua với trình quản lý tác vụ nền của tôi. Về cơ bản, tôi có một đối tượng Thing
(đã tồn tại) và gán cho nó một số thuộc tính, sau đó lưu nó. Sau khi nó được lưu với các thuộc tính mới, tôi xếp hàng nó trong Resque, chuyển vào ID.Chạy mã đường ray sau khi cập nhật cơ sở dữ liệu đã cam kết, không có after_commit
thing = Thing.find(1)
puts thing.foo # outputs "old value"
thing.foo = "new value"
thing.save
ThingProcessor.queue_job(thing.id)
Công việc nền sẽ tải đối tượng từ cơ sở dữ liệu bằng cách sử dụng Thing.find(thing_id)
.
Vấn đề là chúng tôi đã tìm thấy Resque quá nhanh khi chọn công việc và tải đối tượng Thing
từ ID, rằng nó tải một đối tượng cũ. Vì vậy, trong công việc, gọi thing.foo
sẽ vẫn trả lại "giá trị cũ" như 1/100 lần (không phải dữ liệu thực, nhưng nó không xảy ra thường xuyên).
Chúng tôi biết đây là trường hợp cuộc đua, vì đường ray sẽ trở về từ thing.save
trước khi dữ liệu thực sự được cam kết với cơ sở dữ liệu (postgresql trong trường hợp này).
Có cách nào trong Rails chỉ thực thi mã SAU KHI một hành động cơ sở dữ liệu đã cam kết không? Về cơ bản, tôi muốn đảm bảo rằng khi Resque tải đối tượng, nó sẽ nhận được đối tượng mới nhất. Tôi biết điều này có thể đạt được bằng cách sử dụng móc after_commit
trên mẫu Thing
, nhưng tôi không muốn ở đó. Tôi chỉ cần điều này xảy ra trong bối cảnh cụ thể này, không phải mỗi lần mô hình có cam kết thay đổi thành DB.
Vì vậy, chạy một giao dịch sẽ chặn thực thi 'ThingProcessor.queue_job (thing.id)' cho đến khi tất cả các truy vấn trong khối giao dịch đã cam kết? Tôi nghĩ rằng các khối giao dịch chỉ đảm bảo rằng nếu có sự thất bại trong bất kỳ hành động cơ sở dữ liệu nào trong khối, mọi thứ đều được sao lưu. Một tính năng cơ sở dữ liệu. Không phải là một tính năng ruby – Brian
Tôi tin rằng nó là. Hãy thử và cho tôi biết nếu công trình. –
Không thể tìm thấy bất kỳ tài liệu Rails nào nói rằng khối giao dịch chặn thực thi. Bất cứ ai biết dứt khoát? – Ben