StateLock — exclusive access to one state key: read its version, or seal a new one.
A state is a kept name over objects/; swap seals a new version and
repoints the name, so a crash anywhere leaves the previous version current.
StateLock
Bases: KeyLock
Exclusive access to the state key: read its version, or seal and repoint a new one.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/state_lock.py
| class StateLock(KeyLock):
"""Exclusive access to the state ``key``: read its version, or seal and repoint a new one."""
def __init__(self, scratch: Scratch, key: str, timeout_seconds: float) -> None:
"""Acquire the lock on ``key``, waiting up to ``timeout_seconds``.
Raises:
RecipeError: If the lock is still held elsewhere when the timeout passes.
"""
self._scratch = scratch
super().__init__(scratch.state_locks_dir, key)
self.acquire(timeout_seconds)
def get(self) -> tuple[Path, ContentHash] | None:
"""The current version of the state as ``(object directory, hash)``, or ``None``."""
with self._scratch.database.transaction() as db:
hash = names.resolve(db, names.state_name(self.key))
if hash is None or not self._scratch.object_dir(hash).is_dir():
return None
return self._scratch.object_dir(hash), hash
def swap(self, workspace: Workspace, stem: str) -> tuple[Path, ContentHash]:
"""Seal ``workspace/<stem>`` as the state's new version and make it current.
Raises:
RecipeError: If this lock has been released.
"""
if not self.held:
raise RecipeError(f"state lock on {self.key!r} is no longer held")
hash = seal_tree(self._scratch, workspace.path / stem)
with self._scratch.database.transaction() as db:
names.point(db, names.state_name(self.key), hash, kept=True)
workspace.release()
return self._scratch.object_dir(hash), hash
|
__init__(scratch, key, timeout_seconds)
Acquire the lock on key, waiting up to timeout_seconds.
Raises:
| Type |
Description |
RecipeError
|
If the lock is still held elsewhere when the timeout passes.
|
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/state_lock.py
| def __init__(self, scratch: Scratch, key: str, timeout_seconds: float) -> None:
"""Acquire the lock on ``key``, waiting up to ``timeout_seconds``.
Raises:
RecipeError: If the lock is still held elsewhere when the timeout passes.
"""
self._scratch = scratch
super().__init__(scratch.state_locks_dir, key)
self.acquire(timeout_seconds)
|
get()
The current version of the state as (object directory, hash), or None.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/state_lock.py
| def get(self) -> tuple[Path, ContentHash] | None:
"""The current version of the state as ``(object directory, hash)``, or ``None``."""
with self._scratch.database.transaction() as db:
hash = names.resolve(db, names.state_name(self.key))
if hash is None or not self._scratch.object_dir(hash).is_dir():
return None
return self._scratch.object_dir(hash), hash
|
swap(workspace, stem)
Seal workspace/<stem> as the state's new version and make it current.
Raises:
| Type |
Description |
RecipeError
|
If this lock has been released.
|
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/state_lock.py
| def swap(self, workspace: Workspace, stem: str) -> tuple[Path, ContentHash]:
"""Seal ``workspace/<stem>`` as the state's new version and make it current.
Raises:
RecipeError: If this lock has been released.
"""
if not self.held:
raise RecipeError(f"state lock on {self.key!r} is no longer held")
hash = seal_tree(self._scratch, workspace.path / stem)
with self._scratch.database.transaction() as db:
names.point(db, names.state_name(self.key), hash, kept=True)
workspace.release()
return self._scratch.object_dir(hash), hash
|