Rails | 12月 3rd, 2008
複数プロセスを立ち上げていても、script/runner 等で叩くときも並行して同じ処理を走らせないようにするとき、ファイルのロックを使うのが簡単です。
ソース
#{RAILS_ROOT}/lib/batch_lock.rb という名前で下記を保存する。
# 同一処理を並行で走らせない様にするモジュール class BatchLockException < Exception; end module BatchLock # 処理を排他ロックして走らせる def self.run(batch_name) FileUtils.mkdir(RAILS_ROOT + '/tmp/batch_lock') unless File.exists?(RAILS_ROOT + '/tmp/batch_lock') # batch_name をスコープとして排他処理される。 File.open("#{RAILS_ROOT}/tmp/batch_lock/#{batch_name}", 'w') do |f| if f.flock(File::LOCK_EX | File::LOCK_NB) yield else raise BatchLockException.new end end end # 処理が走っているか確認する def self.running?(batch_name) FileUtils.mkdir(RAILS_ROOT + '/tmp/batch_lock') unless File.exists?(RAILS_ROOT + '/tmp/batch_lock') # ロック用のファイル名は、バッチごとにユニークにする。 File.open("#{RAILS_ROOT}/tmp/batch_lock/#{batch_name}", 'w') do |f| ! f.flock(File::LOCK_EX | File::LOCK_NB) end end end
使い方
同時に走らせたくない処理をブロックで実行する。
begin BatchLock.run(:go_to_park) do # ユーザがみんな公園に行く User.find(all).each(&:go_to_park) end rescue BatchLockException logger.error "既にバッチが走っていた…。" end
今バッチが走ってるか確認する。
p BatchLock.running?(:go_to_park) ? 'バッチ進行中' : 'バッチは走ってない'




