perf: precompute collection_contributor_dependency filtered variants (IN-1196) - #4405
perf: precompute collection_contributor_dependency filtered variants (IN-1196)#4405gaspergrom wants to merge 1 commit into
Conversation
…(CM-IN-1196) Extends the Phase 1/2 collection precompute work to cover the contributor-dependency widget's real filtered traffic (86% of production requests carry a date range, 98% of those match one of the 8 fixed date-picker presets). - Adds a 16-variant precomputed matrix (8 date presets x 2 includeCollaborations states) for collection_contributor_dependency, replacing the old v1 single-variant (unfiltered-only) precomputed path. - Splits collection_contributor_dependency_copy and collection_contributors_leaderboard_copy each into 8 presetKey-scoped copy pipes (past90days, past180days, past365days, previousQuarter, previousYear, previous5years, previous10years, allTime), mirroring the existing collection_insights_aggregate_copy pattern. - Rewrites collection_contributor_dependency_copy_ds and collection_contributors_leaderboard_copy_ds as append+snapshotId datasources so each daily run doesn't clobber the prior day's rows mid-query. - Updates the serving pipes (collection_contributor_dependency.pipe, collection_contributors_leaderboard.pipe) to route between the precomputed path (requires presetKey, no repos/platform/activity_type, limit=100) and the live GROUP BY path at template-render time, since ClickHouse evaluates all UNION ALL branches regardless of WHERE guards. - Deletes the superseded v1 collection_contributor_dependency_copy.pipe / collection_contributor_dependency_copy_ds.datasource. Deployed and verified against production Tinybird (staging then production) - all 16 contributor-dependency variants and 16 leaderboard variants confirmed present with matching row counts and correct data for a real collection (cncf). Deploy order: must merge/deploy before the companion insights PR, since that PR sends presetKey values that must already resolve to a live pipe. Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
PR SummaryMedium Risk Overview Leaderboard & bus-factor: Eight Insights aggregate: New Supersedes the v1 single-variant contributor-dependency precompute with the full 16-variant matrix aligned to the frontend picker contract. Reviewed by Cursor Bugbot for commit e08c160. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e08c160. Configure here.
|
|
||
| SQL > | ||
| % | ||
| {% if defined(presetKey) and not defined(repos) and not defined(startDate) and not defined(endDate) and not defined(platform) and not defined(activity_type) and Int32(limit, 100) == 100 %} |
There was a problem hiding this comment.
Precomputed path blocked by dates
High Severity
The precomputed-path guard requires startDate and endDate to be absent, but the pipe docs say those params are ignored when presetKey is present, and the sibling collection_contributors_leaderboard.pipe does not check them. Once the companion frontend sends presetKey with the matching date range (the common traffic shape), this widget stays on the expensive live path and the optimization never activates.
Reviewed by Cursor Bugbot for commit e08c160. Configure here.
| now64(3) AS updatedAt | ||
| FROM collection_insights_aggregate_copy_project_counts c | ||
| INNER JOIN collection_insights_aggregate_copy_activities a ON a.collectionSlug = c.collectionSlug | ||
| GROUP BY c.collectionSlug, c.projectCount, c.avgHealthScore |
There was a problem hiding this comment.
Empty collections dropped from aggregate
Medium Severity
The final copy node INNER JOINs project counts to activity rows, so collections with projects but no qualifying contributors never get a row in collection_insights_aggregate_copy_ds. The old live pipe always returned one row via scalar subqueries (with uniqueContributorCount 0). The serving pipe has no live fallback, so those collections now return empty instead of project count and health score.
Reviewed by Cursor Bugbot for commit e08c160. Configure here.
| TYPE copy | ||
| TARGET_DATASOURCE collection_contributor_dependency_copy_ds | ||
| COPY_MODE append | ||
| COPY_SCHEDULE 15 2 * * * |
There was a problem hiding this comment.
allTime copy schedule race
High Severity
collection_contributor_dependency_copy_allTime and collection_contributors_leaderboard_copy_allTime both run at 15 2 * * *. The dependency pipe reads upstream rows with snapshotId = max(snapshotId). Once earlier leaderboard presets have written today's snapshot, a still-running allTime leaderboard job makes that lookup return zero rows, so the dependency variant is missing until a later successful run—the same class of gap already seen for past365days in the test plan.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit e08c160. Configure here.
There was a problem hiding this comment.
Pull request overview
Precomputes collection contributor metrics for fixed date presets to reduce expensive live Tinybird aggregations.
Changes:
- Adds preset-specific leaderboard and dependency materializations.
- Routes eligible requests to precomputed snapshots.
- Adds aggregate collection insights precomputation and supporting datasources.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
collection_insights_aggregate.pipe |
Serves precomputed aggregates. |
collection_insights_aggregate_copy.pipe |
Builds daily collection aggregates. |
collection_contributors_leaderboard.pipe |
Routes live/precomputed leaderboards. |
collection_contributors_leaderboard_copy_past90days.pipe |
Precomputes 90-day leaderboard. |
collection_contributors_leaderboard_copy_past180days.pipe |
Precomputes 180-day leaderboard. |
collection_contributors_leaderboard_copy_past365days.pipe |
Precomputes 365-day leaderboard. |
collection_contributors_leaderboard_copy_previousQuarter.pipe |
Precomputes previous-quarter leaderboard. |
collection_contributors_leaderboard_copy_previousYear.pipe |
Precomputes previous-year leaderboard. |
collection_contributors_leaderboard_copy_previous5years.pipe |
Precomputes five-year leaderboard. |
collection_contributors_leaderboard_copy_previous10years.pipe |
Precomputes ten-year leaderboard. |
collection_contributors_leaderboard_copy_allTime.pipe |
Precomputes all-time leaderboard. |
collection_contributor_dependency.pipe |
Routes live/precomputed dependency results. |
collection_contributor_dependency_copy_past90days.pipe |
Derives 90-day dependency results. |
collection_contributor_dependency_copy_past180days.pipe |
Derives 180-day dependency results. |
collection_contributor_dependency_copy_past365days.pipe |
Derives 365-day dependency results. |
collection_contributor_dependency_copy_previousQuarter.pipe |
Derives previous-quarter dependency results. |
collection_contributor_dependency_copy_previousYear.pipe |
Derives previous-year dependency results. |
collection_contributor_dependency_copy_previous5years.pipe |
Derives five-year dependency results. |
collection_contributor_dependency_copy_previous10years.pipe |
Derives ten-year dependency results. |
collection_contributor_dependency_copy_allTime.pipe |
Derives all-time dependency results. |
collection_insights_aggregate_copy_ds.datasource |
Defines aggregate storage. |
collection_contributors_leaderboard_copy_ds.datasource |
Defines snapshot leaderboard storage. |
collection_contributor_dependency_copy_ds.datasource |
Defines snapshot dependency storage. |
Comments suppressed due to low confidence (1)
services/libs/tinybird/pipes/collection_contributors_leaderboard.pipe:160
- This data branch has the same partial-snapshot race as the count branch: global
max(snapshotId)advances when any preset writer completes, making unfinished presets temporarily return an empty leaderboard. Resolve the latest snapshot for the requested preset instead.
snapshotId = (SELECT max(snapshotId) FROM collection_contributors_leaderboard_copy_ds)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| c.avgHealthScore AS avgHealthScore, | ||
| now64(3) AS updatedAt | ||
| FROM collection_insights_aggregate_copy_project_counts c | ||
| INNER JOIN collection_insights_aggregate_copy_activities a ON a.collectionSlug = c.collectionSlug |
| SELECT any(totalContributorCount) AS count | ||
| FROM collection_contributors_leaderboard_copy_ds | ||
| WHERE | ||
| snapshotId = (SELECT max(snapshotId) FROM collection_contributors_leaderboard_copy_ds) |
| totalContributorCount | ||
| FROM collection_contributor_dependency_copy_ds | ||
| WHERE | ||
| snapshotId = (SELECT max(snapshotId) FROM collection_contributor_dependency_copy_ds) |
| WHERE | ||
| rank <= 100 | ||
| AND presetKey = 'past90days' | ||
| AND snapshotId = (SELECT max(snapshotId) FROM collection_contributors_leaderboard_copy_ds) |
| WHERE | ||
| rank <= 100 | ||
| AND presetKey = 'past180days' | ||
| AND snapshotId = (SELECT max(snapshotId) FROM collection_contributors_leaderboard_copy_ds) |
| (SELECT memberId, groupUniqArray(role) AS roles FROM maintainers_roles_copy_ds GROUP BY memberId) mr | ||
| ON mr.memberId = r.memberId |
| (SELECT memberId, groupUniqArray(role) AS roles FROM maintainers_roles_copy_ds GROUP BY memberId) mr | ||
| ON mr.memberId = r.memberId |
| (SELECT memberId, groupUniqArray(role) AS roles FROM maintainers_roles_copy_ds GROUP BY memberId) mr | ||
| ON mr.memberId = r.memberId |
| (SELECT memberId, groupUniqArray(role) AS roles FROM maintainers_roles_copy_ds GROUP BY memberId) mr | ||
| ON mr.memberId = r.memberId |
|
|
||
| SQL > | ||
| % | ||
| {% if defined(presetKey) and not defined(repos) and not defined(startDate) and not defined(endDate) and not defined(platform) and not defined(activity_type) and Int32(limit, 100) == 100 %} |
|
Closing without merging — abandoning this optimization work per decision to revert all Tinybird performance-optimization changes (Phases 1-3) and start fresh. |


Summary
includeCollaborationsstates) forcollection_contributor_dependency, replacing the old v1 single-variant (unfiltered-only) precomputed path.collection_contributor_dependency_copyandcollection_contributors_leaderboard_copyeach into 8presetKey-scoped copy pipes (past90days,past180days,past365days,previousQuarter,previousYear,previous5years,previous10years,allTime), mirroring the existingcollection_insights_aggregate_copypattern.collection_contributor_dependency_copy_dsandcollection_contributors_leaderboard_copy_dsas append +snapshotIddatasources so a daily run doesn't clobber the prior day's rows mid-query.collection_contributor_dependency.pipe,collection_contributors_leaderboard.pipe) to route between the precomputed path (requirespresetKey, norepos/platform/activity_type,limit=100) and the liveGROUP BYpath at template-render time — ClickHouse evaluates allUNION ALLbranches regardless ofWHEREguards, so routing has to happen at render time, not query time.collection_contributor_dependency_copy.pipe/collection_contributor_dependency_copy_ds.datasource.Why
At collection scale (e.g.
cncfhas 149,677 distinct contributors), the liveGROUP BY af.memberIdpath for the contributor-dependency widget was triggering Tinybird production rate-limit/concurrency alerts under load. The original precompute only covered fully-unfiltered requests, but real traffic is overwhelmingly filtered by one of the date picker's 8 fixed presets — so the fast path almost never activated. This closes that gap.Changes
services/libs/tinybird/pipes/collection_contributor_dependency.pipe— adds precomputed-path routing node, updated DESCRIPTION.services/libs/tinybird/pipes/collection_contributors_leaderboard.pipe— same routing pattern (was already partially split in an earlier phase; this makes the presetKey contract consistent with contributor-dependency).services/libs/tinybird/pipes/collection_insights_aggregate.pipe— minor consistency update.*_copy_<presetKey>.pipefiles (8 for contributor-dependency, 8 for leaderboard).collection_insights_aggregate_copy.pipe— new copy pipe for that datasource.*_copy_ds.datasourcefiles (append + snapshotId schema).collection_contributor_dependency_copy.pipe(v1, superseded).Deploy order
Must deploy before the companion insights PR (#2041) — that PR sends
presetKeyvalues that need to already resolve against a live pipe here.Test plan
tbCLIcncf)past365dayszero-rows gap post-deploy (one pipe instance's daily cron hadn't fired yet after the redeploy reset its run history) — manually triggered, verified correct data end-to-endJIRA: IN-1196