掲題を実現する場合のサンプル。
処理で更新されるテーブルのモデルに、以下のようなメソッドを実装。
class BatchExecUpdateDate < ApplicationRecord
enum proc_type : { daily: 0, monthly: 1}
class << self
def transaction_with_lock(proc_type, &block)
target_rec = find_or_create_by(proc_type: proc_type)
ActiveRecord::Base transacrion do
lock_rec = BatchExecUpdateDate.lock('FOR UPDATE NOWAIT').find(target_rec.id)
block.call
lock_rec.update(updated_at: Time.zone.now)
end
true
rescue ActiveRecord::StatementInvalid => e
return false if e.cause&.kind_of?(PG::LockNotAvailable)
raise e
end
end
end
modelでupdate_atを必須valideteかけている場合は、
明示的にupdated_atをセットしないとエラーになる
validate指定を外すと、自動でセットしてcreateしてくれる
validates :updated_at, presence: true
target_rec = find_or_create_by(proc_type: proc_type) {|beud| beud.updated_at = Time.zone.now}
以下のような処理があったとして
class AaaBatch
class << self
def update_process
end
end
end
以下のように呼び出すことで、実現できる。
BatchExecUpdateDate.transaction_with_lock(proc_type) do
AaaBatch.update_process(0)
BbbBatch.update_process(0)
:
end