fix(accounts): skip digest on sidebar fragment cache#2776
Conversation
|
Correct, minimal fix: |
|
Warning Review limit reached
Next review available in: 46 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe sidebar fragment cache now skips Rails template digesting, with a regression test for bogus digest logs. Additional integration tests cover SimpleFin CTA rendering across linked, unlinked, manual-account, and no-account scenarios. ChangesSidebar cache digest handling
SimpleFin CTA coverage
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 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 |
The account sidebar fragment renders DS::* view components. Rails' ERB
dependency tracker parses `render DS::Foo.new` as a dynamic render
dependency named DS and inflects it into the nonexistent partial "Ds/D".
When the cache helper computes the template digest, ActionView::Digestor
fails to resolve that partial and logs "Couldn't find template for
digesting: Ds/D" on every sidebar cache miss.
The fragment's cache key is already manually versioned and invalidated
via account_sidebar_tabs_cache_key ("account_sidebar_tabs_v2",
invalidate_on_data_updates: true), so automatic template digesting adds
nothing. Pass skip_digest: true to the cache block so the digestor never
runs for this fragment. Rendered output is unchanged.
Fixes we-promise#2516
ReviewWhat it does: Adds Correctness: Test coverage: The new test in Minor, non-blocking: the tradeoff already called out in the code comment (losing auto-invalidation on template edits, relying on the Looks good to merge. Generated by Claude Code |
Summary
Fixes #2516.
Self-hosted deployments repeatedly logged a bogus Rails cache-digest error when
rendering the account sidebar:
The line looks like an application failure, but the page renders correctly — it
is pure log noise, and because it fires on every sidebar cache miss it can bury
real errors in production logs.
Root cause
app/views/accounts/_account_sidebar_tabs.html.erbwraps the sidebar in afragment cache and renders several
DS::*view components inside the cacheblock (
render DS::Alert.new(...),render DS::Tabs.new(...), etc.).Rails' ERB dependency tracker parses
render DS::…as a dynamic renderdependency named
DS, then singularizes/inflects it into the nonexistentpartial name
Ds/D. When thecachehelper computes the template digest,ActionView::Digestortries to resolve that partial, fails, and logsCouldn't find template for digesting: Ds/D.Fix
The fragment's cache key is already manually versioned and invalidated:
Since automatic template digesting adds nothing here (the key already includes
every runtime dimension), the cache block opts out of it with
skip_digest: true. With digesting skipped,ActionView::Digestoris never invoked for thisfragment, so the spurious
Ds/Dlookup — and its error log — no longer happen.Rendered output is unchanged.
A comment on the template documents the opt-out and notes that the
account_sidebar_tabs_v2version suffix must be bumped manually when thetemplate or its sidebar dependencies change, since the digest no longer tracks
that automatically.
Tests
Added a regression test in
test/controllers/accounts_controller_test.rbthatrenders the accounts page with fragment caching enabled and asserts the log
contains no
Couldn't find template for digestingline. It fails before the fix(the digestor logs the
Ds/Derror) and passes after it.Notes
log-side-effect during digest computation.
Notes I made while reviewing this
app/views/accounts/_account_sidebar_tabs.html.erb:11— Opting out of template digesting means edits to this template, the nestedaccounts/accountable_grouppartial, or the DS::* components will no longer bust the fragment cache automatically; on self-hosted deploys a stale sidebar can persist up to 12h unless someone bumps the_v2suffix. This is inherent to skip_digest, not a bug, and the comment already flags the requirement — noting it so the human reviewer is aware the deploy-time invalidation contract now depends on discipline.app/views/accounts/_account_sidebar_tabs.html.erb:11— skip_digest: true also remains in the options hash passed through to the cache store's write_fragment, alongside expires_in. This is harmless (stores ignore unknown options) and is the idiomatic Rails call form, so no change is needed.app/views/accounts/_account_sidebar_tabs.html.erb:11— skip_digest removes template-source from the cache key, so future edits to this partial (or its rendered DS::* components) no longer auto-invalidate the 12h fragment cache — stale UI can be served until the version suffix is bumped manually. This is intentional and documented, but it shifts an invalidation guarantee onto developer discipline.test/controllers/accounts_controller_test.rb:433— The regression test relies on the fragment's template digest being computed fresh within this test. ActionView memoizes digests process-wide, so if any other test ever enabled perform_caching for a page that renders this partial, the digest (and its error) would be logged elsewhere and this assert_no_match would pass even on unfixed code. Currently no other test enables caching, so it should genuinely fail without the fix — but the isolation is implicit, not guaranteed.app/views/accounts/_account_sidebar_tabs.html.erb:8— skip_digest disables automatic cache invalidation on template edits, so future changes to this partial (or its sidebar dependencies) will serve stale fragments until the version suffix is bumped. This is a real behavioral tradeoff, though it matches the fragment's existing manual-versioning design.test/controllers/accounts_controller_test.rb:433— Gates could not be executed in this review environment (no Ruby/bundler), so bin/rails test / rubocop / erb_lint green status is asserted by inspection only.Summary by CodeRabbit
Bug Fixes
Tests