sqlalchemy_dlock.lock.base module#

class sqlalchemy_dlock.lock.base.BaseSadLock(connection_or_session: TConnectionOrSession, key, /, contextual_timeout: float | int | None = None, **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()

Note

A TimeoutError will be thrown if acquire timeout in with statement.

Parameters:
  • connection_or_session (TConnectionOrSession) – Connection or Session object SQL locking functions will be invoked on it

  • key – ID or name of the SQL locking function

  • contextual_timeout (float | int | None) –

    Timeout(seconds) for Context Managers.

    When called in a with statement, the new created lock object will pass it to timeout argument of BaseSadLock.acquire().

    Attention

    ONLY affects with statements.

    Example

    try:
        with create_sadlock(conn, k, contextual_timeout=5) as lck:
            # do something...
            pass
    except TimeoutError:
        # can not acquire after 5 seconds
        pass
    

    Note

    The default value of timeout is still None, when invoking acquire()

property connection_or_session: TConnectionOrSession#

Connection or Session object SQL locking functions will be invoked on it

It returns connection_or_session parameter of the class’s constructor.

property key: Any#

ID or name of the SQL locking function

It returns key parameter of the class’s constructor

property locked: bool#

locked/unlocked state property

True if the lock is acquired, else False

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 parameter 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.

Parameters:
Return type:

bool

release(*args, **kwargs) None#

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.

Return type:

None

close(*args, **kwargs) None#

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.locked:
    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.

Example

# ...

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.locked
    # ...
    # lock when need
    lock.acquire()
    assert lock.locked
    # ...

# `close` will be called at the end with-block
assert not lock.locked
Return type:

None