-
Notifications
You must be signed in to change notification settings - Fork 11.5k
fix: use graceful filtering for previously hard failing blocked users in team events #26446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| @@unique([type, value, organizationId]) | ||
| @@index([type, value, organizationId, action]) | ||
| @@index([isGlobal, action, organizationId, type, value]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ordering is optimal because:
- isGlobal (boolean) - filters to global vs org entries immediately
- action (enum: REPORT/BLOCK/ALERT) - narrows to blocking entries
- organizationId - filters by specific org (or null for global)
- type (EMAIL/DOMAIN) - before the range scan
- value - at the end for the IN clause range lookup
This matches both query patterns:
- Global:
isGlobal=true, action=BLOCK, organizationId=null, type IN (EMAIL,DOMAIN), value IN (...) - Org:
isGlobal=false, action=BLOCK, organizationId=X, type IN (EMAIL,DOMAIN), value IN (...)
packages/features/watchlist/lib/service/OrganizationBlockingService.ts
Outdated
Show resolved
Hide resolved
packages/features/watchlist/operations/filter-blocked-hosts.controller.ts
Outdated
Show resolved
Hide resolved
packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts
Outdated
Show resolved
Hide resolved
E2E results are ready! |
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
| organizationId?: number | null | ||
| ): Promise<CheckUserBlockingResult> { | ||
| // Filter out users with empty/invalid emails | ||
| const validUsers = users.filter((u) => u.email && u.email.trim().length > 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Instead of doing emai.trim twice at 103 and here, we could do map first here and then filter. Tha would ensure validUsers have email trimmed already
| const organizationId = eventType.parent?.team?.parentId ?? eventType.team?.parentId ?? null; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't consistent with what we are doing in loadAndValidateUsers. It is missing Organization members' personal events' handling
volnei
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work!
| * Bulk check multiple emails in a single query. | ||
| * Returns Map<email (lowercase), BlockingResult> for efficient lookup. | ||
| */ | ||
| async areBlocked(emails: string[]): Promise<BulkBlockingResult> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
What does this PR do?
Refactors watchlist blocking to use batched checks and graceful filtering instead of the previous N+1 query pattern that hard-failed if any user was blocked.
Key Changes:
1. Batch Watchlist Methods (N+1 → O(1))
areBlocked(emails[])toGlobalBlockingServiceandOrganizationBlockingServicefindBlockingEntriesForEmailsAndDomains()to repository interfaces2. Slot Display: Filter Blocked Hosts
filterBlockedHosts()controller filters hosts BEFORE calculating availability3. Booking: Graceful Filtering
filterBlockedUsers()controller replacescheckIfUsersAreBlocked()Before: Team of 100 users, 1 blocked → ❌ 404 error, entire event unavailable
After: Team of 100 users, 1 blocked → ✅ 99 users available, booking succeeds
Visual Demo (For contributors especially)
Video Demo (if applicable):
Mandatory Tasks (DO NOT REMOVE)
How should this be tested?
Prerequisites:
Test Steps:
Setup:
blocked@example.com)Before blocking - verify baseline:
Block a user:
blocked@example.comto the global watchlist (BLOCK action)After blocking - verify graceful filtering:
Edge case - all users blocked:
Expected Behavior:
Performance Verification:
SELECTfor watchlist check regardless of team sizeChecklist