Skip to content

Bump retina-tracker: bounded track history - #314

Merged
jehanazad merged 1 commit into
mainfrom
fix/tracker-history-bounds
Sep 6, 2026
Merged

jehanazad merged 1 commit into
mainfrom
fix/tracker-history-bounds

Conversation

@jehanazad

Copy link
Copy Markdown
Contributor

Summary

Submodule bump of libs/retina-tracker to d172e3e (offworldlabs/retina-tracker#25, merged): per-track history buffers become bounded ring buffers (TRACK_HISTORY_MAX = 600) and the never-read completed_tracks archive shrinks from 5000 to 50 tracks per node.

Why

A robustness audit of the long-running server found these two stores as the only sustained-growth and largest never-read plateau in the process: Track.history grew ~1.5 MiB per track-hour with no cap, and completed_tracks held up to 149 MiB of dead Track objects per node pipeline that nothing in the backend reads. Live RSS on the test droplet climbs ~8 MB/min for the first hour after every restart with no plateau in sight.

Server impact

No backend code change. The deepest server reader (get_recent_detections, N2_TRACK_HISTORY_MAX = 20) is 30× inside the cap. Server test suite run against the new library: 2971 outcomes, 0 failures; pre-commit clean.

Post-deploy check

process_rss_mb on /api/admin/metrics should plateau within the first hour instead of climbing linearly.

🤖 Generated with Claude Code

Picks up retina-tracker fix/bounded-track-history, which makes the five
`Track.history` buffers deque(maxlen=600) and drops
MAX_COMPLETED_TRACKS from 5000 to 50.

Both stores are per Tracker, and this server holds one Tracker per node
pipeline for days at a time, so the fleet multiplies them by ~60. The
history lists were appended on every processed frame on both the update
and the coast path with no cap, at a measured 450 B per entry -- 1.55
MiB per track-hour at 1 Hz for any track that never satisfies
should_delete. The completed-track archive held 5000 whole retired
Tracks with their history attached, a ~149 MiB per-node ceiling reached
by ordinary track churn within the hour, and nothing here reads it:
get_confirmed_tracks and completed_tracks have zero call sites in the
backend.

No backend change is needed. Nothing here touches a history attribute
directly; the readers go through get_recent_detections, and the deepest
of them asks for N2_TRACK_HISTORY_MAX samples, which is 20 against a cap
of 600. Its reverse-scan semantics are unchanged, including the skip
over the None measurements mark_missed appends -- which is what
frame_processor's freshness signal depends on.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown

Claude finished @jehanazad's task in 2m 3s —— View job


Review: Bump retina-tracker: bounded track history

  • Gather context (diff, submodule bump target)
  • Understand the request (code review)
  • Review the submodule bump and its backend impact
  • Post review feedback

Scope: This PR is a pure submodule pointer bump (libs/retina-tracker 79db48c → d172e3e, +1/-1). No backend source changed. Note: I don't have network access in this sandbox to check out the submodule at the new commit, so I couldn't diff the tracker library's actual code — this review is based on the PR description plus a check of how retina-server's backend consumes the library.

Verified against the backend:

  • completed_tracks — confirmed zero references anywhere in backend/ (or the rest of this repo). The PR's claim that nothing here reads it holds up; shrinking it from 5000→50 is safe from this repo's perspective.
  • get_recent_detections / N2_TRACK_HISTORY_MAX (backend/config/constants.py:85, used in backend/services/frame_processor.py:317) — capped at 20 samples, well inside the new 600-sample ring buffer. backend/pipeline/passive_radar.py:160,572 and backend/services/tasks/analytics_refresh.py:536 also only pull small recent slices via this same method, not the raw history length.
  • track.history.get("measurements") in backend/services/aircraft_feed.py:551 only reads the latest entry (next(reversed(meas), ...)), so it's unaffected by the new cap.
  • CI (CI workflow) is green on this PR.

Minor observation (non-blocking): the backend has its own, unrelated TRACK_HISTORY_MAX = 60 in backend/config/constants.py:248 ("Rolling position buffer per aircraft" for the map trail, state.track_histories). This is a pre-existing, separate constant from the tracker library's new TRACK_HISTORY_MAX = 600 — not touched by this PR, but the identical name across two codebases is a mild trap for future greps/debugging. Not worth renaming for this PR; just flagging so nobody conflates the two when investigating memory or trail-length issues later.

No issues found that would block merging. The change looks correctly scoped and the "no backend code change" claim checks out against actual usage sites.

@jehanazad
jehanazad merged commit 65731b4 into main Sep 6, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant