### Producer-Consumer with Wait and Signal - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Provides an example of using 'wait' and 'signal' for inter-process communication, such as in a dynamic queue system. A consumer process 'waits' for jobs, and a producer process 'signals' by sending new jobs. Requires the 'redis-semaphore' gem. ```ruby # Consumer process job = semaphore.wait # Producer process semaphore.signal(new_job) # Job can be any string, it will be passed unmodified to the consumer process ``` -------------------------------- ### Wait and Signal for Producer-Consumer Source: https://context7.com/dv/redis-semaphore/llms.txt Demonstrates the traditional semaphore wait (P) and signal (V) operations, suitable for producer-consumer patterns. This example uses separate threads for consumers waiting for jobs and producers signaling job availability. ```ruby require 'redis-semaphore' redis = Redis.new(db: 15) job_queue = Redis::Semaphore.new(:job_queue, resources: 0, redis: redis) # Consumer process consumer_thread = Thread.new do loop do job_token = job_queue.wait # Blocks until job available puts "Processing job: #{job_token}" sleep rand(1..3) puts "Job #{job_token} completed" end end # Producer process producer_thread = Thread.new do 5.times do |i| job_data = "job_#{Time.now.to_i}_#{i}" job_queue.signal(job_data) puts "Produced: #{job_data}" sleep 0.5 end end sleep 10 ``` -------------------------------- ### Initialize Redis Semaphore with Local Time Option Source: https://github.com/dv/redis-semaphore/blob/master/README.md Configures the Redis::Semaphore to use the client's local time instead of the Redis server's time for calculating timeouts. This reduces network roundtrips and is beneficial for single-client setups. It requires the `:use_local_time => true` option during initialization. ```ruby s = Redis::Semaphore.new(:local_semaphore, :redis = r, :stale_client_timeout => 5, :use_local_time => true) ``` -------------------------------- ### Initialize Semaphore with Custom Redis Client - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Demonstrates initializing a Redis Semaphore instance by passing a pre-configured Redis client object. This allows for custom Redis connection configurations, such as specifying a different database. Requires the 'redis-semaphore' gem. ```ruby r = Redis.new(:host => "localhost", :db => 222) s = Redis::Semaphore.new(:another_name, :redis => r) #... ``` -------------------------------- ### Initialize Redis Semaphore Instances Source: https://context7.com/dv/redis-semaphore/llms.txt Demonstrates how to create new semaphore instances with unique names and various configuration options. Supports basic mutexes, multi-resource semaphores, using existing Redis connections, and setting stale client timeouts or key expirations. ```ruby require 'redis-semaphore' # Basic mutex (single resource) mutex = Redis::Semaphore.new(:payment_processor, host: 'localhost', port: 6379) # Semaphore with multiple resources worker_pool = Redis::Semaphore.new(:worker_pool, resources: 5, host: 'localhost') # Using existing Redis connection redis = Redis.new(host: 'localhost', db: 2)semaphore = Redis::Semaphore.new(:database_migration, redis: redis) # With stale client timeout (releases locks after 30 seconds) robust_sem = Redis::Semaphore.new(:api_limiter, resources: 10, stale_client_timeout: 30, redis: redis ) # With expiration (keys auto-delete after 300 seconds) temporary_sem = Redis::Semaphore.new(:temp_job, resources: 3, expiration: 300, use_local_time: true, redis: redis ) ``` -------------------------------- ### Dynamic Resource Management with Redis Semaphore Source: https://context7.com/dv/redis-semaphore/llms.txt Demonstrates dynamically adding and consuming resources from a Redis semaphore. It shows how to create a semaphore, add resources, consume them, and return specific tokens. Initial resources are managed by the semaphore. ```ruby require 'redis-semaphore' redis = Redis.new(db: 15) # Dynamic resource managementsemaphore = Redis::Semaphore.new(:dynamic_pool, redis: redis)semaphore.exists_or_create! # Add 3 resources dynamically 3.times { semaphore.signal } puts "Available: #{semaphore.available_count}" # => 4 (1 initial + 3 added) # Consume resources token1 = semaphore.wait(1) token2 = semaphore.wait(1) puts "Available: #{semaphore.available_count}" # => 2 # Return specific tokenssemaphore.signal(token1)semaphore.signal(token2) # Add new unique tokensemaphore.signal puts "Available: #{semaphore.available_count}" # => 5 ``` -------------------------------- ### Create Semaphore with Resource Limit - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Shows how to initialize a Redis Semaphore with a specified number of resources, allowing multiple processes to execute a protected block concurrently up to that limit. Requires the 'redis-semaphore' gem. ```ruby s = Redis::Semaphore.new(:semaphore_name, :resources => 5, :host => "localhost") s.lock do # Up to five processes at a time will be able to get inside this code # block simultaneously. work end ``` -------------------------------- ### Querying Semaphore State with Redis Semaphore Source: https://context7.com/dv/redis-semaphore/llms.txt Shows how to query the state of a Redis semaphore, including its existence, available resource count, and lock status for specific tokens or overall. This is useful for monitoring and debugging purposes. It demonstrates creating, locking, and deleting semaphores. ```ruby require 'redis-semaphore' redis = Redis.new(db: 15) semaphore = Redis::Semaphore.new(:monitoring_test, resources: 5, redis: redis) # Check existence puts "Exists initially: #{semaphore.exists?}" # => false semaphore.exists_or_create! puts "Exists after create: #{semaphore.exists?}" # => true # Check available resources puts "Available: #{semaphore.available_count}" # => 5 # Lock and check status token1 = semaphore.lock(1) puts "Available after lock: #{semaphore.available_count}" # => 4 puts "Locked: #{semaphore.locked?}" # => true puts "Specific token locked: #{semaphore.locked?(token1)}" # => true # Multiple locks token2 = semaphore.lock(1) token3 = semaphore.lock(1) puts "Available: #{semaphore.available_count}" # => 2 puts "Still locked: #{semaphore.locked?}" # => true # Check all tokens all_tokens = semaphore.all_tokens puts "Total tokens: #{all_tokens.count}" # => 5 puts "All tokens: #{all_tokens.inspect}" # Unlock specific token semaphore.signal(token1) puts "Token1 still locked: #{semaphore.locked?(token1)}" # => false puts "Semaphore still locked: #{semaphore.locked?}" # => true (token2, token3) # Clean up semaphore.signal(token2) semaphore.signal(token3) puts "Final available: #{semaphore.available_count}" # => 5 # Delete semaphore completely semaphore.delete! puts "Exists after delete: #{semaphore.exists?}" # => false ``` -------------------------------- ### Create and Use Mutex with Lock Block - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Demonstrates creating a Redis Semaphore instance and using its 'lock' method with a block for mutex-protected code execution. Ensures only one process runs the block at a time. Requires the 'redis-semaphore' gem. ```ruby s = Redis::Semaphore.new(:semaphore_name, :host => "localhost") s.lock do # We're now in a mutex protected area # No matter how many processes are running this program, # there will be only one running this code block at a time. work end ``` -------------------------------- ### Manual Lock and Unlock - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Illustrates manual control of a Redis Semaphore by calling 'lock' and 'unlock' methods separately. This pattern requires careful handling to ensure 'unlock' is always called, especially after potential exceptions. Requires the 'redis-semaphore' gem. ```ruby s = Redis::Semaphore.new(:semaphore_name, :host => "localhost") s.lock work s.unlock # Don't forget this, or the mutex will stay locked! ``` -------------------------------- ### Configuration Options for Redis Semaphore Source: https://context7.com/dv/redis-semaphore/llms.txt Details various configuration options for Redis Semaphore, including direct Redis connection parameters, reusing existing Redis clients, using local time instead of Redis TIME command, auto-expiring semaphores, and namespace support. These options allow customization for different use cases. ```ruby require 'redis-semaphore' # Direct Redis connection parameters sem1 = Redis::Semaphore.new(:direct_config, host: '10.0.1.50', port: 6380, db: 3, password: 'secret123', timeout: 5 ) # Reuse Redis client (recommended for non-blocking operations) redis_client = Redis.new( url: 'redis://user:password@redis-host:6379/1', reconnect_attempts: 3 ) sem2 = Redis::Semaphore.new(:shared_client, redis: redis_client, resources: 10 ) # Use local time instead of Redis TIME command (saves round-trip) sem3 = Redis::Semaphore.new(:local_time, use_local_time: true, stale_client_timeout: 10, redis: redis_client ) # Auto-expiring semaphore (all keys expire after 60 seconds) temp_sem = Redis::Semaphore.new(:temporary_lock, expiration: 60, redis: redis_client ) temp_sem.lock do # Keys will expire 60 seconds after unlock perform_task end sleep 65 puts "Expired: #{temp_sem.exists?}" # => false # Redis namespace support (requires redis-namespace gem) require 'redis-namespace' namespaced_redis = Redis::Namespace.new(:myapp, redis: redis_client) sem4 = Redis::Semaphore.new(:feature_flag, redis: namespaced_redis ) # Keys: myapp:feature_flag:AVAILABLE, myapp:feature_flag:GRABBED, etc. ``` -------------------------------- ### Ruby: Lock Semaphore Indefinitely Source: https://github.com/dv/redis-semaphore/blob/master/README.md Demonstrates how to acquire a lock on a semaphore indefinitely in Ruby. This behavior mimics the standard Redis BLPOP command. It's a simple call to the `lock` method without arguments or with `nil`. ```ruby semaphore.locksemaphore.lock(nil) ``` -------------------------------- ### Acquire and Release Locks with Block Syntax Source: https://context7.com/dv/redis-semaphore/llms.txt Shows how to use block syntax for acquiring semaphore locks, ensuring automatic release even with exceptions. Supports basic blocking, timeouts, non-blocking attempts, multi-resource semaphores, and exception safety. ```ruby require 'redis-semaphore' redis = Redis.new(db: 15)semaphore = Redis::Semaphore.new(:critical_section, redis: redis) # Basic blocking lock result = semaphore.lock do # Only one process can execute this at a time puts "Processing payment..." process_payment 42 end puts result # => 42 # With timeout (blocks for max 5 seconds) success = semaphore.lock(5) do expensive_operation "completed" end if success puts "Operation completed: #{success}" else puts "Could not acquire lock within 5 seconds" end # Non-blocking (timeout 0) semaphore.lock(0) do puts "Got lock immediately!" end || puts "Lock unavailable, skipping" # Multi-resource semaphore worker_pool = Redis::Semaphore.new(:workers, resources: 5, redis: redis) # Up to 5 processes can execute simultaneously worker_pool.lock do |token| puts "Worker #{token} processing job" process_job end # Exception safety - lock automatically released begin semaphore.lock do raise "Something went wrong" end rescue => e puts "Error: #{e.message}" puts "Locked? #{semaphore.locked?}" # => false end ``` -------------------------------- ### Wait and Signal Semaphore Operations - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Demonstrates the 'wait' (aliased to 'lock') and 'signal' (to release resources) methods for traditional semaphore operations. 'signal' can put a token back or generate a new one. Requires the 'redis-semaphore' gem. ```ruby # Retrieve 2 resources token1 = sem.wait token2 = sem.wait work # Put 3 resources back sem.signal(token1) sem.signal(token2) sem.signal sem.available_count # returns 3 ``` -------------------------------- ### Configure Production Redis Semaphore Source: https://context7.com/dv/redis-semaphore/llms.txt Sets up a Redis Semaphore instance for production use with specific resource limits, timeouts, and expiration settings. It utilizes a provided Redis client and configures time synchronization for distributed consistency. ```ruby production_sem = Redis::Semaphore.new(:critical_api, redis: redis_client, resources: 20, stale_client_timeout: 30, expiration: 3600, use_local_time: false # Use Redis time for distributed consistency ) ``` -------------------------------- ### Manual Lock and Unlock Operations Source: https://context7.com/dv/redis-semaphore/llms.txt Illustrates manual acquisition and release of semaphore locks, offering finer control over the lock lifecycle. This method is useful when the block syntax is not suitable. It demonstrates checking lock status and available resources. ```ruby require 'redis-semaphore' redis = Redis.new(db: 15)semaphore = Redis::Semaphore.new(:file_processor, redis: redis) # Basic manual locking if semaphore.lock(2) # Wait up to 2 seconds begin file = File.open('data.txt', 'w') file.write('Important data') file.close ensure available = semaphore.unlock puts "Resources available after unlock: #{available}" end else puts "Could not acquire lock" end # Multi-resource semaphore pool = Redis::Semaphore.new(:connection_pool, resources: 3, redis: redis) token1 = pool.lock(1) token2 = pool.lock(1) token3 = pool.lock(1) puts "Locked? #{pool.locked?}" # => true puts "Available: #{pool.available_count}" # => 0 fourth_attempt = pool.lock(1) puts "Fourth lock: #{fourth_attempt}" # => false pool.unlock puts "Still locked? #{pool.locked?}" # => true puts "Available: #{pool.available_count}" # => 1 pool.unlock pool.unlock puts "Locked? #{pool.locked?}" # => false puts "Available: #{pool.available_count}" # => 3 ``` -------------------------------- ### Initialize Semaphore with Stale Client Timeout - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Demonstrates initializing a Redis Semaphore with a 'stale_client_timeout' option. This setting enables automatic checking and release of stale locks after a specified duration, preventing deadlocks if a client crashes. Requires the 'redis-semaphore' gem. ```ruby s = Redis::Semaphore.new(:stale_semaphore, :redis => r, :stale_client_timeout => 5) # in seconds ``` -------------------------------- ### Check Semaphore Existence and Available Count - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Shows how to check if a Redis Semaphore exists using 'exists?' and retrieve the number of currently available resources using 'available_count'. These methods are useful for monitoring the semaphore's state. Requires the 'redis-semaphore' gem. ```ruby puts "This semaphore does exist." if s.exists? puts "There are #{s.available_count} resources available right now." ``` -------------------------------- ### Initialize Redis Semaphore with Expiration Option Source: https://github.com/dv/redis-semaphore/blob/master/README.md Sets an expiration timeout for Redis semaphore keys using the Redis EXPIRE command. This ensures that semaphore-related keys are automatically removed from the Redis server after a specified period, preventing clutter. The `:expiration` option takes the timeout in seconds. Use with caution to avoid premature semaphore disappearance. ```ruby s = Redis::Semaphore.new(:local_semaphore, :redis = r, :expiration => 100) ``` -------------------------------- ### Lock with Timeout - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Demonstrates acquiring a lock on a Redis Semaphore with a specified timeout. The 'lock' method will only wait for the given duration before returning false if the lock cannot be acquired. Requires the 'redis-semaphore' gem. ```ruby if s.lock(5) # This will only block for at most 5 seconds if the semaphore stays locked. work s.unlock else puts "Aborted." end ``` -------------------------------- ### Ruby: Non-blocking Semaphore Lock Source: https://github.com/dv/redis-semaphore/blob/master/README.md Illustrates acquiring a lock on a semaphore without blocking in Ruby. This is useful when you need to check for resource availability immediately without waiting. This is achieved by passing 0 as the timeout argument. ```ruby # This does not block at all and rather returns immediately if there's no ``` -------------------------------- ### Unlock Returns Available Count - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Illustrates that the 'unlock' method of Redis Semaphore returns the new count of available resources after the lock is released. This can be useful for tracking resource availability. Requires the 'redis-semaphore' gem. ```ruby sem.lock sem.unlock # returns 1 sem.available_count # also returns 1 ``` -------------------------------- ### Stale Lock Detection with Redis Semaphore Source: https://context7.com/dv/redis-semaphore/llms.txt Explains how to use Redis Semaphore for stale lock detection, automatically releasing locks held by dead or hung clients. It covers setting a timeout for stale clients and using a watchdog pattern for continuous cleanup. Locks are automatically released if held longer than the specified timeout. ```ruby require 'redis-semaphore' redis = Redis.new(db: 15) # Semaphore with staleness checking on every lock attemptsemaphore = Redis::Semaphore.new(:api_calls, resources: 1, stale_client_timeout: 5, redis: redis ) # Lock automatically released if held > 5 secondssemaphore.lock sleep 6 # Another process/thread can now acquire the lock second_sem = Redis::Semaphore.new(:api_calls, stale_client_timeout: 5, redis: redis ) acquired = second_sem.lock(1) puts "Acquired stale lock: #{acquired}" # => token string # Watchdog pattern - dedicated thread for stale lock cleanup normal_sem = Redis::Semaphore.new(:shared_resource, redis: redis) watchdog_sem = Redis::Semaphore.new(:shared_resource, stale_client_timeout: 3, redis: redis ) watchdog = Thread.new do loop do watchdog_sem.release_stale_locks! sleep 1 end end # Main process locks but doesn't unlock normal_sem.lock puts "Initially locked: #{normal_sem.locked?}" # => true sleep 4 # Watchdog has released the stale lock puts "After watchdog: #{normal_sem.locked?}" # => false # Blocking calls also get unblocked by watchdog normal_sem.lock thread = Thread.new do puts "Waiting for lock..." if normal_sem.lock(10) puts "Got lock from watchdog!" end end sleep 5 # Watchdog will release after 3 seconds thread.join watchdog.kill ``` -------------------------------- ### Manually Release Stale Locks - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Shows how to use the 'release_stale_locks!' method to manually check for and release any locks that have exceeded their stale client timeout. This is often used in a background process or watchdog. Requires the 'redis-semaphore' gem. ```ruby Thread.new do watchdog = Redis::Semaphore.new(:semaphore, :host => "localhost", :stale_client_timeout => 5) while(true) watchdog.release_stale_locks! sleep 1 end end normal_sem = Redis::Semaphore.new(:semaphore, :host => "localhost") normal_sem.lock sleep 5 normal_sem.locked? # returns false normal_sem.lock normal_sem.lock(5) # will block until the watchdog releases the previous lock after 1 second ``` -------------------------------- ### Automatic Lock Release on Exception - Ruby Source: https://github.com/dv/redis-semaphore/blob/master/README.md Shows that if an exception occurs within a block passed to the 'lock' method, the semaphore lock is automatically released. This ensures locks are not left hanging due to errors. Requires the 'redis-semaphore' gem. ```ruby begin s.lock do raise Exception end rescue s.locked? # false end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.