Skip to content

refactor(frontend): drop per-project fan-out from all batch fetchers#4637

Open
mmabrouk wants to merge 1 commit into
fix/evaluator-names-from-artifactfrom
refactor/single-project-batch-fetchers
Open

refactor(frontend): drop per-project fan-out from all batch fetchers#4637
mmabrouk wants to merge 1 commit into
fix/evaluator-names-from-artifactfrom
refactor/single-project-batch-fetchers

Conversation

@mmabrouk

Copy link
Copy Markdown
Member

Context

While reviewing #4634, @junaway flagged the artifact fetcher's shape: it grouped requests into a Map keyed by project_id and ran one query per project inside a Promise.all. That structure handles a state that cannot exist. The web app holds exactly one project_id in scope at any time, and the /query endpoints accept multiple ids, so a batch of coalesced requests always resolves with a single call.

The interesting part is where that shape came from. It was not invented for #4634; it was copied from the fetchers sitting right next to it. A grep for the pattern found it in 13 batch fetchers across 9 files: workflow revisions, latest revisions, traces, spans, testsets, testset revisions (twice), testcases (twice), evaluation runs, annotations, and environments. Every one of them defends against a multi-project batch that no caller can produce. Each copy also drags in real complexity: nested grouping maps, per-group error handling, and in one case a per-project queryClient set that exists only to serve the impossible case.

This is how a wrong pattern propagates. "Match the surrounding code" is the default instinct for any contributor (or agent) writing a new fetcher, and the surrounding code taught the wrong thing. #4634 fixed its own fetcher after review; this PR removes the remaining 12 copies and writes the invariant down so the next fetcher starts from the right shape.

Changes

Every batchFn now follows one shape:

  1. Pre-fill the results map with the miss value, so error paths need no per-key cleanup.
  2. Take project_id from the first request. If any other request disagrees, throw. A multi-project batch means a bug upstream, and per @junaway's review it must fail rather than be silently accommodated.
  3. Resolve all ids with a single query.

Before (the shape every fetcher had):

const byProject = new Map<string, {ids: string[]; keys: string[]}>()
requests.forEach((req) => { /* bucket into byProject */ })
await Promise.all(
    Array.from(byProject.entries()).map(async ([projectId, group]) => {
        /* one query per project, per-group error handling */
    }),
)

After:

const projectId = requests[0]?.projectId
if (!projectId) return results
if (requests.some((req) => req.projectId !== projectId)) {
    throw new Error("…: requests span multiple projects")
}
/* one query with all ids */

Behavior that was per-fetcher stays: cache short-circuits, fallback-to-individual-fetch paths, and cache priming are preserved, just no longer duplicated per project group. Grouping by other dimensions survives where it is real: the testcase entity fetcher still groups its cache lookup by revisionId, because the paginated cache is genuinely revision-scoped. The rule is only that the project dimension is singular.

web/AGENTS.md now states the invariant under Data fetching ("Single project scope"), so the convention no longer lives only in the code it was just removed from.

Tests

  • tsc --noEmit clean on agenta-entities; zero errors in the two touched web/oss files (the workspace has unrelated pre-existing errors elsewhere).
  • All 656 agenta-entities unit tests pass.
  • eslint clean on all nine touched source files.
  • Net −186 lines.

What to QA

This is a refactor with no intended behavior change, so the check is regression-only: the touched fetchers feed most entity displays. Browse the evaluators table, a testset and its revisions, an evaluation run detail, the annotation queue, a trace drawer, and the deployments page. Everything should load exactly as before, with no new errors in the console.

One project is in scope at a time in the web app, so grouping batched
requests by project and issuing one query per project handles a state
that cannot exist. Every batchFn now takes the single project in scope,
throws if coalesced requests disagree, and resolves all ids with one
call. Documents the invariant in web/AGENTS.md.
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jun 11, 2026 10:22am

Request Review

@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. Frontend refactoring A code change that neither fixes a bug nor adds a feature labels Jun 11, 2026
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: accd39a4-59e2-40b9-81f1-2727e2eb5bad

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/single-project-batch-fetchers

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 and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Frontend refactoring A code change that neither fixes a bug nor adds a feature size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants