Class: Woods::Coordination::PipelineLock
- Inherits:
-
Object
- Object
- Woods::Coordination::PipelineLock
- Defined in:
- lib/woods/coordination/pipeline_lock.rb
Overview
File-based lock for preventing concurrent pipeline operations.
Creates a lock file with PID and timestamp. Supports stale lock detection for crashed processes.
Constant Summary collapse
- DEFAULT_STALE_TIMEOUT =
1 hour
3600
Instance Method Summary collapse
-
#acquire ⇒ Boolean
Attempt to acquire the lock.
-
#initialize(lock_dir:, name:, stale_timeout: DEFAULT_STALE_TIMEOUT) ⇒ PipelineLock
constructor
A new instance of PipelineLock.
-
#locked? ⇒ Boolean
Whether the lock is currently held by this instance.
-
#release ⇒ void
Release the lock.
-
#with_lock { ... } ⇒ Object
Execute a block while holding the lock.
Constructor Details
#initialize(lock_dir:, name:, stale_timeout: DEFAULT_STALE_TIMEOUT) ⇒ PipelineLock
Returns a new instance of PipelineLock.
27 28 29 30 31 32 33 |
# File 'lib/woods/coordination/pipeline_lock.rb', line 27 def initialize(lock_dir:, name:, stale_timeout: DEFAULT_STALE_TIMEOUT) @lock_dir = lock_dir @name = name @stale_timeout = stale_timeout @lock_path = File.join(lock_dir, "#{name}.lock") @held = false end |
Instance Method Details
#acquire ⇒ Boolean
Attempt to acquire the lock.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/woods/coordination/pipeline_lock.rb', line 38 def acquire FileUtils.mkdir_p(@lock_dir) # Check for stale lock first (separate from atomic creation) if File.exist?(@lock_path) return false unless stale? # Remove stale lock FileUtils.rm_f(@lock_path) end # Atomic lock creation: File::EXCL ensures this fails if file already exists File.open(@lock_path, File::WRONLY | File::CREAT | File::EXCL) do |f| f.write(lock_content) end @held = true true rescue Errno::EEXIST false end |
#locked? ⇒ Boolean
Whether the lock is currently held by this instance.
85 86 87 |
# File 'lib/woods/coordination/pipeline_lock.rb', line 85 def locked? @held && File.exist?(@lock_path) end |
#release ⇒ void
This method returns an undefined value.
Release the lock.
62 63 64 65 |
# File 'lib/woods/coordination/pipeline_lock.rb', line 62 def release FileUtils.rm_f(@lock_path) if @held @held = false end |
#with_lock { ... } ⇒ Object
Execute a block while holding the lock.
72 73 74 75 76 77 78 79 80 |
# File 'lib/woods/coordination/pipeline_lock.rb', line 72 def with_lock(&block) raise LockError, "Cannot acquire lock '#{@name}' — another process is running" unless acquire begin block.call ensure release end end |