Skip to content

🚨 Lighthouse: [Fix N+1 bottleneck in report card validation]#254

Open
ldsgroups225 wants to merge 1 commit intomasterfrom
lighthouse-fix-nplus1-report-cards-10152485457501312247
Open

🚨 Lighthouse: [Fix N+1 bottleneck in report card validation]#254
ldsgroups225 wants to merge 1 commit intomasterfrom
lighthouse-fix-nplus1-report-cards-10152485457501312247

Conversation

@ldsgroups225
Copy link
Copy Markdown
Owner

@ldsgroups225 ldsgroups225 commented Apr 5, 2026

Impact on performance

This PR eliminates a severe N+1 query problem during report card batch validation. Previously, validateReportCardPayloads iterated over arrays of mapped unique IDs and awaited a database hit per student, class, term, etc. This has been replaced with a single bulk fetch using Drizzle's inArray(), which is correctly mapped back to memory structures.

Technical Rationale

  • O(N) database roundtrips changed to O(1) batched queries.
  • Utilizes Drizzle inArray for better efficiency and Cloudflare connection pooling usage.
  • Emptry arrays are appropriately handled to prevent SQL syntax errors.
  • Matches exactly the semantics of the original getScoped* error handling and uniqueness checking.

PR created automatically by Jules for task 10152485457501312247 started by @ldsgroups225

Summary by CodeRabbit

  • Refactor
    • Enhanced report card validation to improve processing performance and provide more detailed error messages when validation issues are detected.

@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 5, 2026

📝 Walkthrough

Walkthrough

The validation logic in validateReportCardPayloads has been refactored to replace parallel per-entity scoped getter function calls with bulk database queries using inArray() conditions. The function now fetches all requested entity scopes in fewer queries and conditionally skips queries when entity ID lists are empty.

Changes

Cohort / File(s) Summary
Report Card Validation Optimization
packages/data-ops/src/queries/report-cards.ts
Replaced parallel per-entity scoped getter calls with single bulk DB inArray() queries for students, classes, terms, school-years, and templates. Added conditional query skipping for empty ID lists and result count verification against expected unique ID counts. Refactored scopedClasses and scopedTerms map construction from bulk results instead of individual entity arrays.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #210: Parallelizes per-entity scoped getters in the same validation function, representing an alternative approach to the sequential bulk query pattern introduced here.
  • PR #163: Previously modified validateReportCardPayloads to use concurrent Promise.all calls for per-ID scoped getters, which is the pattern now being replaced by bulk queries.

Poem

🐰 In databases vast where the scopes dance and play,
One query now reigns where once many held sway,
With inArray magic, bulk validation's the way,
No parallel sprawl—efficiency's here to stay!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: fixing an N+1 query bottleneck in report card validation by consolidating database calls into batched queries.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lighthouse-fix-nplus1-report-cards-10152485457501312247

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/data-ops/src/queries/report-cards.ts (1)

430-437: Consider filtering by active status for classes and school years in batch validation.

The batch queries in validateReportCardPayloads do not filter by classes.status = 'active' or schoolYears.isActive = true, while the listNightlyReportCardDiscoveryUnits function applies these filters elsewhere in the file (lines 922, 1009). This could allow report cards to be validated/created for archived classes or inactive school years, creating an inconsistency in how status is enforced across report card operations.

The refactored code correctly preserves the original behavior of getScopedClass and getScopedSchoolYear (which also lack status filters), but consider adding status filters in a follow-up PR to align with the filtering patterns used in discovery operations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/data-ops/src/queries/report-cards.ts` around lines 430 - 437, The
batch validation queries inside validateReportCardPayloads currently select
classes, terms, and schoolYears without filtering on status; update the three
db.select calls that query classes, terms (which already innerJoins
schoolYears), and schoolYears so they also include filters equivalent to
classes.status = 'active' and schoolYears.isActive = true (mirror the filtering
used in listNightlyReportCardDiscoveryUnits) to prevent validating report cards
for archived classes or inactive school years; ensure the classes query adds the
classes.status filter, the terms query keeps its innerJoin(schoolYears) and adds
schoolYears.isActive = true, and the schoolYears query adds schoolYears.isActive
= true.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/data-ops/src/queries/report-cards.ts`:
- Around line 430-437: The batch validation queries inside
validateReportCardPayloads currently select classes, terms, and schoolYears
without filtering on status; update the three db.select calls that query
classes, terms (which already innerJoins schoolYears), and schoolYears so they
also include filters equivalent to classes.status = 'active' and
schoolYears.isActive = true (mirror the filtering used in
listNightlyReportCardDiscoveryUnits) to prevent validating report cards for
archived classes or inactive school years; ensure the classes query adds the
classes.status filter, the terms query keeps its innerJoin(schoolYears) and adds
schoolYears.isActive = true, and the schoolYears query adds schoolYears.isActive
= true.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2655446b-d732-492f-84c4-1f90a79d0c64

📥 Commits

Reviewing files that changed from the base of the PR and between 7e37ef8 and 4977b54.

📒 Files selected for processing (1)
  • packages/data-ops/src/queries/report-cards.ts

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant