Files
twenty/packages
Sonarly Claude Code 41bf13d557 fix(calendar): hoist userWorkspace query and batch connectedAccount lookups outside visibility loop
https://sonarly.com/issue/22703?type=bug

The `FindManyCalendarEvents` post-query hook executes 38 identical `userWorkspace` lookups and 38 `connectedAccount` queries inside a per-event loop, adding ~94ms of avoidable DB overhead per calendar page load.

Fix: ## Fix: Eliminate N+1 queries in calendar event visibility restrictions

The `ApplyCalendarEventsVisibilityRestrictionsService` was executing 2 DB queries per calendar event inside the visibility restriction loop:
1. `userWorkspaceRepository.findOne()` — identical every iteration (same userId + workspaceId)
2. `connectedAccountRepository.find()` — varying by calendar channel IDs

With 38 events, this produced 76 individual queries (~94ms overhead).

### Changes:

**`apply-calendar-events-visibility-restrictions.service.ts`:**
- Hoisted `userWorkspace` lookup before the loop (it's loop-invariant — same userId/workspaceId every time)
- Replaced per-event `connectedAccount` queries with a single batch query that fetches all connected accounts for ALL non-SHARE_EVERYTHING calendar channels at once, using `relations: ['calendarChannels']` to get the channel associations
- Built a `Set<string>` of owned calendar channel IDs for O(1) lookup inside the loop
- The loop now does pure in-memory checks (`ownedCalendarChannelIds.has()`) instead of DB queries

This reduces the query count from `2 + N*2` (where N = events without SHARE_EVERYTHING) to `4` fixed queries regardless of event count.

**`apply-calendar-events-visibility-restrictions.service.spec.ts`:**
- Updated mock setup to match new batch query pattern (single `find` call returns connected accounts with `calendarChannels` relation)
- Removed unused `mockWorkspaceMemberRepository`
- All existing test cases preserved with same behavioral expectations

**Note:** The messaging equivalent (`apply-messages-visibility-restrictions.service.ts`) has the same N+1 pattern but is out of scope for this fix.
2026-04-08 04:56:51 +00:00
..
2026-04-08 03:42:20 +02:00