File.flock
を使うのが簡単、という結論に到達した。
require 'timeout'
class AccessDenied < StandardError; end
def lock(&block)
# 10秒以内に終わらない場合はAccessDenied例外が発生
Timeout::timeout(10) do
open(File.join(Dir.tmpdir, 'my-application.lock'), 'w') do |f|
begin
f.flock(File::LOCK_EX)
block.call
ensure
f.flock(File::LOCK_UN)
end
end
end
rescue Exception => ex
raise AccessDenied.new('timeout')
end
lock do
# 排他処理
end