sqlalchemy_dlock.types module

class sqlalchemy_dlock.types.BaseSadLock(connection_or_session: Connection | Session | scoped_session, key, *args, **kwargs)

Bases: _local

Base class of database lock implementation

Note

  • It’s Thread-Local (threading.local)

  • It’s an abstract class, do not manual instantiate

The acquire() and release() methods can be used as context managers for a with statement. acquire() will be called when the block is entered, and release() will be called when the block is exited. Hence, the following snippet:

with some_lock:
    # do something...
    pass

is equivalent to:

some_lock.acquire()
try:
    # do something...
    pass
finally:
    some_lock.release()
Parameters:
  • connection_or_session (sqlalchemy Connection or orm Session/ScopedSession object) – SQL locking functions will be invoked on it

  • key – ID or name of the SQL locking function

acquire(block: bool = True, timeout: float | int | None = None, *args, **kwargs) bool

Acquire a lock, blocking or non-blocking.

  • With the block argument set to True (the default), the method call will block until the lock is in an unlocked state, then set it to locked and return True.

  • With the block argument set to False, the method call does not block. If the lock is currently in a locked state, return False; otherwise set the lock to a locked state and return True.

  • When invoked with a positive, floating-point value for timeout, block for at most the number of seconds specified by timeout as long as the lock can not be acquired. Invocations with a negative value for timeout are equivalent to a timeout of zero. Invocations with a timeout value of None (the default) set the timeout period to infinite. The timeout argument has no practical implications if the block argument is set to False and is thus ignored. Returns True if the lock has been acquired or False if the timeout period has elapsed.

property acquired: bool

locked/unlocked state property

As a Getter:

  • It returns True if the lock has been acquired, False otherwise.

As a Setter:

  • Set to True is equivalent to call acquire()

  • Set to False is equivalent to call release()

close(*args, **kwargs)

Same as release()

Except that the ValueError is NOT raised when invoked on an unlocked lock.

An invocation of this method is equivalent to:

if not some_lock.acquired:
    some_lock.release()

This method maybe useful together with contextlib.closing(), when we need a with statement, but don’t want it to acquire at the beginning of the block.

eg:

# ...

from contextlib import closing
from sqlalchemy_dlock import create_sadlock

# ...

with closing(create_sadlock(some_connection, some_key)) as lock:
    # will not acquire at the begin of with-block
    assert not lock.acquired
    # ...
    # lock when need
    lock.acquire()
    assert lock.acquired
    # ...
# `close` will be called at the end with-block
assert not lock.acquired
property connection_or_session: Connection | Session | scoped_session

Returns connection_or_session parameter of the constructor

property key

Returns key parameter of the constructor

property locked: bool

Alias of acquired

release(*args, **kwargs)

Release a lock.

Since the class is thread-local, this cannot be called from other thread or process, and also can not be called from other connection. (Although PostgreSQL’s shared advisory lock supports so).

When the lock is locked, reset it to unlocked, and return. If any other threads are blocked waiting for the lock to become unlocked, allow exactly one of them to proceed.

When invoked on an unlocked lock, a ValueError is raised.

There is no return value.