Skip to content

fix(leaderboard): move missing-logo downloads off the render thread - #271

Merged
ChuckBuilds merged 2 commits into
fix/leaderboard-logo-cachefrom
claude/ledmatrix-logo-cache-fix-4xer77
Aug 12, 2026
Merged

fix(leaderboard): move missing-logo downloads off the render thread#271
ChuckBuilds merged 2 commits into
fix/leaderboard-logo-cachefrom
claude/ledmatrix-logo-cache-fix-4xer77

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

What

Addresses the CodeRabbit review comment on #270: _get_team_logo ran from
layout construction inside display() (the render thread the Vegas scroll
depends on), and on a cache miss it called download_missing_logo — a
network request that could stall the scroll. This targets that PR's branch
directly.

  • _get_team_logo now only ever reads a local file; it never invokes the
    downloader.
  • New ImageRenderer.download_missing_logos(leaderboard_data) backfills any
    missing team logo files from the network. manager.update() calls it
    after fetching standings — off the render thread, alongside the plugin's
    other network I/O.
  • The existing mtime-keyed logo cache already picks up a file that appears
    after the fact, so a logo downloaded in update() becomes visible on the
    next rebuild with no further wiring needed.

Skipped

The review comment also asked to update test_logo_cache.py#L97-115. Those
lines test _cached_prepared_logo's generic cache-miss-is-retried behavior
via a synthetic load callback — they never call _get_team_logo or the
downloader, so they were not exercising the code path this fix changes and
didn't need updating. Instead, added new coverage that directly targets the
fixed behavior: _get_team_logo never invokes the downloader on a miss, and
download_missing_logos (the update() path) does, with a subsequently
written local file becoming visible on a later render.

Tests

plugins/ledmatrix-leaderboard/test_logo_cache.py — all checks pass,
including the two new sections covering this fix.

Bumped manifest.json to 1.3.2 per repo convention; pre-commit hook synced
plugins.json.


Generated by Claude Code

_get_team_logo ran from layout construction inside display(), and on a
cache miss it invoked download_missing_logo -- a network call on the
render thread the Vegas scroll depends on. Missing logos are now
backfilled by a new download_missing_logos(), called from update()
instead; _get_team_logo only ever reads local files, and a backfilled
logo becomes visible on the next rebuild via the existing mtime-keyed
cache.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RRsTMmLUcpd8tpN1qciEgC
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a0f56175-b4e3-4940-b322-7889a743b3fb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

codacy-production Bot commented Aug 12, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 7 complexity

Metric Results
Complexity 7

View in Codacy

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.

Codacy flagged an unused local in the new test coverage.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RRsTMmLUcpd8tpN1qciEgC
@ChuckBuilds
ChuckBuilds merged commit 1524979 into fix/leaderboard-logo-cache Aug 12, 2026
4 checks passed
ChuckBuilds added a commit that referenced this pull request Aug 12, 2026
* perf(leaderboard): decode each logo once, not once per rebuild

Image.open defers the PNG decode to first access, so the decode landed
inside _prepare_logo's convert(), with a LANCZOS resize behind it -- for
every team, on every rebuild, for files that had not changed. Measured
on the real asset directory: 25 logos cost 276ms cold and 0.3ms warm.

It matters more than a normal cache miss because leaderboard scroll
content is generated on the render thread. The adapter's capture path
needs the shared canvas, so it cannot be prepared in the background
(render_pipeline.drain_deferred explains why), and the cost lands
directly on the Vegas scroll as stutter.

Keyed on path and mtime, so a logo the downloader backfills is picked up
rather than served stale. A missing file is deliberately not cached:
remembering it as absent would keep a logo downloaded moments later
invisible until restart.

Honest scope: this does not fix the 3.2s freeze that led here. That one
is still present with this change in place, and the watchdog work on the
core side now shows why it was never caught -- it holds the GIL. This
removes a real and separate cost on the same path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5

* fix(leaderboard): move missing-logo downloads off the render thread (#271)

* fix(leaderboard): move missing-logo downloads off the render thread

_get_team_logo ran from layout construction inside display(), and on a
cache miss it invoked download_missing_logo -- a network call on the
render thread the Vegas scroll depends on. Missing logos are now
backfilled by a new download_missing_logos(), called from update()
instead; _get_team_logo only ever reads local files, and a backfilled
logo becomes visible on the next rebuild via the existing mtime-keyed
cache.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RRsTMmLUcpd8tpN1qciEgC

* test(leaderboard): drop unused variable in logo cache test

Codacy flagged an unused local in the new test coverage.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RRsTMmLUcpd8tpN1qciEgC

---------

Co-authored-by: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants