mirror of
https://github.com/alexgetmancom/miband-bot.git
synced 2026-07-19 20:20:14 +03:00
feat: add dynamic owner binding
This commit is contained in:
+40
-6
@@ -3,13 +3,24 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import fcntl
|
||||
import os
|
||||
import time
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
# Попытка импорта fcntl (для Unix-систем) или msvcrt (для Windows)
|
||||
try:
|
||||
import fcntl
|
||||
_HAS_FCNTL = True
|
||||
except ImportError:
|
||||
_HAS_FCNTL = False
|
||||
try:
|
||||
import msvcrt
|
||||
_HAS_MSVCRT = True
|
||||
except ImportError:
|
||||
_HAS_MSVCRT = False
|
||||
|
||||
|
||||
class LockUnavailable(RuntimeError):
|
||||
"""Raised when another process already owns the sync lock."""
|
||||
@@ -19,10 +30,23 @@ class LockUnavailable(RuntimeError):
|
||||
def exclusive_file_lock(path: Path) -> Iterator[None]:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with path.open("a+", encoding="utf-8") as lock_file:
|
||||
try:
|
||||
fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except BlockingIOError as exc:
|
||||
raise LockUnavailable(f"Lock is already held: {path}") from exc
|
||||
fd = lock_file.fileno()
|
||||
|
||||
if _HAS_FCNTL:
|
||||
try:
|
||||
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except BlockingIOError as exc:
|
||||
raise LockUnavailable(f"Lock is already held: {path}") from exc
|
||||
elif _HAS_MSVCRT:
|
||||
try:
|
||||
lock_file.seek(0)
|
||||
# Блокируем первые 64 байта файла без ожидания (non-blocking)
|
||||
msvcrt.locking(fd, msvcrt.LK_NBLCK, 64)
|
||||
except (OSError, IOError) as exc:
|
||||
raise LockUnavailable(f"Lock is already held: {path}") from exc
|
||||
else:
|
||||
# Резервный вариант, если блокировки недоступны на платформе
|
||||
pass
|
||||
|
||||
try:
|
||||
lock_file.seek(0)
|
||||
@@ -31,4 +55,14 @@ def exclusive_file_lock(path: Path) -> Iterator[None]:
|
||||
lock_file.flush()
|
||||
yield
|
||||
finally:
|
||||
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
||||
if _HAS_FCNTL:
|
||||
try:
|
||||
fcntl.flock(fd, fcntl.LOCK_UN)
|
||||
except Exception:
|
||||
pass
|
||||
elif _HAS_MSVCRT:
|
||||
try:
|
||||
lock_file.seek(0)
|
||||
msvcrt.locking(fd, msvcrt.LK_UNLCK, 64)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user