Live flight tracker showcase + the wire/republish bugs it surfaced#232
Live flight tracker showcase + the wire/republish bugs it surfaced#232FarhanAliRaza wants to merge 2 commits into
Conversation
examples/reflex gains a /flights page as a throughput showcase on real sensor data: world mode (default) polls OpenSky /states/all (~14k aircraft globally) and republishes the full figure every cycle over a Natural Earth 50m basemap (~80k points of segments); region mode polls an adsb.fi 250nm circle at up-to-1s cadence. Click-to-follow trail chart, box-select altitude cross-filter, and bundled-capture offline fallback (world mode dead-reckons one real 14k-aircraft frame along each track instead of shipping megabytes of frames). Building it surfaced an adapter bug: socket.io-parser's JS Decoder rejects binary packets with more than 10 attachments, and the resulting "parse error" closes the app's entire shared websocket, which then reconnects and re-subs in a silent infinite loop. The namespace now falls back from the split-buffer layout to the joined single-blob payload whenever the split would exceed the cap, and bounds msg replies with an err envelope instead of emitting an unparseable packet.
A republish through ChartView.updatePayload destroys the outgoing trace
groups, but the cached hover hit kept a direct reference to one — the
next draw dereferenced its freed (nulled) xBuf and threw. Worse than a
broken highlight: Reflex's frontend exception handler pattern-matches
"Cannot read properties of null" as a hydration error and responds with
window.location.reload(), so every crash became a full page reload that
reset the viewport (the "selecting resets zoom" symptom on the flights
page). _destroyTraceResources now clears the hover target it is about
to invalidate, and _drawHoverState treats null buffers as nothing to
highlight.
The title had the mirror-image bug: it is mount-time DOM, so an
in-place swap updated spec.title without ever touching the visible
element ("0 aircraft - idle" over a live map). Both spec-swap paths
(updatePayload and streaming append) now re-sync the title element and
the container's aria-label; a title appearing or disappearing forces a
re-layout since it owns top-margin space.
Merging this PR will not alter performance
Comparing Footnotes
|
Greptile SummaryThis PR adds a live flight tracker showcase and fixes republish issues it exposed. The main changes are:
Confidence Score: 4/5Safe to merge after addressing the non-blocking UI helper style issue. Core socket, republish, and showcase changes match the intended contracts and include targeted tests.
What T-Rex did
Important Files Changed
Reviews (1): Last reviewed commit: "Drop stale hover and re-sync title on in..." | Re-trigger Greptile |
| *[ | ||
| rx.badge(name, variant="solid") | ||
| if name == current | ||
| else rx.link(rx.badge(name, variant="soft"), href=href) |
There was a problem hiding this comment.
Avoid pre-styled links
nav() wraps badge navigation in rx.link, which brings Reflex link styling into a badge-only control. The project rule asks for rx.el.a when underline styling should be avoided, and these badges are intended to look like pills rather than text links.
| else rx.link(rx.badge(name, variant="soft"), href=href) | |
| else rx.el.a(rx.badge(name, variant="soft"), href=href) |
Rule Used: Use rx.el.a (unstyled) instead of rx.link (pre... (source)
Learned From
reflex-dev/reflex-web#1649
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
What
Adds a
/flightspage to the reflex-xy showcase and fixes three bugs that building it surfaced — one in the adapter's wire layer, two in the render client's in-place republish path.The showcase (
examples/reflex)/states/all— every aircraft on Earth (~14k) — and republishes the full figure each cycle: altitude-colored/speed-sized scatter with per-aircraft trails over the Natural Earth 50m coastline + borders (~80k points ofxy.segments), as one multi-MB binary blob, while pan/zoom stays smooth. Click-to-follow altitude trail, box-select altitude cross-filter.XY_FLIGHTS_MODE=region): one adsb.fi 250 nm circle (~600–900 aircraft), pollable down to 1 s.data/regenerate.py(stdlib-only) rebuilds all assets.Adapter fix: socket.io attachment cap
socket.io-parser's JS
Decoderrejects binary packets with >10 attachments; the resulting "parse error" closes the app's entire shared websocket, which reconnects, re-subs, re-sends the oversized payload, and loops forever with no console error. The namespace now falls back from the split-buffer layout to the joined single-blob payload when the split would exceed the cap, and boundsmsgreplies with anerrenvelope. Spec section added; regression test intests/reflex_adapter/test_socket_data_plane.py.Client fixes: in-place republish (
ChartView.updatePayload)Cannot read properties of null (reading '_fcId'). Reflex's frontend exception handler pattern-matches exactly that message class and responds withwindow.location.reload()— so the crash presented as selection resetting the zoom. The destroy path now drops the hover target it invalidates, and the hover draw treats null buffers as nothing-to-highlight.spec.titlewithout touching it ("0 aircraft · idle" over a live map). Both spec-swap paths now re-sync the title element + containeraria-label, forcing a re-layout when title presence changes.Republish survival contract (viewport/selection survive; hover re-resolves; title re-syncs) documented in
spec/design/reflex-integration.md.Testing
tests/test_ui_issue_regressions.py::test_republish_clears_stale_hover_and_syncs_title— browser probe, red on the un-fixed bundle, green nowtests/reflex_adapter/test_socket_data_plane.py::test_sub_over_attachment_limit_ships_single_blob(11/11 pass)scripts/render_smoke_nonumpy.pyfull probe list passespre-commit run --all-files,ruff check,ruff format --checkclean