У меня есть несколько работников Resque для одного и того же объекта (пользователя). После успешной обработки он должен уменьшить атрибут call_left
.ActiveJob/Resque грязный читает. Уровень изоляции транзакции
Он отлично работает с perform_now
(следовательно), но дает непредсказуемые результаты с perform_later
(параллельно). В журналах есть коммиты с таким же числом calls_left
.
Я попытался использовать метод reload
и даже установить самый высокий уровень изоляции. Но все еще есть эта проблема.
Как решить?
class DataProcessJob < ActiveJob::Base
queue_as :default
def perform(user_id, profile_id)
User.transaction(isolation: :serializable) do
user = User.find(user_id).reload
user.data_process(profile_id)
user.update(calls_left: user.calls_left-1)
end
end
end
замки не работают. оптимистичный не работает, потому что он предназначен для работы в едином процессе. пессимистический - просто нет. Raw SQL, похоже, работает, спасибо. –
На самом деле, Rails реализует оптимистичную блокировку, добавляя поле 'lock_version' к вашей таблице (немного отличающееся от оптимистической блокировки уровня БД). Таким образом, он будет работать в сценариях без единого процесса, если они будут реализовывать проверку версии блокировки в запросе обновления SQL. Но, я не уверен, не заглянул в исходный код. Вы пытались использовать оптимистичную блокировку? Если вы это сделали, и это не сработало, сообщите мне. Было бы неплохо принять это к сведению в будущем. – Uzbekjon
Оптимистическая блокировка включена по умолчанию. Он вызывает «спасение ActiveRecord :: StaleObjectError», если объект устарел, что неверно в моем случае. И это из документации: 'Этот механизм блокировки будет функционировать внутри одного рубинового процесса. Чтобы он работал во всех веб-запросах, рекомендуется использовать lock_version как скрытое поле для вашей формы. ' –