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.