fix(ledmatrix-flights): key the map background cache on display size - #243
Merged
Conversation
The cached map composite is already cropped to the display aspect ratio and resized to the panel before it is stored, but the memo was keyed on centre and zoom alone. Vegas narrows the display manager while it requests content, so the rotation and the ticker ask for the same view at different widths — and whichever rendered second was handed the other one's image. _render_map_image() copies that background, so the symptom is a whole frame at the wrong size, with aircraft and trails projected for the size it didn't get. This is why #231's "sizing needs no extra plumbing" only held for _latlon_to_pixel: the projection follows the display, the cached background didn't. The cache now holds one entry per size and clears them all when the centre or zoom moves. Keeping every size rather than a single slot keyed on size matters because the two paths alternate: a single slot would re-crop and re-resize on every Vegas/rotation swap. Also renames cached_map_bg -> cached_map_bgs, updating the config-reload test that asserts the cache is invalidated on change. Tests: three cases in test_vegas_map_parity.py covering the size after a narrower render, per-size cache retention, and the end-to-end frame size across a size switch. All three fail against the old memo. The existing parity tests can't catch this — they set map_bg_enabled = False, so the tile path never runs. Full suite: 21 passed, plus test_config_reload.py (15) and test_overhead_radius.py green. check_module_collisions.py: OK across 42 plugins. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016ZQZi3TiR77t2k5QjPix3E
Contributor
📝 WalkthroughWalkthroughChangesMap background cache update
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Display
participant _render_map_image
participant cached_map_bgs
participant tile_fetcher
Display->>_render_map_image: Request frame at display size
_render_map_image->>cached_map_bgs: Check size-specific composite
alt Cache hit
cached_map_bgs-->>_render_map_image: Return cached composite
else Cache miss
_render_map_image->>tile_fetcher: Fetch map tiles
tile_fetcher-->>_render_map_image: Return tile images
_render_map_image->>cached_map_bgs: Store composite by display size
end
_render_map_image-->>Display: Render frame at display size
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 8 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
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.
Summary
The map background cache was keyed on centre and zoom, but the image it stores has already been cropped to the display aspect ratio and resized to the panel — so the display size is part of its identity too. Vegas narrows the display manager while requesting content, so the rotation and the ticker ask for the same view at different widths, and whichever rendered second was handed the other one's image. The cache now keys on size as well.
Follow-up to #231, which is where the two paths started sharing a renderer.
Type of change
Plugin(s) affected
ledmatrix-flights(1.12.6 → 1.12.7)Related issues
Refs #231. Found while checking the CodeRabbit review comment on that PR — see "Notes for reviewer" for where that comment landed.
The bug
_get_map_background()stores its result after cropping to the display aspect ratio and resizing to the panel:but the memo that guards all of that only looked at centre and zoom:
Vegas narrows the display manager while it requests content, so
display_widthdiffers between the two paths — on a panel withvegas_width_pct: 50the ticker asks at half the width. Whichever path rendered first populated the single slot; the other got that image back at the wrong size._render_map_image()doesimg = map_bg.copy(), so the mismatch propagates to the whole frame: the returned image is the wrong size, and the aircraft, trails and centre marker on it were projected by_latlon_to_pixelfor the size it didn't get.This is the gap in #231's "sizing needs no extra plumbing" note. That's true of the projection — it reads
display_widthon every call — but not of the cached background, which was baked at one size and reused at another.Fix
One entry per size, dropped wholesale when the view moves:
Keeping every size rather than a single slot re-keyed on size is deliberate: the two paths alternate every rotation cycle, so a single slot would re-crop, re-resize and re-run the brightness/contrast/saturation enhancers on each Vegas↔rotation swap. Tiles come off the disk cache in that case, so it wouldn't hit the network — but it's avoidable work in the render path.
cached_map_bg→cached_map_bgs, which touches the config-reload test that asserts the cache is invalidated on change.Test plan
EMULATOR=true python3 run.py)scripts/dev_server.py)safetyCI job on this PRFour new cases in
test_vegas_map_parity.py:test_background_matches_the_requested_size_after_a_narrower_rendertest_each_size_is_still_cachedtest_moving_the_centre_drops_every_cached_sizetest_rendered_map_is_the_display_size_across_a_size_switchThey stub
_fetch_tilewith a gradient tile, so the compositing path actually runs without touching the network, andchdirto a tmp dir because the renderer dropsdebug_composite.png/debug_cropped.pngin the cwd.Verified load-bearing: reverting the memo to its old behaviour fails 3 of the 4. The existing parity tests can't catch this —
make_plugin()setsmap_bg_enabled = False, so the tile path never executes and the byte-identity assertion is satisfied by the memo regardless.test_vegas_map_parity.py: 21 passedtest_config_reload.py: 15 passedtest_overhead_radius.py: passedscripts/check_module_collisions.py: OK across 42 pluginsRequired for plugin changes
versioninplugins/<id>/manifest.json(1.12.6 → 1.12.7)class_nameinmanifest.jsonmatches the actual class inmanager.pyexactlyentry_pointmatches the real fileREADME.mdif config keys changed — N/A, no config keys changedconfig_schema.jsonis the source of truth for the web UI form — N/A, no new optionsplugins.json)Checklist
CONTRIBUTING.mdCONTRIBUTING.mdandCODE_OF_CONDUCT.mdNotes for reviewer
On the CodeRabbit comment from #231. It flagged
_get_map_background()being reachable from the render path as a stability risk and asked for tile fetching to move intoupdate(). That concern is real —_fetch_tiledoes a blockingrequests.get(url, timeout=10), and a cold cache can walk 16 tiles × 4 URL fallbacks — but it wasn't introduced by #231. Both call sites on the oldmainalready reached it from render code (_display_mapandget_vegas_content); #231 reduced that to one. It's mitigated in practice by the disk tile cache, the in-memory composite memo, and thedisable_on_cache_error/ >50%-failure circuit breakers, so it bites on first render rather than per frame.I've left that as-is — moving the fetch into
update()is a real restructure of a 200-line method and deserves its own PR. This PR fixes the different, concrete bug I found in the same memo while checking that comment.On the docstring-coverage pre-merge warning. Not addressed deliberately. The functions it counts are the four new test methods and a nested
fake_fetchhelper; this file documents intent at the class level and relies on sentence-style method names, and the three existing test classes have no method docstrings either. Adding them to clear the threshold would diverge from the file's idiom without helping a reader.Also spotted, not fixed here:
cached_pixels_per_mile(manager.py:156) is dead — set toNonein two places and never read or assigned. And_get_map_backgroundunconditionally writesdebug_composite.pnganddebug_cropped.pngto the process cwd on every cold render. Both are pre-existing and out of scope; happy to fold either in if you'd prefer.