diff options
| author | Scott Gasch <[email protected]> | 2022-05-31 15:36:40 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2022-05-31 15:36:40 -0700 |
| commit | 02302bbd9363facb59c4df2c1f4013087702cfa6 (patch) | |
| tree | 938e51338678416afc891d2839c2ee8dd341f34d /lockfile.py | |
| parent | f3dbc7dc19ba5703f8f5aa9bf8af3c491b3510f6 (diff) | |
Improve docstrings for sphinx.
Diffstat (limited to 'lockfile.py')
| -rw-r--r-- | lockfile.py | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/lockfile.py b/lockfile.py index ae48e57..7d187ea 100644 --- a/lockfile.py +++ b/lockfile.py @@ -42,20 +42,24 @@ class LockFileContents: """The contents we'll write to each lock file.""" pid: int + """The pid of the process that holds the lock""" + commandline: str + """The commandline of the process that holds the lock""" + expiration_timestamp: Optional[float] + """When this lock will expire as seconds since Epoch""" class LockFile(contextlib.AbstractContextManager): """A file locking mechanism that has context-manager support so you - can use it in a with statement. e.g. - - with LockFile('./foo.lock'): - # do a bunch of stuff... if the process dies we have a signal - # handler to do cleanup. Other code (in this process or another) - # that tries to take the same lockfile will block. There is also - # some logic for detecting stale locks. + can use it in a with statement. e.g.:: + with LockFile('./foo.lock'): + # do a bunch of stuff... if the process dies we have a signal + # handler to do cleanup. Other code (in this process or another) + # that tries to take the same lockfile will block. There is also + # some logic for detecting stale locks. """ def __init__( @@ -66,6 +70,18 @@ class LockFile(contextlib.AbstractContextManager): expiration_timestamp: Optional[float] = None, override_command: Optional[str] = None, ) -> None: + """C'tor. + + Args: + lockfile_path: path of the lockfile to acquire + do_signal_cleanup: handle SIGINT and SIGTERM events by + releasing the lock before exiting + expiration_timestamp: when our lease on the lock should + expire (as seconds since the Epoch). None means the + lock will not expire until we explicltly release it. + override_command: don't use argv to determine our commandline + rather use this instead if provided. + """ self.is_locked: bool = False self.lockfile: str = lockfile_path self.locktime: Optional[int] = None @@ -76,12 +92,19 @@ class LockFile(contextlib.AbstractContextManager): self.expiration_timestamp = expiration_timestamp def locked(self): + """Is it locked currently?""" return self.is_locked def available(self): + """Is it available currently?""" return not os.path.exists(self.lockfile) def try_acquire_lock_once(self) -> bool: + """Attempt to acquire the lock with no blocking. + + Returns: + True if the lock was acquired and False otherwise. + """ logger.debug("Trying to acquire %s.", self.lockfile) try: # Attempt to create the lockfile. These flags cause @@ -107,6 +130,20 @@ class LockFile(contextlib.AbstractContextManager): backoff_factor: float = 2.0, max_attempts=5, ) -> bool: + """Attempt to acquire the lock repeatedly with retries and backoffs. + + Args: + initial_delay: how long to wait before retrying the first time + backoff_factor: a float >= 1.0 the multiples the current retry + delay each subsequent time we attempt to acquire and fail + to do so. + max_attempts: maximum number of times to try before giving up + and failing. + + Returns: + True if the lock was acquired and False otherwise. + """ + @decorator_utils.retry_if_false( tries=max_attempts, delay_sec=initial_delay, backoff=backoff_factor ) @@ -121,6 +158,7 @@ class LockFile(contextlib.AbstractContextManager): return _try_acquire_lock_with_retries() def release(self): + """Release the lock""" try: os.unlink(self.lockfile) except Exception as e: |
