RedisCluster.Lock (redis_cluster v0.8.0)
View SourceA simple in-memory locking mechanism using Erlang's :persistent_term.
This module provides a lightweight, process-independent locking mechanism that can be used to coordinate access to shared resources.
Examples
# Create a lock with name :my_lock
iex> RedisCluster.Lock.create(:my_lock)
:ok
iex> RedisCluster.Lock.check(:my_lock)
:ok
# Lock it to prevent concurrent access
iex> RedisCluster.Lock.lock(:my_lock)
:ok
iex> RedisCluster.Lock.check(:my_lock)
:locked
# Unlock it when done
iex> RedisCluster.Lock.unlock(:my_lock)
:ok
iex> RedisCluster.Lock.check(:my_lock)
:ok
# Use with_lock to automatically unlock after an operation
iex> RedisCluster.Lock.with_lock(:auto_lock, fn ->
...> # This code runs while the lock is held
...> "operation result"
...> end)
"operation result"
iex> RedisCluster.Lock.check(:auto_lock)
:ok
# Delete a lock when no longer needed
iex> RedisCluster.Lock.create(:temp_lock)
:ok
iex> RedisCluster.Lock.delete(:temp_lock)
true
Summary
Types
The name of the lock as an atom. Must be unique within the application.
Possible statuses of a lock.
Functions
Checks the status of a lock.
Retries a function until the lock becomes available or max attempts are reached.
Creates a new lock with the given name.
Deletes a lock with the given name.
Locks a lock, to signal to other processes that the lock is held.
Unlocks a lock, to signal to other processes that the lock is available.
Executes a function with a lock held, and automatically unlocks when done.
Types
@type name() :: atom()
The name of the lock as an atom. Must be unique within the application.
@type status() :: :ok | :locked
Possible statuses of a lock.
Functions
Checks the status of a lock.
Returns :ok if the lock is available, :locked if it's held, or the default
value if the lock doesn't exist.
Examples
iex> RedisCluster.Lock.create(:check_lock)
:ok
iex> RedisCluster.Lock.check(:check_lock)
:ok
iex> RedisCluster.Lock.lock(:check_lock)
:ok
iex> RedisCluster.Lock.check(:check_lock)
:locked
iex> RedisCluster.Lock.check(:bogus, :not_found)
:not_found
@spec check_with_retry(name(), pos_integer(), (status() -> term())) :: term()
Retries a function until the lock becomes available or max attempts are reached.
Returns the result of calling the function with the lock status.
Examples
iex> RedisCluster.Lock.create(:retry_example)
:ok
iex> RedisCluster.Lock.check_with_retry(:retry_example, 3, fn status ->
...> # This will be called with status = :ok since the lock is available
...> {:got_status, status}
...> end)
{:got_status, :ok}
@spec create(name()) :: :ok
Creates a new lock with the given name.
The lock is initially unlocked.
Examples
iex> RedisCluster.Lock.create(:example_lock)
:ok
iex> RedisCluster.Lock.check(:example_lock)
:ok
Deletes a lock with the given name.
Returns true if the lock was deleted, false otherwise.
Examples
iex> RedisCluster.Lock.create(:delete_me)
:ok
iex> RedisCluster.Lock.delete(:delete_me)
true
iex> RedisCluster.Lock.delete(:bogus)
false
@spec lock(name()) :: :ok
Locks a lock, to signal to other processes that the lock is held.
Examples
iex> RedisCluster.Lock.create(:lock_me)
:ok
iex> RedisCluster.Lock.lock(:lock_me)
:ok
iex> RedisCluster.Lock.check(:lock_me)
:locked
@spec unlock(name()) :: :ok
Unlocks a lock, to signal to other processes that the lock is available.
Examples
iex> RedisCluster.Lock.create(:unlock_me)
iex> RedisCluster.Lock.lock(:unlock_me)
iex> RedisCluster.Lock.check(:unlock_me)
:locked
iex> RedisCluster.Lock.unlock(:unlock_me)
iex> RedisCluster.Lock.check(:unlock_me)
:ok
Executes a function with a lock held, and automatically unlocks when done.
This ensures that the lock is released even if the function raises an exception.
Examples
iex> RedisCluster.Lock.with_lock(:protected_operation, fn ->
...> # Critical section that requires exclusive access
...> :operation_complete
...> end)
:operation_complete