Conversation
bef2aeb to
86720d8
Compare
Move menubar admin-stats polling off the main thread into a background worker. Guard against stale results with single-flight locking and generation-token invalidation across stop/restart, status-flap, and STOPPING transitions. Key changes: - Background worker for HTTP stats polling with per-generation sessions - Watchdog recovery for stuck in-flight refresh state - Session cleanup on invalidation, stale completion, and failure paths - Lightweight version loader for bundled .app layouts (no omlx import) - Internal version comparator replacing packaging.version dependency (handles stable upgrades, rc→final, .postN) Includes focused contract tests for all async refresh, invalidation, session isolation, watchdog, and version comparison paths.
87885e9 to
e1b3a44
Compare
jundot
left a comment
There was a problem hiding this comment.
Thanks for the PR. Moving stats polling off the main thread makes sense since the 2s HTTP timeout could freeze the menubar.
A few things:
-
Thread safety:
_stats_refresh_in_flight/_stats_refresh_tokenare accessed from both main thread and background workers without a lock. The 5s polling interval makes races unlikely, but a brief comment or athreading.Lockwould clarify the intent. -
_is_newer_versioncustom parser: PEP 440 has edge cases (epochs, local versions, dev+pre combos) the regex doesn't cover.packagingships with pip so it's available everywhere. If the bundled .app is missing it, that's a build config fix, not a code workaround. -
requests.Sessionacross threads: not documented as thread-safe. Current pattern is probably fine (one thread at a time) but worth a comment. -
_load_versionfallback: silently returning"0.0.0"could mask bundle build issues. A log warning would help.
Overall design is solid and test coverage is thorough. Nothing blocking, mostly hardening suggestions.
187e87b to
dfc5b20
Compare
|
Thanks for the review — all four points addressed in
|
Make _fetch_stats_snapshot a @staticmethod so the background worker never touches self — api_key, base_url, and session are snapshotted by the caller before dispatch. Drop eager session close from _invalidate_stats_refresh_generation; the stale-token rejection in the completion handler already closes orphaned sessions when the worker finishes. Tighten the stale-token guard: reject when token != current, not only when token is not None and != current. The old guard silently accepted results with a missing token field. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
This PR moves menubar admin-stats polling off the main thread and hardens the refresh lifecycle so stale results from prior server generations do not leak back into the UI.
It also folds in the menubar import-safety/package-init work that was previously split into #349, so the packaged app modules remain importable in headless/CI environments without pulling in the heavy
omlxruntime.What Changed
STOPPINGand a watchdog to recover from stuck in-flight refresh state.requests.Sessionobjects on invalidation, stale completion, non-running completion, and snapshot failure paths.requests.Session..applayouts without importing the heavyomlxruntime._is_newer_versionnow usespackaging.version.Versionfor PEP 440-aware comparison._load_version()now logs a warning before falling back to"0.0.0".mainand resolved the resulting overlap inpackaging/omlx_app/app.py.Test Coverage
Added and expanded focused contract tests for:
STOPPINGfallback behavioromlx_appandomlx_app.apppackaging.version.VersionValidation
Focused menubar/package suites passing locally:
/Users/noahlyons/dev/omlx/.venv/bin/python -m pytest tests/test_omlx_app_async_refresh.py tests/test_omlx_app_package_init.py -qSanity check:
python3 -m py_compile packaging/omlx_app/app.pyNotes