Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify FileLock class implementation #228

Merged
merged 3 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions broker/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,38 +402,34 @@ def simple_retry(cmd, cmd_args=None, cmd_kwargs=None, max_timeout=60, _cur_timeo

class FileLock:
"""Basic file locking class that acquires and releases locks
recommended usage is the context manager which will handle everythign for you
recommended usage is the context manager which will handle everything for you

with FileLock("basic_file.txt") as basic_file:
basic_file.write("some text")
with FileLock("basic_file.txt"):
Path("basic_file.txt").write_text("some text")

basic_file is a Path object of the desired file
If a lock is already in place, FileLock will wait up to <timeout> seconds
"""

def __init__(self, file_name, timeout=10):
self.file = Path(file_name)
self.lock = Path(f"{self.file}.lock")
self.lock = Path(f"{file_name}.lock")
self.timeout = timeout

def wait_file(self):
start = time.time()
timeout_after = time.time() + self.timeout
while self.lock.exists():
if (time.time() - start) < self.timeout:
if time.time() <= timeout_after:
time.sleep(1)
continue
else:
raise exceptions.BrokerError(
f"Timeout while attempting to open {self.file.absolute()}"
f"Timeout while waiting for lock release: {self.lock.absolute()}"
)
self.lock.touch()
return self.file

def return_file(self):
self.lock.unlink()

def __enter__(self):
return self.wait_file()
self.wait_file()

def __exit__(self, *tb_info):
self.return_file()
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ classifiers =
install_requires =
awxkit
click
dynaconf>=3.1.0
dynaconf<3.2.1
logzero
pyyaml
setuptools
Expand Down
10 changes: 6 additions & 4 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ def test_emitter(tmp_file):


def test_lock_file_created(tmp_file):
with helpers.FileLock(tmp_file) as tf:
assert isinstance(tf, Path)
assert Path(f"{tf}.lock").exists()
lock_file = helpers.FileLock(tmp_file)
with lock_file:
assert isinstance(lock_file.lock, Path)
assert lock_file.lock.exists()
assert not lock_file.lock.exists()


def test_lock_timeout(tmp_file):
Expand All @@ -85,7 +87,7 @@ def test_lock_timeout(tmp_file):
with pytest.raises(exceptions.BrokerError) as exc:
with helpers.FileLock(tmp_file, timeout=1):
pass
assert str(exc.value).startswith("Timeout while attempting to open")
assert str(exc.value).startswith("Timeout while waiting for lock release: ")


def test_find_origin_simple():
Expand Down
Loading