fix: paginate summary aggregation to avoid 500-item truncation (#337) - #339
Conversation
|
Warning Review limit reached
More reviews will be available in 50 minutes and 25 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?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 credits. 🚦 How do rate 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 see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthrough
ChangesPagination fix for scan summary aggregation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
|
Summary:
|
Review — no blockersI reviewed the pagination fix against the underlying store semantics and ran the tests. No blocking issues found. Correctness ✅The loop matches the store's continuation contract exactly:
Tests ✅Verified locally with Go 1.25:
Non-blocking note (no change required)This trades "bounded-but-wrong" for "correct-but-unbounded": on a cluster with N summaries the aggregation now issues ⌈N/500⌉ sequential list pages and, in the LGTM. |
ConfigurationScanSummaryStorage.GetList and VulnerabilitySummaryStorage.GetList built their cluster-wide per-namespace aggregations from a single realStore.GetList call. The underlying store caps each page at a default limit of 500 objects and returns a continuation token that was never consumed, so on clusters with more than 500 stored summaries the aggregation only covered the first page: namespaces beyond it silently disappeared and per-namespace severity counters were wrong. Both GetList methods now follow the continuation token in a loop, accumulating every page before aggregating. The token is a monotonic SQLite rowid, so paging is duplicate- and skip-free, and the loop terminates when the store returns an empty token (only set when a page is full). Adds regression tests that create 500 objects in one namespace plus 200 in a second (so the second namespace lives entirely on page 2) and assert both namespaces are present and all 700 objects are aggregated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Docs-exempt: bug fix to internal summary aggregation pagination, no documented behavior changed Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
0a83362 to
ab84de3
Compare
|
Summary:
|
Summary
Fixes #337 — on-the-fly summary aggregations silently truncated to the first 500 objects on larger clusters.
ConfigurationScanSummaryStorage.GetListandVulnerabilitySummaryStorage.GetListbuild cluster-wide, per-namespace summaries by listing the underlyingworkloadconfigurationscansummaries/vulnerabilitymanifestsummaries. The storage layer (storage.go) applies a hard-coded defaultLimit = 500when a client lists without an explicit limit and returns a continuation token — but these two aggregators issued a singlerealStore.GetListcall and never consumed the token.Result on clusters with >500 stored objects:
high: 0via LIST while a direct GET returns the real count);Fix
Both
GetListmethods now follow the continuation token in a loop, accumulating every page before aggregating. The token is a monotonic SQLiterowid(rowid > :cont ORDER BY rowid), so paging is duplicate- and skip-free, and the loop terminates when the store returns an empty token (only set when a page is full).Tests
Added
..._GetList_Paginationregression tests for both storages: create 500 objects in one namespace + 200 in a second (so the second namespace lives entirely on page 2), then assert both namespaces are present and all 700 objects are aggregated. Verified these fail against the pre-fix single-call code (1 namespace / count 500) and pass with the fix.Scope
kubescape/prometheus-exporter(the other consumer named in the issue) is handled separately in fix(api): follow continuation token when listing summaries (kubescape/storage#337) prometheus-exporter#52.🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests