chart/tests
Chris Amow a395818581 Post cross-thread events through the loop, and measure how late it runs
P0 from docs/async_refactor.md. The mutating routes are sync `def`, so FastAPI
runs them in a threadpool, and they reach Runtime.broadcast through
rebuild_levels — writing asyncio.Queue directly from there. That queue is not
thread-safe: it wakes a consumer by resolving a Future, which only the loop
thread may do. A dropped wakeup means a drawing made in one browser does not
reach another until the next market tick.

broadcast now posts through call_soon_threadsafe when it is off the loop, and
publishes directly when it is on it, so the stream's own path pays nothing.

Worth being straight about the tests: the race is timing-dependent and did not
reproduce in twenty attempts — a foreign-thread put_nowait usually lands in the
ready queue before the loop sleeps, and a tick every second covers the rest.
Even asyncio's debug thread-affinity check stays quiet unless a consumer is
parked on the Future at that instant. So the tests assert the contract rather
than provoke the failure: a broadcast from a worker thread must go through
call_soon_threadsafe, one from the loop must deliver synchronously, and both
must arrive.

Also adds the loop-lag probe, which reports scheduling drift as loop_lag_ms on
/api/status. It found P1 on its first run: 19,441ms worst against 1.5ms in
steady state, which is seeding blocking the loop. "The chart feels laggy" is now
a number.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 15:30:45 -05:00
..
e2e Post cross-thread events through the loop, and measure how late it runs 2026-08-11 15:30:45 -05:00
fixtures Add implementation plan for /ES multi-timeframe confluence chart 2026-08-09 20:31:40 -05:00
test_aggregator.py Expand regression coverage and document next steps 2026-08-11 03:22:00 -05:00
test_alert_state.py Persist alert cooldowns across restarts so deploys stop re-firing every zone 2026-08-11 19:46:11 +00:00
test_alerts.py Stop re-alerting when price crosses a level 2026-08-10 01:51:54 -05:00
test_asset_versioning.py Version static assets so a fixed bug stops reproducing in an open tab 2026-08-10 04:29:56 -05:00
test_auth.py - Drag a selected trendline body to reposition the entire line. 2026-08-11 05:46:09 -05:00
test_bar_space.py Price trendlines across bars, add one-shot alerts, collapse layers, drop 1h MAs 2026-08-10 04:15:05 -05:00
test_confluence.py Fix trendline deletion while typing, audio leak, prefs drift, cluster payload 2026-08-10 00:17:40 -05:00
test_horizontals.py Add prior-day levels and session VWAP; fix alert repetition they exposed 2026-08-10 00:36:21 -05:00
test_manual_lines.py better default names 2026-08-11 14:36:58 -05:00
test_moving_averages.py Implement M3 projected daily moving averages 2026-08-09 20:44:11 -05:00
test_price_alerts.py Add a price alert input 2026-08-10 02:09:14 -05:00
test_replay.py Implement M0 Yahoo market data and replay 2026-08-09 20:36:13 -05:00
test_runtime_alerts.py Post cross-thread events through the loop, and measure how late it runs 2026-08-11 15:30:45 -05:00
test_runtime_start.py Unify chart geometry and deepen 30m history 2026-08-11 04:08:02 -05:00
test_schwab_callback.py Add the OAuth callback endpoint at /api/qt 2026-08-10 04:45:31 -05:00
test_schwab_source.py Stop a zero-price tick and a late exchange bar corrupting the store 2026-08-10 17:10:24 -05:00
test_session.py Expand regression coverage and document next steps 2026-08-11 03:22:00 -05:00
test_store.py Stop a zero-price tick and a late exchange bar corrupting the store 2026-08-10 17:10:24 -05:00
test_vwap.py Add prior-day levels and session VWAP; fix alert repetition they exposed 2026-08-10 00:36:21 -05:00
test_ws_preferences.py Expand regression coverage and document next steps 2026-08-11 03:22:00 -05:00
test_yahoo.py Unify chart geometry and deepen 30m history 2026-08-11 04:08:02 -05:00