mirror of
https://github.com/zulip/zulip.git
synced 2025-11-11 01:16:19 +00:00
update_analytics_count: Use a correct lock mechanism.
Adds a re-usable lockfile_nonblocking helper to context_managers.
Relying on naive `os.mkdir` is not enough especially now that the
successful operation of this command is necessary for push notifications
to work for many servers.
We can't use `lockfile` context manager from
`zerver.lib.context_managers`, because we want the custom behavior of
failing if the lock can't be acquired, instead of waiting.
That's because if an instance of this gets stuck, we don't want to start
queueing up more processes waiting forever whenever the cronjob runs
again and fail->exit is preferrable instead.
(cherry picked from commit f61ed58c8f)
This commit is contained in:
committed by
Tim Abbott
parent
aecab44538
commit
96001b19fc
@@ -30,3 +30,21 @@ def lockfile(filename: str, shared: bool = False) -> Iterator[None]:
|
||||
with open(filename, "w") as lock:
|
||||
with flock(lock, shared=shared):
|
||||
yield
|
||||
|
||||
|
||||
@contextmanager
|
||||
def lockfile_nonblocking(filename: str) -> Iterator[bool]: # nocoverage
|
||||
"""Lock a file using flock(2) for the duration of a 'with' statement.
|
||||
|
||||
Doesn't block, yields False immediately if the lock can't be acquired."""
|
||||
with open(filename) as f:
|
||||
lock_acquired = False
|
||||
try:
|
||||
fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
lock_acquired = True
|
||||
yield lock_acquired
|
||||
except BlockingIOError:
|
||||
yield False
|
||||
finally:
|
||||
if lock_acquired:
|
||||
fcntl.flock(f, fcntl.LOCK_UN)
|
||||
|
||||
Reference in New Issue
Block a user