Skip to content

Commit 0af3980

Browse files
committed
docs(internals): Add file_lock module documentation
what: - Add docs/internals/file_lock.md with API reference - Add file_lock to internals toctree
1 parent 1ba58ed commit 0af3980

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

docs/internals/file_lock.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# FileLock - `libvcs._internal.file_lock`
2+
3+
Typed, asyncio-friendly file locking based on [filelock](https://github.com/tox-dev/filelock) patterns.
4+
5+
## Overview
6+
7+
This module provides portable file-based locking using the **SoftFileLock** pattern
8+
(`os.O_CREAT | os.O_EXCL`) for atomic lock acquisition. It supports both synchronous
9+
and asynchronous contexts.
10+
11+
### Key Features
12+
13+
- **Atomic acquisition**: Uses `os.O_CREAT | os.O_EXCL` for race-free lock creation
14+
- **Reentrant locking**: Same thread can acquire lock multiple times
15+
- **Stale lock detection**: Auto-removes locks older than configurable timeout (default 5min)
16+
- **Async support**: {class}`~libvcs._internal.file_lock.AsyncFileLock` with `asyncio.sleep` polling
17+
- **Two-file pattern**: Lock file (temporary) + marker file (permanent)
18+
- **PID tracking**: Writes PID to lock file for debugging
19+
20+
## Quick Start
21+
22+
### Synchronous Usage
23+
24+
```python
25+
from libvcs._internal.file_lock import FileLock
26+
27+
# Context manager (recommended)
28+
with FileLock("/tmp/my.lock"):
29+
# Critical section - only one process at a time
30+
pass
31+
32+
# Explicit acquire/release
33+
lock = FileLock("/tmp/my.lock")
34+
lock.acquire()
35+
try:
36+
# Critical section
37+
pass
38+
finally:
39+
lock.release()
40+
```
41+
42+
### Asynchronous Usage
43+
44+
```python
45+
import asyncio
46+
from libvcs._internal.file_lock import AsyncFileLock
47+
48+
async def main():
49+
async with AsyncFileLock("/tmp/my.lock"):
50+
# Async critical section
51+
pass
52+
53+
asyncio.run(main())
54+
```
55+
56+
### Atomic Initialization
57+
58+
The {func}`~libvcs._internal.file_lock.atomic_init` function implements the **two-file pattern**
59+
for coordinating one-time initialization across multiple processes:
60+
61+
```python
62+
from libvcs._internal.file_lock import atomic_init
63+
64+
def expensive_init():
65+
# One-time setup (e.g., clone repo, build cache)
66+
pass
67+
68+
# First call does initialization, subsequent calls skip
69+
did_init = atomic_init("/path/to/resource", expensive_init)
70+
```
71+
72+
## API Reference
73+
74+
```{eval-rst}
75+
.. automodule:: libvcs._internal.file_lock
76+
:members:
77+
:undoc-members:
78+
:show-inheritance:
79+
```

docs/internals/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ If you need an internal API stabilized please [file an issue](https://github.com
1212
exc
1313
types
1414
dataclasses
15+
file_lock
1516
query_list
1617
run
1718
subprocess

0 commit comments

Comments
 (0)