Repository navigation
Conversation
The server marks its aircraft feed dirty once per frame received, whatever the frame carried, and that dirty flag is what drives the 1 Hz websocket broadcast to the map. Skipping empty frames therefore made the fleet's silence look like a dead socket: with nothing in any node's beam the broadcast stops, and after 12 s the client's watchdog force-closes a healthy connection and drops the map to HTTP polling. Real nodes already send empty frames (an all-empty detection array is a valid v1 frame), so this also removes a behavioural difference between the synthetic fleet and the hardware it stands in for, which is what made the POLL badge mean different things on testmap and on the production map. Cost: the send rate is now the configured one rather than whatever fraction of nodes happened to see something, so staging runs at the 50 fps its compose file already describes, and empty frames reach the server's archive buffer like any other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
retina-servermarks its aircraft feed dirty once per frame received, inservices/tasks/frame_loop.py, whatever the frame carried. That flag gates the1 Hz websocket broadcast to the map, so the socket is fed by frames arriving,
not by aircraft existing.
Skipping empty frames made the fleet's silence indistinguishable from a dead
connection. With nothing in any node's beam the broadcast stops, and after 12 s
the map client's watchdog force-closes a healthy websocket and falls back to
HTTP polling, showing
POLLin the toolbar. It shows up on an empty world, astopped fleet, and a local stack before the fleet comes up.
Real nodes already send empty frames:
delay/doppler/snr/adsb_hexcarryonly a
max_lengthin the v1 contract, so an all-empty frame is valid and thehardware sends one per CPI. This removes a behavioural difference between the
synthetic fleet and the hardware it stands in for, which is why
POLLmeantsomething different on testmap than on
map.retina.fm.What
Drops the
if frame.get("delay")guard inrun_simulation_loop. Two testsdrive one pass of the loop against a stub connection and a world in which
nothing is ever in a beam.
Cost
The send rate is now the configured rate rather than whatever fraction of nodes
happened to see something, so staging runs at the 50 fps its compose file
already describes rather than below it. Empty frames reach the server's archive
buffer like any other; there is no empty-frame fast path in
process_one_frame, though every stage it runs iterates over empty lists.Verification
pytest: 213 passed.pre-commit run --all-filesclean. Both new tests wereconfirmed to fail with the guard restored.
Needs a submodule pointer bump in
retina-serverbefore staging picks it up.🤖 Generated with Claude Code