Skip to content

fix(news): keep the rendered ticker when the headlines have not changed - #282

Open
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/news-skip-unchanged-rebuild
Open

fix(news): keep the rendered ticker when the headlines have not changed#282
ChuckBuilds wants to merge 1 commit into
mainfrom
fix/news-skip-unchanged-rebuild

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

The problem

update() discarded the scroll image and the rendered headline images on every refresh, whether or not the headlines had changed:

if self.current_headlines:
    self.rotation_count = 0
    self._headline_image_cache = {}
    ...
    self.scroll_helper.clear_cache()

An RSS feed mostly returns what it returned last time, so a still-correct strip was thrown away and the next Vegas fetch rebuilt it — measured on a 512×64 rig at 427 ms for a 10220×64 px image, on the render thread. Observed three times in forty minutes at 431, 427 and 424 ms. That is one of the sources of the marquee's visible stutter.

The fix

The discard is gated on the headline set actually differing, keyed on feed name and title in order. Order is part of the key because rotation reorders the list without changing its contents, and that does need a rebuild.

The risk, and what guards it

The opposite failure — holding a strip that should have been replaced — is worse than the cost it saves. Two paths invalidate the drawing without touching the headlines, and both clear the signature explicitly:

  • a font or colour change (_apply_font_customization path) — same headlines, different rendering
  • a feed-set change — headlines cleared, page window reset

Most of the test is about what must still rebuild rather than about the saving: changed title, changed feed name, added, removed, reordered, font/colour change, feed-set change. A changed link alone correctly does not rebuild, since the strip isn't drawn from it.

On the tests

Two rounds of mutation testing, each of which caught a gap I would otherwise have shipped:

  1. Deleting the guard entirely was missed — the test helper mirrored the guard instead of exercising it. Fixed by reading update() through the AST: the scroll-cache discard must sit inside a signature-guarded branch, and no unguarded discard may remain.
  2. Deleting the signature store was still missed — that silently reverts to rebuilding every time. No correctness bug, just the saving quietly gone. Now asserted too.

All six mutants are caught: guard removed, signature never stored, either reset path dropped, signature ignoring order, signature ignoring the title.

Measured on hardware

Deployed to the rig it was diagnosed on, 43-minute window:

  • 41 updates produced 3 rebuilds. Before, all 41 would have discarded the strip.
  • Fetch times went 421ms → 9ms → 418ms. The 9 ms is the cache holding; the 418 ms is a genuine headline change, which should rebuild.
  • Content stays fresh — three rebuilds means new headlines reached the panel during the window.

Honest framing of the size: the win is partial, because news headlines genuinely change at roughly the same cadence the scroll strip is extended. It removes the wasted rebuilds, not the legitimate ones.

Safety harness clean.

update() discarded the scroll image and the rendered headline images on
every refresh, whether or not the headlines had changed. An RSS feed
mostly returns what it returned last time, so a still-correct strip was
thrown away and the next Vegas fetch rebuilt it -- measured on a 512x64
rig at 427ms for a 10220x64 image, on the render thread. Observed three
times in forty minutes at 431ms, 427ms and 424ms, which is where the
marquee's stutter came from.

The discard is now gated on the headline set actually differing, keyed on
feed name and title in order. Order is part of the key because rotation
reorders the list without changing its contents, and that does need a
rebuild.

The risk of this change is the opposite failure -- holding a strip that
should have been replaced -- so the paths that invalidate the drawing
without touching the headlines clear the signature explicitly: the
font/colour reload and the feed-set change. Both are asserted.

Most of the test is about what must still rebuild rather than the saving:
changed title, changed feed, added, removed, reordered, font change, feed
change. It also reads update() through the AST, because a test that
mirrors the guard passes with the guard deleted -- confirmed by mutation
testing before the structural check was added.

Mutation-checked, all six caught: guard removed, signature never stored,
either reset path dropped, signature ignoring order, signature ignoring
the title.

Harness clean.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01Udr6MfaFLUPhX5Fgo67Jf5
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7e98800b-4be3-401e-88a9-08dd24fe8519


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

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 45 complexity

Metric Results
Complexity 45

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.

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