LockMgr

class lockmgr.lockmgr.LockMgr(name, expires: Optional[int] = 600, locked_by=None, lock_process=None, wait: int = None)[source]

LockMgr is a wrapper class for the various locking functions in this module, e.g. get_lock(), and is designed to be used as a context manager, i.e. using a with statement.

By using django-lockmgr via this context manager, it ensures you don’t forget to release any locks after you’ve finished with the resources you were using.

Not only that, but it also ensures in the event of an exception, or an unexpected crash of your application, that your locks will usually be safely released by __exit__().

Usage:

Using a with statement, create a LockMgr for mylock with automatic expiration if held for more than 60 seconds. After the with statement is completed, all locks created will be removed.

>>> try:
...     with LockMgr('mylock', 60) as l:
...         print('Doing stuff with mylock locked.')
...         # Obtain an additional lock for 'otherlock' - will use the same expiry as mylock
...         # Since ``ret`` is set to True, it will return a bool instead of raising Lock
...         if l.lock('otherlock', ret=True):
...             print('Now otherlock is locked...')
...             l.unlock('otherlock')
...         else:
...             print('Not doing stuff because otherlock is already locked...')
... except Locked as e:
...     print('Failed to lock. Reason: ', type(e), str(e))

You can also use renew() to request more time / re-create the lock if you’re close to, or have already exceeded the lock expiration time (defaults to 10 mins).

>>> try:
...     with LockMgr('mylock', 60) as l:
...         print('Doing stuff with mylock locked.')
...         sleep(50)
...         l.renew(expires=30)    # Add an additional 30 seconds of time to the lock expiration
...         sleep(50)              # It's now been 100 seconds. 'mylock' should be expired.
...         # We can still renew an expired lock when using LockMgr. It will simply re-create the lock.
...         l.renew()              # Add an additional 120 seconds (default) of time to the lock expiration
... except Locked as e:
...     print('Failed to lock. Reason: ', type(e), str(e))
__init__(name, expires: Optional[int] = 600, locked_by=None, lock_process=None, wait: int = None)[source]

Create an instance of LockMgr. This class is primarily intended to be used as a context manager (i.e. with LockMgr('mylock') as l:), see the main PyDoc block for LockMgr for more info.

Parameters
  • name (str) – The lock name to create (when using as a context manager)

  • expires (int) – How many seconds before this lock is considered stale and forcefully released?

  • locked_by (str) – (Optional) Who/what is using this lock. Defaults to system hostname.

  • lock_process (int) – (Optional) The process ID of the app using this lock

  • wait (int) – (Optional) Wait this many seconds for a lock to be released before giving up. If this is None then waiting will be disabled

expires = None

The user supplied expiration time in seconds

lock(name, expires: int = None, ret: bool = False, wait: int = None)[source]

Obtains a lock using get_lock() and appends it to _locks if successful.

If the argument ret is False (default), it will raise Locked if the lock couldn’t be obtained.

Otherwise, if ret is True, it will simply return False if the requested lock name is already locked.

Parameters
  • name (str) – A unique name to identify your lock

  • expires (int) – (Default: 600 sec) How long before this lock is considered stale and forcefully released?

  • ret (bool) – (Default: False) Return False if locked, instead of raising Locked.

  • wait (int) – (Optional) Retry obtaining the lock for this many seconds. MUST be divisible by 5. If not empty, will retry obtaining the lock every 5 seconds until wait seconds

Raises

Locked – If the requested lock name is already locked elsewhere, Locked will be raised

Return bool success

True if successful. If ret is true then will also return False on failure.

lock_process = None

Usually None, but sometimes may represent the process ID this lock belongs to

locked_by = None

Who/what created this lock - usually the hostname unless manually specified

main_lock = None

The Lock object created at the start of a with LockManager('xyz') statement

name = None

The lock name (from the constructor)

renew(lock: Union[str, lockmgr.models.Lock] = None, expires: int = 120, add_time: bool = True, **kwargs) → lockmgr.models.Lock[source]

Add expires seconds to the lock expiry time of lock. If lock isn’t specified, will default to the class instance’s original lock main_lock

Alias for renew_lock() - but with add_time and create set to True by default, instead of False.

With no arguments specified, this method will renew the main lock of the class main_lock for an additional 2 minutes (or if the lock is already expired, will re-create it with 2 min expiry).

Example usage:

>>> with LockMgr('mylock', expires=30) as l:
...     sleep(10)
...     l.renew(expires=60)                  # Add 60 seconds more time to 'mylock' expiration
...     l.main_lock.refresh_from_db()
...     print(l.main_lock.expires_seconds)   # Output: 79
...     l.renew('lockx', expires=60)         # Add 60 seconds more time to 'lockx' expiration
Parameters
  • lock (Lock) – Name of the lock to renew

  • lock – A Lock object to renew

  • expires (int) – (Default: 120) If not add_time, then this is the new expiration time in seconds from now. If add_time, then this many seconds will be added to the expiration time of the lock.

  • add_time (bool) – (Default: True) If True, then expires seconds will be added to the existing lock expiration time, instead of setting the expiration time to now + expires

Extra Keyword Arguments

Key bool create

(Default: True) If True, then create a new lock if it doesn’t exist / already expired

Key str locked_by

(Default: system hostname) What server/app is trying to obtain this lock?

Key int lock_process

(Optional) The process ID requesting the lock

Exceptions

Raises

LockNotFound – Raised if the requested lock doesn’t exist / is already expired and create is False.

Return Lock lock

The Lock object which was renewed

unlock(lock: Union[lockmgr.models.Lock, str] = None)[source]

Alias for unlock()

wait = None

How long to wait for a lock before giving up. If this is None then waiting will be disabled

Methods

Methods

__init__(name[, expires, locked_by, …])

Create an instance of LockMgr.

lock(name[, expires, ret, wait])

Obtains a lock using get_lock() and appends it to _locks if successful.

renew([lock, expires, add_time])

Add expires seconds to the lock expiry time of lock.

unlock([lock])

Alias for unlock()

__enter__()

When LockMgr is used as a context manager, i.e.

__exit__(exc_type, exc_val, exc_tb)

When the context manager is finished or an exception occurs, we unlock all locks that were created during the context manager session.