Skip to content

perf: optimize getBusyTimesForLimitChecks with batched parallel queries#27399

Merged
volnei merged 10 commits intomainfrom
devin/1769709003-optimize-busy-times-limit-checks
Feb 10, 2026
Merged

perf: optimize getBusyTimesForLimitChecks with batched parallel queries#27399
volnei merged 10 commits intomainfrom
devin/1769709003-optimize-busy-times-limit-checks

Conversation

@Udit-takkar
Copy link
Copy Markdown
Contributor

@Udit-takkar Udit-takkar commented Jan 29, 2026

What does this PR do?

TODO

  • Do we need to add one more index @@index([eventTypeId, userId, status, startTime]) on Booking Table?
    Not required as we already have other index and it does a index scan when i ran the query

Optimizes the getBusyTimesForLimitChecks query in BusyTimesService which can be slow for teams/orgs with many members due to the userId: { in: userIds } clause.

Changes:

  1. Splits large userIds arrays into batches of 50 and runs queries in parallel
  2. Adds comprehensive unit tests for the batching logic (12 new tests)

This addresses performance concerns for organizations with hundreds of team members where the original single query with a large IN clause could cause slow query planning and execution.

Link to Devin run: https://app.devin.ai/sessions/0f1730edf1a14b2184c4b9bfb9c556d4
Requested by: @Udit-takkar

Updates since last revision

  • Fixed PII logging issue: Changed debug log at line 368 from JSON.stringify(busyTimes) to count=${busyTimes.length} to avoid exposing userId in logs (addressed Cubic AI review feedback, confidence 9/10)

Link to Devin run (Cubic fix): https://app.devin.ai/sessions/a16fb642ff984783a46e24f5e2aed4e3

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. N/A - no documentation changes needed.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  1. Unit tests: Run TZ=UTC yarn test packages/features/busyTimes/services/getBusyTimes.test.ts to verify all 15 tests pass (3 existing + 12 new)

  2. Functional testing: Create a team event type with booking limits enabled and multiple team members. Verify that:

    • Booking limits are still correctly enforced
    • Rescheduling works correctly (the rescheduleUid exclusion)
    • The busy times returned match the expected bookings
  3. Performance testing (optional but recommended):

    • Test with a large team (100+ members) and compare query times before/after
    • Monitor database query logs to verify batching is working

Checklist

  • I have read the contributing guide
  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have checked if my changes generate no new warnings

Human Review Checklist

  • Verify the raw SQL is semantically equivalent to the original Prisma query
  • Verify the hardcoded status = 'accepted' string matches BookingStatus.ACCEPTED enum value
  • Review that the batch size of 50 is appropriate for the expected use cases

@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration bot and others added 2 commits January 29, 2026 18:03
The batching (50 user chunks) and parallel execution (Promise.all) provide
the main performance optimization. Using findMany instead of $queryRaw
maintains the same performance characteristics while being compatible
with prismock for testing.

Co-Authored-By: [email protected] <[email protected]>
@Udit-takkar Udit-takkar changed the title perf: optimize getBusyTimesForLimitChecks with batched parallel queries and raw SQL perf: optimize getBusyTimesForLimitChecks with batched parallel queries Jan 29, 2026
@keithwillcode keithwillcode added the core area: core, team members only label Feb 3, 2026
@pull-request-size pull-request-size bot added size/XL and removed size/L labels Feb 5, 2026
@Udit-takkar Udit-takkar marked this pull request as ready for review February 5, 2026 10:18
@graphite-app graphite-app bot added the enterprise area: enterprise, audit log, organisation, SAML, SSO label Feb 5, 2026
@graphite-app graphite-app bot requested a review from a team February 5, 2026 10:18
@Udit-takkar Udit-takkar added this to the v6.2 milestone Feb 5, 2026
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/features/busyTimes/services/getBusyTimes.ts">

<violation number="1" location="packages/features/busyTimes/services/getBusyTimes.ts:368">
P1: Rule violated: **Avoid Logging Sensitive Information**

This log serializes busyTimes including `userId`, which exposes PII in logs. Avoid logging user identifiers; log only aggregate counts or remove the busyTimes payload.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 5, 2026

Devin AI is addressing Cubic AI's review feedback

A Devin session has been created to address the issues identified by Cubic AI.

View Devin Session

devin-ai-integration bot and others added 2 commits February 5, 2026 10:25
Replace JSON.stringify(busyTimes) with count to avoid exposing userId
in logs. Addresses Cubic AI review feedback (confidence 9/10).

Co-Authored-By: unknown <>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/features/busyTimes/services/getBusyTimes.ts">

<violation number="1" location="packages/features/busyTimes/services/getBusyTimes.ts:368">
P1: Rule violated: **Avoid Logging Sensitive Information**

Avoid logging sensitive data: JSON.stringify(busyTimes) includes per-booking userId values, which are PII, and should not be written to logs. Log only aggregate counts or non-identifying metadata per the "Avoid Logging Sensitive Information" rule.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@paragon-review
Copy link
Copy Markdown

paragon-review bot commented Feb 5, 2026

Paragon: tests updated

2 updated tests generated for this PR.

Updated Tests

  • getBusyTimesForLimitChecks integration tests — Integration tests for getBusyTimesForLimitChecks with real database - tests batching across multiple users and rescheduleUid exclusion
  • getBusyTimesForLimitChecks tests — Adding new test to existing file

Accept Changes Open in Paragon

Details

Updated Tests

  • getBusyTimesForLimitChecks integration tests (unit)
  • getBusyTimesForLimitChecks tests (unit)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 5, 2026

Devin AI is addressing Cubic AI's review feedback

New feedback has been sent to the existing Devin session.

View Devin Session


✅ No changes pushed (PR owner explicitly requested to keep the logging in comments here and here)

Copy link
Copy Markdown
Contributor

@volnei volnei left a comment

Choose a reason for hiding this comment

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

🚀

@@ -351,10 +466,10 @@ export class BusyTimesService {
status: BookingStatus.ACCEPTED,
// FIXME: bookings that overlap on one side will never be counted
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👀 should we take care of it in this PR? or link a issue... I know it's old but since we're touching it 🙂

@volnei volnei enabled auto-merge (squash) February 10, 2026 15:44
@volnei volnei merged commit 3908cda into main Feb 10, 2026
90 of 91 checks passed
@volnei volnei deleted the devin/1769709003-optimize-busy-times-limit-checks branch February 10, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ready-for-e2e size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants