Background
_acquire_sync_lock in logseq_sync.py currently calls sys.exit(1) directly when it fails to acquire the lock:
def _acquire_sync_lock(db_path: str):
...
except portalocker.LockException:
lock_file.close()
print("Error: another sync process is already running. ...", file=sys.stderr)
sys.exit(1) # ← design smell
Problem
A lock acquisition function shouldn't decide to terminate the process — that conflates two concerns:
- What happened: couldn't acquire the lock
- What to do about it: that's the caller's decision
It also makes the function harder to test (requires mocking sys.exit) and prevents any caller from handling the failure gracefully (e.g., logging, cleanup, returning a structured error).
Proposed Fix
Raise a specific exception (e.g., RuntimeError or a dedicated SyncLockError) instead of calling sys.exit. Move the exit logic to the caller (_run_sync, _watch) where it belongs.
def _acquire_sync_lock(db_path: str):
...
except portalocker.LockException:
lock_file.close()
raise RuntimeError(
"Another sync process is already running. "
"Wait for it to finish or check for stale sync.lock."
)
Impact
Low risk, improves testability and separation of concerns.
Background
_acquire_sync_lockinlogseq_sync.pycurrently callssys.exit(1)directly when it fails to acquire the lock:Problem
A lock acquisition function shouldn't decide to terminate the process — that conflates two concerns:
It also makes the function harder to test (requires mocking
sys.exit) and prevents any caller from handling the failure gracefully (e.g., logging, cleanup, returning a structured error).Proposed Fix
Raise a specific exception (e.g.,
RuntimeErroror a dedicatedSyncLockError) instead of callingsys.exit. Move the exit logic to the caller (_run_sync,_watch) where it belongs.Impact
Low risk, improves testability and separation of concerns.