Skip to content

perf(stats): bound the review-volume trend's own-ledger query by an index, not a full scan - #4727

Merged
JSONbored merged 1 commit into
mainfrom
perf/bound-review-volume-trend-audit-events-scan-4723
Jul 10, 2026
Merged

perf(stats): bound the review-volume trend's own-ledger query by an index, not a full scan#4727
JSONbored merged 1 commit into
mainfrom
perf/bound-review-volume-trend-audit-events-scan-4723

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • loadOwnLedgerDayRows (src/services/public-review-volume-trend.ts, shipped in feat(stats): add a public review-volume/filtered-rate trend and 2 more hero sparklines #4722) computed each PR's true first-publish date via MIN(created_at) over the entire github_app.pr_public_surface_published history before discarding anything outside the trailing 8-week trend window — an effectively-unbounded scan that grows with the whole audit_events table on every /v1/public/stats request.
  • Splits it into two index-backed steps instead of one unbounded scan:
    1. recent_keys — which PRs had any publish event in the trailing window. Uses the existing audit_events_type_created_idx (event_type, created_at).
    2. true_first_seen — for just those candidates, the TRUE first-publish date across the PR's full history. Uses a new audit_events_target_key_created_idx (target_key, created_at) (migrations/0142).
  • Confirmed via EXPLAIN QUERY PLAN against the real migrated schema that both steps now SEARCH ... USING INDEX rather than SCAN the table.

Closes #4723.

Why not a simpler prefilter

A naive single-pass fix (filter raw created_at >= sinceIso before the MIN()) would have been a correctness regression, not just a perf tweak: a PR whose true first-publish is outside the window, but which got a legitimate re-publish (e.g. a fresh push triggering re-review) inside the window, would resolve to the wrong, too-recent date and get misattributed to that week instead of correctly excluded. This is exactly why #4723 flagged the naive fix as unsafe rather than just landing it under review-cycle time pressure.

The new regression test proves the two-step version handles this correctly — verified failing against the naive single-pass version first (temporarily reverted, confirmed the test genuinely catches the bug, restored the fix).

Scope

  • The PR title follows type(scope): short summary Conventional Commit format.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves.

Validation

  • git diff --check
  • npm run actionlint — skipped, no .github/workflows/** changes.
  • npm run typecheck
  • npm run db:migrations:check — 145 migrations OK, contiguous through 0142.
  • npm run db:schema-drift:checksrc/db/schema.ts matches migrations/.
  • npm run test:coverage (targeted, not the full unsharded suite — see Notes) locally; the rewritten loadOwnLedgerDayRows is 100% stmts/branch/funcs/lines.
  • npm run test:workers — skipped, no Worker-specific code beyond what typecheck/coverage already cover.
  • npm run build:mcp / npm run test:mcp-pack — skipped, no MCP package changes.
  • npm run ui:openapi:check / ui:lint / ui:typecheck / ui:test / ui:build — skipped, no apps/gittensory-ui/** changes; no API response shape changed, only the query computing it.
  • npm audit --audit-level=moderate
  • New or changed behavior has unit/integration tests — see Notes.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth/cookie/CORS/GitHub App/Cloudflare/session changes include negative-path tests — N/A, none touched.
  • API/OpenAPI/MCP behavior is updated and tested where needed — no API shape change; the existing reviewVolumeTrend field's values are now computed by a query with the same output, verified by the full existing test suite passing unchanged plus the new regression test.
  • UI changes use live API data — N/A, no UI changes.
  • UI Evidence section — N/A, backend-only change, no visible UI surface.
  • Public docs/changelogs are updated where needed; no changelog edit (not a release-prep PR).

Notes

New migration: migrations/0142_audit_events_target_key_created_idx.sql adds audit_events_target_key_created_idx (target_key, created_at) — a lookup index (not unique; target_key repeats once per lifecycle event on a PR). src/db/schema.ts's auditEvents table definition updated to match.

Test coverage: extended test/unit/public-review-volume-trend.test.ts with a new end-to-end regression test seeding a PR whose true first-publish is 20 weeks old (well outside the 8-week window) with a re-publish event in the current week, asserting it's excluded from every bucket — the exact scenario a naive prefilter gets wrong. All 9 pre-existing tests in the file (and the 2 integration tests exercising the same code path via GET /v1/public/stats) pass unchanged against the rewritten query, confirming it's output-equivalent for every previously-tested scenario.

Verified via EXPLAIN QUERY PLAN (not committed, a local one-off check against the real migrated schema): both recent_keys and true_first_seen show SEARCH ... USING INDEX, confirming the fix achieves its stated goal.

…ndex, not a full scan (#4723)

loadOwnLedgerDayRows previously computed each PR's true first-publish
date via MIN(created_at) over the ENTIRE github_app.pr_public_surface_published
history before discarding anything outside the trailing 8-week window --
an unbounded scan that grows with the whole audit_events table.

Splits it into two index-backed steps instead: which PRs had any publish
event in the trailing window (existing event_type+created_at index), then
each candidate's true first-publish across its FULL history (new
target_key+created_at index, migrations/0142). Confirmed via EXPLAIN QUERY
PLAN that both steps now SEARCH an index rather than SCAN the table.

A naive single-pass prefilter (raw created_at >= sinceIso before the
MIN()) would have been a correctness regression, not just a perf fix: a
PR whose true first-publish is outside the window but got re-published
inside it (a fresh push triggering re-review) would resolve to the wrong,
too-recent date. The new regression test proves such a PR is still
correctly excluded -- verified failing against the naive version first.
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.21%. Comparing base (bfc34cd) to head (0689c72).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4727   +/-   ##
=======================================
  Coverage   94.21%   94.21%           
=======================================
  Files         439      439           
  Lines       38704    38704           
  Branches    14101    14101           
=======================================
  Hits        36466    36466           
  Misses       1576     1576           
  Partials      662      662           
Files with missing lines Coverage Δ
src/db/schema.ts 73.07% <ø> (ø)
src/services/public-review-volume-trend.ts 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 10, 2026
@loopover-orb

loopover-orb Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-10 21:20:40 UTC

4 files · 1 AI reviewer · no blockers · readiness 100/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review: This PR changes guardrail-protected path(s): src/services/public-review-volume-trend.ts (matched src/services/**).

Review summary
This PR replaces an unbounded MIN(created_at) scan over the full pr_public_surface_published history with a two-step, index-backed query: a time-bounded 'recent_keys' CTE (existing audit_events_type_created_idx) narrows candidates, then a 'true_first_seen' CTE (new audit_events_target_key_created_idx, migration 0142) resolves each candidate's TRUE first-publish date over its full history before the trend-window filter is applied. This ordering matters for correctness, not just speed — filtering by sinceIso before MIN() would misattribute a PR whose true first-publish is outside the window but that got a legitimate recent re-publish, and the new regression test explicitly exercises and pins that scenario (verified failing against the naive single-pass version first per the PR description). The migration is a plain CREATE INDEX IF NOT EXISTS, D1-remote-safe, with matching schema.ts parity, and parameter binding order in the rewritten query (sinceIso, ...projects, sinceIso) correctly matches the three placeholders in SQL order.

Nits — 6 non-blocking
  • src/services/public-review-volume-trend.ts:80 — the doc comment cites 'perf(stats): bound public-review-volume-trend's own-ledger query by the trailing window, not a post-aggregation HAVING #4723' inline rather than as a named constant/reference; harmless, but consider a single glossary-style comment instead of repeating the issue number across the file.
  • true_first_seen selects `repo` from target_key without re-lowercasing it before joining to pull_requests.repo_full_name, while recent_keys does lowercase for its own IN-list filter — likely intentional (preserves original casing for the join) but worth a one-line comment so a future reader doesn't 'fix' it as an inconsistency.
  • Consider adding an EXPLAIN QUERY PLAN assertion or a comment pointing to where the SEARCH-not-SCAN behavior was manually verified, so future readers can re-confirm the index usage without re-running the manual check described in the PR description.
  • The migration's SQL comment is thorough — consider carrying the same 'index lookup, not uniqueness constraint' framing into the schema.ts index definition for symmetry.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #4723
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 48 registered-repo PR(s), 40 merged, 285 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 48 PR(s), 285 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Linked issue satisfaction

Addressed
The PR replaces the unbounded MIN(created_at) scan with an index-backed two-step CTE (recent_keys bounded by the trailing window via an existing index, true_first_seen computed over each candidate's full history via a new target_key index), preserves correctness for the re-publish edge case, adds a regression test proving a PR re-published inside the window but truly first-published outside it is

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 48 PR(s), 285 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 10, 2026
@JSONbored
JSONbored merged commit 436bc37 into main Jul 10, 2026
12 checks passed
@JSONbored
JSONbored deleted the perf/bound-review-volume-trend-audit-events-scan-4723 branch July 10, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

perf(stats): bound public-review-volume-trend's own-ledger query by the trailing window, not a post-aggregation HAVING

1 participant