mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
fix(proxy): remove invalid savings tracker flock
This commit is contained in:
parent
a8b62a77d9
commit
0d8de25bfc
2 changed files with 37 additions and 25 deletions
|
|
@ -21,19 +21,6 @@ from typing import Any
|
|||
|
||||
from headroom import paths as _paths
|
||||
|
||||
# fcntl is Unix-only; on Windows file locking is skipped (best-effort).
|
||||
# Typed Any so attribute access on flock/LOCK_EX/LOCK_UN doesn't fail on
|
||||
# platforms where the type stub is absent.
|
||||
_fcntl: Any = None
|
||||
_HAS_FCNTL = False
|
||||
try:
|
||||
import fcntl as _fcntl_impl # noqa: E402
|
||||
|
||||
_fcntl = _fcntl_impl
|
||||
_HAS_FCNTL = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
HEADROOM_SAVINGS_PATH_ENV_VAR = _paths.HEADROOM_SAVINGS_PATH_ENV
|
||||
|
|
@ -825,18 +812,7 @@ class SavingsTracker:
|
|||
f.write(json_data)
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
# Acquire an exclusive cross-process lock on the target file
|
||||
# before the atomic rename so concurrent workers don't clobber
|
||||
# each other's increments. Unix only; Windows skips gracefully.
|
||||
if _HAS_FCNTL and self._path.exists():
|
||||
with open(self._path, "r+b") as lock_fh:
|
||||
_fcntl.flock(lock_fh, _fcntl.LOCK_EX)
|
||||
try:
|
||||
Path(tmp_path).replace(self._path)
|
||||
finally:
|
||||
_fcntl.flock(lock_fh, _fcntl.LOCK_UN)
|
||||
else:
|
||||
Path(tmp_path).replace(self._path)
|
||||
Path(tmp_path).replace(self._path)
|
||||
except Exception:
|
||||
try:
|
||||
Path(tmp_path).unlink()
|
||||
|
|
|
|||
|
|
@ -211,6 +211,42 @@ def test_record_compression_savings_skips_empty_updates_and_normalizes_timestamp
|
|||
assert persisted["history"][-1]["timestamp"] == "2026-03-27T12:34:00Z"
|
||||
|
||||
|
||||
def test_savings_tracker_save_does_not_flock_target_inode_before_replace(tmp_path, monkeypatch):
|
||||
path = tmp_path / "proxy_savings.json"
|
||||
tracker = SavingsTracker(path=str(path))
|
||||
|
||||
tracker.record_request(
|
||||
model="gpt-4o",
|
||||
input_tokens=120,
|
||||
tokens_saved=10,
|
||||
timestamp="2026-03-27T09:00:00Z",
|
||||
)
|
||||
assert path.exists()
|
||||
|
||||
flock_calls: list[int] = []
|
||||
|
||||
class _FcntlSpy:
|
||||
LOCK_EX = 1
|
||||
LOCK_UN = 2
|
||||
|
||||
def flock(self, _fh, operation: int) -> None:
|
||||
flock_calls.append(operation)
|
||||
|
||||
monkeypatch.setattr(savings_tracker_module, "_HAS_FCNTL", True, raising=False)
|
||||
monkeypatch.setattr(savings_tracker_module, "_fcntl", _FcntlSpy(), raising=False)
|
||||
|
||||
tracker.record_request(
|
||||
model="gpt-4o",
|
||||
input_tokens=80,
|
||||
tokens_saved=5,
|
||||
timestamp="2026-03-27T09:10:00Z",
|
||||
)
|
||||
|
||||
assert flock_calls == []
|
||||
persisted = json.loads(path.read_text(encoding="utf-8"))
|
||||
assert persisted["lifetime"]["tokens_saved"] == 15
|
||||
|
||||
|
||||
def test_litellm_resolution_and_savings_estimation_fallbacks(monkeypatch):
|
||||
def fake_cost_per_token(*, model, prompt_tokens, completion_tokens):
|
||||
if model in {"gpt-4o", "anthropic/claude-sonnet-4-6"}:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue