-
Notifications
You must be signed in to change notification settings - Fork 10.2k
feat: outlook cache - PR: Office365 Calendar Cache & Webhook System #21854
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
base: main
Are you sure you want to change the base?
feat: outlook cache - PR: Office365 Calendar Cache & Webhook System #21854
Conversation
@din-prajapati is attempting to deploy a commit to the cal Team on Vercel. A member of the Team first needs to authorize it. |
Hey there and thank you for opening this pull request! 👋🏼 We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted. Details:
|
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (06/16/25)1 reviewer was added to this PR based on Keith Williams's automation. "Add community label" took an action on this PR • (06/16/25)1 label was added to this PR based on Keith Williams's automation. |
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.
cubic found 23 issues across 28 files. Review them in cubic.dev
React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai
to give specific feedback.
packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts
Outdated
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/shared/team-scenarios.utils.ts
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
Outdated
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
Outdated
Show resolved
Hide resolved
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.
cubic found 29 issues across 28 files. Review them in cubic.dev
React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai
to give specific feedback.
packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts
Outdated
Show resolved
Hide resolved
Addresses issues identified in PR calcom#21854 code review
…: 21050) - Add Office365CalendarCache for performance optimization - Add Office365SubscriptionManager for webhook subscriptions - Add environment validation utilities - Add webhook API endpoint for real-time sync - Add comprehensive unit tests - Update .env.example with correct configuration Core Features: - Calendar caching with TTL and invalidation - Real-time webhook notifications - Proper environment variable validation - Comprehensive error handling Note: ESLint warnings to be addressed in follow-up commit
Addresses issues identified in PR calcom#21854 code review
5c5b89b
to
14a5fd5
Compare
- Fixed TypeScript error in Office365 calendar tests - Added required calendarDescription field to test event object - Resolves type mismatch with CalendarServiceEvent interface
…n-prajapati/cal.com into feat/office365-calendar-cache
@maintainers Could you please add the following labels to this PR? 🙋 Bounty claim |
@anikdhabal who will be relevant person for this PR Review ? And Also I noticed there are few below labels missing could you let me know how to assign those if you have permission can you assign it ? 🙋 Bounty claim |
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThis update introduces comprehensive Office365 Calendar integration, focusing on webhook-based calendar cache optimization, robust subscription management, and extensive test coverage. The database schema and Prisma models are extended with new fields and constraints to support Outlook subscription tracking. The Office365CalendarService is enhanced with chunked availability fetching, subscription lifecycle methods, and improved error handling, while a new Office365CalendarCache class manages availability caching. A dedicated webhook API route processes Microsoft Graph notifications, validates payloads, deduplicates events, and refreshes caches as needed. Supporting modules handle environment validation, subscription management, and Zod-based payload validation. Extensive unit, integration, and end-to-end tests are added, along with utilities and mocks for simulating API responses, webhook payloads, and team scenarios. Documentation and configuration files are updated to reflect new environment variables, platform compatibility, and feature support. No existing logic is removed; all changes extend current functionality to support Office365 calendar optimization and testing. Estimated code review effort🎯 4 (Complex) | ⏱️ ~90 minutes Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used📓 Path-based instructions (3)**/*.ts📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Files:
**/*.{ts,tsx}📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Files:
**/*Service.ts📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Files:
🧠 Learnings (10)📓 Common learnings
📚 Learning: in packages/app-store/office365calendar/lib/calendarservice.ts, the fetcher method in office365calen...
Applied to files:
📚 Learning: the office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is spec...
Applied to files:
📚 Learning: applies to **/*.ts : ensure the `credential.key` field is never returned from trpc endpoints or apis...
Applied to files:
📚 Learning: for e2e integration tests that require real third-party service credentials (like outlook calendar),...
Applied to files:
📚 Learning: applies to **/*service.ts : service files must include `service` suffix, use pascalcase matching exp...
Applied to files:
📚 Learning: for microsoft graph webhook handlers, when dealing with internal configuration errors (like missing ...
Applied to files:
📚 Learning: applies to **/*.{ts,tsx} : flag excessive day.js use in performance-critical code; prefer native dat...
Applied to files:
📚 Learning: the outlook calendar integration in cal.com intentionally reuses subscription ids across multiple ev...
Applied to files:
📚 Learning: in cal.com's calendar integration, both google calendar and outlook calendar are designed to allow m...
Applied to files:
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (17)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 11
♻️ Duplicate comments (5)
packages/app-store/office365calendar/__tests__/unit_tests/shared/team-scenarios.utils.ts (1)
1-1
: Fix the incorrect type-only import forvi
.-import type { vi } from "vitest"; +import { vi } from "vitest";packages/app-store/office365calendar/__tests__/mock_utils/utils.ts (1)
120-124
: Fix property override order in credential object.The current order spreads
credentialInDb
after setting properties, which could override important fields likeuser
anddelegatedTo
.return { - ...credentialInDb, - user: user ? { email: user.email ?? "" } : null, - delegatedTo, + user: user ? { email: user.email ?? "" } : null, + delegatedTo, + ...credentialInDb, } as CredentialForCalendarServiceWithTenantId;packages/app-store/office365calendar/lib/CalendarService.ts (1)
649-671
: Fix unreachable error logging code.The condition uses AND when it should use OR, making the error logging unreachable:
- if (!response.ok && (response.status < 200 || response.status >= 300)) { + if (!response.ok || response.status < 200 || response.status >= 300) {Actually, since
response.ok
is false when status is outside 200-299, you can simplify:- if (!response.ok && (response.status < 200 || response.status >= 300)) { + if (!response.ok) {packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts (1)
521-521
: Fix misleading test description.The test description claims the code "should retry on transient failures" but the test actually verifies that it fails without retry.
- test("should retry on transient failures", async () => { + test("should fail on transient failures without retry", async () => {packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts (1)
84-754
: Entire test suite needs restructuring to test actual webhook handlerAll tests in this file follow the same anti-pattern of creating mock webhook handlers and testing those mocks instead of the actual implementation. This provides no real test coverage of the webhook handler logic.
The test file should:
- Import the actual webhook handler from
../../api/webhook
- Mock only external dependencies (database, API calls)
- Test the real handler's behavior with various inputs
- Verify actual responses, not mock responses
🧹 Nitpick comments (8)
.env.example (2)
168-171
: Fix environment variable ordering.The
E2E_TEST_OUTLOOK_CALENDAR_EMAIL
variable should be placed beforeE2E_TEST_OUTLOOK_CALENDAR_TENANT_ID
to maintain alphabetical ordering consistency.E2E_TEST_OUTLOOK_CALENDAR_CLIENT_ID="" E2E_TEST_OUTLOOK_CALENDAR_CLIENT_KEY="" -E2E_TEST_OUTLOOK_CALENDAR_TENANT_ID="" E2E_TEST_OUTLOOK_CALENDAR_EMAIL="" +E2E_TEST_OUTLOOK_CALENDAR_TENANT_ID=""
173-174
: Remove extra blank lines.E2E_TEST_OUTLOOK_CALENDAR_EMAIL="" - - # Inbox to send user feedbackpackages/app-store/office365calendar/lib/Office365SubscriptionManager.ts (2)
89-89
: Remove commented out codeThese commented lines serve no purpose and should be removed to keep the code clean.
async renewSubscription(subscriptionId: string) { try { - //const userEndpoint = await this.calendarService.getUserEndpoint(); const response = await this.calendarService.fetcher(`/subscriptions/${subscriptionId}`, {
async deleteSubscription(subscriptionId: string) { try { - //const userEndpoint = await this.calendarService.getUserEndpoint(); const response = await this.calendarService.fetcher(`/subscriptions/${subscriptionId}`, {
Also applies to: 112-112
132-132
: Remove additional commented out codeThis commented line should also be removed.
async getSubscriptionsForCredential() { try { - //const userEndpoint = await this.calendarService.getUserEndpoint(); const response = await this.calendarService.fetcher(`/subscriptions`, {
packages/app-store/office365calendar/__tests__/unit_tests/shared/performance.utils.ts (1)
107-107
: Use class name instead of 'this' in static contextUsing
this
in static methods can be confusing as it refers to the class itself. Use the explicit class name for better clarity.static expectBatchOptimization(fetcherSpy: ReturnType<typeof vi.fn>, expectedBatchCalls = 1): void { - const apiCalls = this.measureApiCalls(fetcherSpy); + const apiCalls = PerformanceTestUtils.measureApiCalls(fetcherSpy); expect(apiCalls.batch).toBeGreaterThanOrEqual(expectedBatchCalls);const totalCalendars = teamSize * calendarsPerMember; - const apiCalls = this.measureApiCalls(fetcherSpy); + const apiCalls = PerformanceTestUtils.measureApiCalls(fetcherSpy);): void { - const apiCalls = this.measureApiCalls(fetcherSpy); + const apiCalls = PerformanceTestUtils.measureApiCalls(fetcherSpy); expect(apiCalls.total).toBeLessThan(maxApiCalls);Also applies to: 121-121, 136-136
packages/app-store/office365calendar/lib/Office365CalendarCache.ts (1)
97-154
: Consider using a proper deep clone methodThe
JSON.parse(JSON.stringify(busyTimes))
pattern on line 142 will not properly handle Date objects, undefined values, or functions. SincebusyTimes
likely contains Date objects, consider using a proper cloning method or structured cloning.await calendarCache.upsertCachedAvailability({ credentialId: this.credentialId, userId: this.userId, args, - value: JSON.parse(JSON.stringify(busyTimes)), + value: structuredClone ? structuredClone(busyTimes) : busyTimes, });packages/app-store/office365calendar/__tests__/unit_tests/shared/team-scenarios.utils.ts (1)
84-84
: Consider using dynamic dates instead of hardcoded values.The hardcoded date "2024-01-01" may become outdated. Consider using the dynamic date utilities from the
dates.ts
module for more maintainable tests.-busySlots: member % 2 === 0 ? [{ start: "2024-01-01T09:00:00Z", end: "2024-01-01T10:00:00Z" }] : [], +busySlots: member % 2 === 0 ? [{ start: TEST_DATES.TOMORROW_9AM, end: TEST_DATES.TOMORROW_10AM }] : [],You'll need to import the date utilities:
import { TEST_DATES } from "../../dates";packages/app-store/office365calendar/lib/CalendarService.ts (1)
1021-1021
: Remove unnecessary continue statement.The continue statement at the end of the loop is redundant.
this.log.error("Error fetching chunk availability", { error, chunk, calendarIds, }); // Continue with next chunk even if one fails - continue;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (28)
.env.example
(1 hunks)apps/api/v1/test/lib/selected-calendars/_post.test.ts
(2 hunks)packages/app-store/office365calendar/__tests__/dates.ts
(1 hunks)packages/app-store/office365calendar/__tests__/mock_utils/mocks.ts
(1 hunks)packages/app-store/office365calendar/__tests__/mock_utils/utils.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/TeamEvents.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/shared/error-handling.utils.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/shared/performance.utils.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/shared/team-scenarios.utils.ts
(1 hunks)packages/app-store/office365calendar/api/index.ts
(1 hunks)packages/app-store/office365calendar/api/webhook.ts
(1 hunks)packages/app-store/office365calendar/lib/CalendarService.ts
(8 hunks)packages/app-store/office365calendar/lib/Office365CalendarCache.ts
(1 hunks)packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts
(1 hunks)packages/app-store/office365calendar/lib/envValidation.ts
(1 hunks)packages/app-store/office365calendar/tests/office365calendar.e2e.ts
(1 hunks)packages/app-store/office365calendar/tests/testUtils.ts
(1 hunks)packages/app-store/office365calendar/zod.ts
(1 hunks)packages/features/calendar-cache/CalendarCache.md
(1 hunks)packages/lib/server/repository/selectedCalendar.ts
(4 hunks)packages/prisma/migrations/20250520104336_feature_outlook_cache_21050/migration.sql
(1 hunks)packages/prisma/schema.prisma
(2 hunks)playwright.config.ts
(1 hunks)turbo.json
(3 hunks)
👮 Files not reviewed due to content moderation or server errors (1)
- packages/app-store/office365calendar/lib/envValidation.ts
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
apps/api/v1/test/lib/selected-calendars/_post.test.ts (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/features/calendar-cache/CalendarCache.md (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
turbo.json (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/prisma/migrations/20250520104336_feature_outlook_cache_21050/migration.sql (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/prisma/schema.prisma (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/app-store/office365calendar/lib/envValidation.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
.env.example (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/app-store/office365calendar/__tests__/unit_tests/TeamEvents.test.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/lib/server/repository/selectedCalendar.ts (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/app-store/office365calendar/tests/office365calendar.e2e.ts (3)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/app-store/office365calendar/tests/testUtils.ts (3)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/app-store/office365calendar/__tests__/mock_utils/utils.ts (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
packages/app-store/office365calendar/__tests__/dates.ts (1)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.742Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/app-store/office365calendar/lib/CalendarService.ts (2)
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.256Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.255Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
🧬 Code Graph Analysis (3)
packages/app-store/office365calendar/lib/envValidation.ts (1)
apps/api/v2/src/lib/logger.bridge.ts (1)
error
(77-79)
packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts (2)
packages/app-store/office365calendar/lib/CalendarService.ts (1)
Office365CalendarService
(62-1046)packages/app-store/office365calendar/lib/envValidation.ts (2)
getWebhookUrl
(87-98)getWebhookToken
(103-111)
packages/lib/server/repository/selectedCalendar.ts (1)
packages/prisma/selects/credential.ts (1)
credentialForCalendarServiceSelect
(3-17)
🪛 markdownlint-cli2 (0.17.2)
packages/features/calendar-cache/CalendarCache.md
6-6: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
7-7: Unordered list indentation
Expected: 4; Actual: 6
(MD007, ul-indent)
8-8: Unordered list indentation
Expected: 6; Actual: 8
(MD007, ul-indent)
9-9: Unordered list indentation
Expected: 4; Actual: 6
(MD007, ul-indent)
10-10: Unordered list indentation
Expected: 4; Actual: 6
(MD007, ul-indent)
11-11: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
13-13: Unordered list indentation
Expected: 2; Actual: 4
(MD007, ul-indent)
🪛 dotenv-linter (3.3.0)
.env.example
[warning] 160-160: [QuoteCharacter] The value has quote characters (', ")
[warning] 168-168: [QuoteCharacter] The value has quote characters (', ")
[warning] 169-169: [QuoteCharacter] The value has quote characters (', ")
[warning] 170-170: [QuoteCharacter] The value has quote characters (', ")
[warning] 171-171: [QuoteCharacter] The value has quote characters (', ")
[warning] 171-171: [UnorderedKey] The E2E_TEST_OUTLOOK_CALENDAR_EMAIL key should go before the E2E_TEST_OUTLOOK_CALENDAR_TENANT_ID key
[warning] 173-173: [ExtraBlankLine] Extra blank line detected
[warning] 174-174: [ExtraBlankLine] Extra blank line detected
🪛 Biome (1.9.4)
packages/app-store/office365calendar/__tests__/unit_tests/shared/performance.utils.ts
[error] 23-140: Avoid classes that contain only static members.
Prefer using simple functions instead of classes with only static members.
(lint/complexity/noStaticOnlyClass)
[error] 107-107: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 121-121: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 136-136: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
packages/app-store/office365calendar/__tests__/unit_tests/shared/team-scenarios.utils.ts
[error] 35-212: Avoid classes that contain only static members.
Prefer using simple functions instead of classes with only static members.
(lint/complexity/noStaticOnlyClass)
[error] 188-188: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 193-193: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 198-198: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 204-204: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 205-205: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
[error] 206-206: Using this in a static context can be confusing.
this refers to the class.
Unsafe fix: Use the class name instead.
(lint/complexity/noThisInStatic)
packages/app-store/office365calendar/lib/CalendarService.ts
[error] 1021-1021: Unnecessary continue statement
Unsafe fix: Delete the unnecessary continue statement
(lint/correctness/noUnnecessaryContinue)
[error] 636-636: Avoid the use of spread (...
) syntax on accumulators.
Spread syntax should be avoided on accumulators (like those in .reduce
) because it causes a time complexity of O(n^2)
.
Consider methods such as .splice or .push instead.
(lint/performance/noAccumulatingSpread)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Install dependencies / Yarn install & cache
- GitHub Check: Security Check
🔇 Additional comments (33)
packages/app-store/office365calendar/api/index.ts (1)
3-3
: LGTM: Clean API export additionThe export follows the established pattern and properly integrates the new webhook functionality into the API surface.
apps/api/v1/test/lib/selected-calendars/_post.test.ts (2)
96-97
: LGTM: Test mocks updated for schema consistencyThe addition of
outlookSubscriptionId
andoutlookSubscriptionExpiration
fields to the mock data correctly aligns with the database schema updates, ensuring test coverage includes the expanded Office365 calendar functionality.
143-144
: LGTM: Consistent mock data updatesThe mock data in both test cases now includes the new Outlook subscription fields, maintaining consistency across the test suite.
packages/prisma/migrations/20250520104336_feature_outlook_cache_21050/migration.sql (2)
8-9
: LGTM: Appropriate column types chosenThe migration correctly uses
TIMESTAMPTZ
for the expiration field (enabling proper date operations) andTEXT
for the subscription ID field.
12-12
: Verify compatibility with subscription sharing patternBased on the retrieved learnings, Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. This unique constraint on
[outlookSubscriptionId, eventTypeId]
may conflict with that pattern if multiple event types are meant to share the same Outlook subscription ID.Please verify whether this unique constraint aligns with the intended subscription sharing behavior mentioned in the learnings. If subscription sharing is intended, this constraint may need adjustment.
packages/features/calendar-cache/CalendarCache.md (3)
6-6
: LGTM: Documentation correctly updated for dual calendar supportThe criteria for unwatched calendars now properly includes both Google and Outlook subscription checks, accurately reflecting the expanded functionality.
11-11
: LGTM: Expiration logic updated for both calendar typesThe documentation correctly describes checking both
googleChannelExpiration
andoutlookSubscriptionExpiration
for subscription renewal logic.
17-17
: LGTM: Webhook documentation updatedThe addition of
office365calendar/api/webhook
to the webhook files list correctly documents the new Office365 webhook handler.turbo.json (3)
62-62
: LGTM: Microsoft webhook token added to web build environmentThe addition of
MICROSOFT_WEBHOOK_TOKEN
to the web build environment correctly supports the new Office365 webhook functionality.
139-139
: LGTM: Microsoft webhook token added to website build environmentConsistent addition of the webhook token to the website build environment maintains parity with the web build configuration.
496-500
: LGTM: E2E test environment variables addedThe addition of Outlook calendar E2E test variables (
MICROSOFT_WEBHOOK_TOKEN
and the fourE2E_TEST_OUTLOOK_CALENDAR_*
variables) properly supports comprehensive testing of the Office365 calendar integration.packages/prisma/schema.prisma (2)
868-869
: LGTM! New fields follow established patterns.The addition of
outlookSubscriptionId
andoutlookSubscriptionExpiration
fields mirrors the existing Google Calendar subscription pattern, providing consistency in the schema design.
891-891
: Unique constraint appropriately supports subscription sharing.The unique constraint on
outlookSubscriptionId
andeventTypeId
is correctly designed to allow the same subscription ID to be reused across multiple event types, which aligns with the intentional subscription sharing pattern described in the retrieved learnings.packages/app-store/office365calendar/zod.ts (1)
13-31
: Webhook payload schema is well-structured and addresses previous concerns.The schema comprehensively validates Microsoft Graph webhook payloads with proper type constraints. The
subscriptionExpirationDateTime
field correctly uses.datetime()
validation as suggested in previous reviews, ensuring only valid ISO-8601 datetime strings are accepted.playwright.config.ts (1)
28-36
: Cross-platform environment variable handling is well-implemented.The implementation correctly handles the differences between Windows and Unix systems for setting environment variables in the web server command. The Windows syntax using
set VAR=value &&
and Unix syntax usingVAR='value'
are both appropriate for their respective platforms..env.example (1)
168-172
: Reminder: Replace test credentials with placeholders before final release.As per the development plan, ensure that the actual test account credentials are replaced with placeholder values before the final release. The current empty strings are appropriate for the example file.
packages/lib/server/repository/selectedCalendar.ts (4)
31-36
: Type extension looks good!The
outlookSubscriptionId
field follows the same pattern asgoogleChannelId
, maintaining consistency in the filtering API.
174-224
: Well-structured integration of Office365 calendar support!The OR condition cleanly separates the logic for each calendar type. Note that Office365 calendars skip error retry logic while Google calendars have sophisticated retry mechanisms - ensure this difference is intentional based on the respective API behaviors.
231-277
: Consistent implementation for unwatching calendars!The unwatching logic properly handles both calendar types with appropriate filtering for teams without the calendar-cache feature.
299-389
: Great addition of Office365 methods with proper field selection!The implementation:
- Follows consistent patterns across all three methods
- Properly addresses the previous concern about field-level selection by explicitly selecting required fields from
selectedCalendars
- Maintains consistency with the repository pattern
packages/app-store/office365calendar/lib/Office365CalendarCache.ts (1)
13-22
: Clean constructor implementation!Good use of dependency injection pattern. The nullable userId is properly typed and handled throughout the class.
packages/app-store/office365calendar/api/webhook.ts (3)
23-221
: Excellent webhook processing implementation!The handler demonstrates several best practices:
- Proper payload validation with Zod
- Security validation via clientState
- Idempotent processing with duplicate detection
- Efficient batch processing grouped by credential
- Comprehensive error tracking and reporting
239-263
: Secure handling of validation tokens!Good security practices:
- Validation token is properly redacted in logs
- Error messages don't expose sensitive query parameters
- Immediate response for validation requests as required by Microsoft
268-279
: Clever use of conditional body parsing!The function-based bodyParser configuration efficiently skips unnecessary parsing for validation requests. Good to see this is tested and working, even if undocumented.
packages/app-store/office365calendar/__tests__/unit_tests/shared/error-handling.utils.ts (1)
1-241
: Excellent test utilities for error handling!This module provides comprehensive error testing infrastructure:
- Well-defined error scenarios covering network, auth, rate limiting, etc.
- Reusable mock factories that properly simulate HTTP error responses
- Clear assertion helpers that standardize error validation across tests
- Batch operation scenarios for complex error cases
This will significantly improve test maintainability and coverage.
packages/app-store/office365calendar/__tests__/mock_utils/mocks.ts (4)
1-61
: Well-implemented mock Response class!Good fixes from previous review:
MockTeamMember
interface properly defined (no missing type issues)json()
method correctly returns parsed objects, not strings- Proper Response interface implementation with status-based
ok
property
68-115
: Clean mock implementation with proper routing!The fetcher mock properly handles all major endpoints and returns correctly structured responses for batch operations.
117-459
: Comprehensive mock response coverage!Excellent set of mock responses covering:
- Success cases for all API operations
- Error scenarios (401, 429, 500)
- Pagination support
- Proper status codes and headers
543-599
: Good use of deterministic patterns for test scenarios!The mock team scenarios use deterministic patterns (modulo operations) instead of random values, ensuring reproducible and stable tests. This addresses previous concerns about test flakiness.
packages/app-store/office365calendar/tests/testUtils.ts (1)
93-96
: Verify SERVICE_ACCOUNT_ENCRYPTION_KEY is defined.The code uses
SERVICE_ACCOUNT_ENCRYPTION_KEY!
with a non-null assertion but doesn't validate it exists.+if (!SERVICE_ACCOUNT_ENCRYPTION_KEY) { + throw new Error("SERVICE_ACCOUNT_ENCRYPTION_KEY is required for encryption"); +} encrypted_credentials: symmetricEncrypt( JSON.stringify({ private_key: client_secret }), SERVICE_ACCOUNT_ENCRYPTION_KEY! ),packages/app-store/office365calendar/lib/CalendarService.ts (2)
73-81
: Good practice: Environment validation at startup.Excellent defensive programming by validating required environment variables during service initialization. This fail-fast approach prevents runtime errors.
969-1026
: Well-implemented chunked availability fetching.The implementation properly handles large date ranges by splitting them into 90-day chunks, with good error handling that allows partial failures without breaking the entire operation.
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts (1)
638-708
: Well-structured lifecycle test!This comprehensive test effectively validates the complete subscription lifecycle (create → renew → delete) in a single flow, providing good integration coverage.
packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts
Outdated
Show resolved
Hide resolved
packages/app-store/office365calendar/lib/Office365CalendarCache.ts
Outdated
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/shared/team-scenarios.utils.ts
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/TeamEvents.test.ts
Outdated
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
Outdated
Show resolved
Hide resolved
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
Outdated
Show resolved
Hide resolved
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.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts (1)
4-4
: Remove unused logger importThe logger is imported but never used in the test file, violating the no-unused-vars ESLint rule.
🧹 Nitpick comments (1)
packages/app-store/office365calendar/lib/Office365CalendarCache.ts (1)
201-201
: Consider more efficient deep cloning approachWhile
JSON.parse(JSON.stringify())
works, consider using a more efficient deep cloning library likestructuredClone()
(if available) or a dedicated utility for better performance.- value: JSON.parse(JSON.stringify(busyTimes)), + value: structuredClone(busyTimes),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/app-store/office365calendar/__tests__/dates.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts
(1 hunks)packages/app-store/office365calendar/lib/Office365CalendarCache.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/app-store/office365calendar/tests/dates.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
**/*.ts
: For Prisma queries, only select data you need; never useinclude
, always useselect
Ensure thecredential.key
field is never returned from tRPC endpoints or APIs
Files:
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts
packages/app-store/office365calendar/lib/Office365CalendarCache.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()
in hot paths like loops
Files:
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts
packages/app-store/office365calendar/lib/Office365CalendarCache.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: For large pull requests (>500 lines changed or >10 files touched), advise splitting into smaller, focused PRs by feature, layer, dependency chain, or file/module
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts (3)
Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.{ts,tsx} : Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc()
in hot paths like loops
Learnt from: vijayraghav-io
PR: #21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.779Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts (3)
Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: vijayraghav-io
PR: #21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.779Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : Ensure the credential.key
field is never returned from tRPC endpoints or APIs
packages/app-store/office365calendar/lib/Office365CalendarCache.ts (2)
Learnt from: vijayraghav-io
PR: #21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.{ts,tsx} : Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc()
in hot paths like loops
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Install dependencies / Yarn install & cache
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (15)
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts (5)
27-46
: LGTM - Well-structured test setupThe test setup properly clears mocks, provides realistic mock data, and handles dynamic module mocking appropriately.
50-89
: LGTM - Comprehensive cache hit testThis test correctly validates that cache hits return cached data without making API calls, with proper assertions for cache lookup parameters.
91-122
: LGTM - Proper cache miss validationThis test correctly verifies that cache misses trigger fresh API calls and that the cache lookup is properly attempted first.
166-196
: LGTM - Comprehensive cache update testThis test properly validates the cache update mechanism, verifying both fresh data fetching and cache storage operations.
198-248
: LGTM - Robust concurrent operations testThis test properly validates that the cache system can handle concurrent updates from multiple credentials without conflicts, with comprehensive assertions for both operations.
packages/app-store/office365calendar/__tests__/unit_tests/CalendarService.test.ts (6)
1-18
: LGTM - Proper imports and logger usageAll imports are appropriately used, including the logger which is properly instantiated as a sub-logger.
47-61
: LGTM - Invalid credential test correctly configuredThe invalid field is properly set to
true
for testing invalid credentials, and the test correctly verifies that construction doesn't throw.
64-186
: LGTM - Comprehensive single calendar operationsThese tests properly validate core CRUD operations with realistic test data and appropriate API call verification.
188-262
: LGTM - Excellent batch operations validationThese tests properly validate critical performance optimizations including batch API calls and pagination handling, with appropriate performance metrics validation.
265-290
: LGTM - Proper calendar listing validationThis test correctly validates the calendar listing functionality with appropriate API call expectations and endpoint verification.
293-344
: LGTM - Comprehensive date and timezone validationThese tests properly validate date range handling and timezone conversions, which are critical for accurate calendar operations across different time zones.
packages/app-store/office365calendar/lib/Office365CalendarCache.ts (4)
13-19
: LGTM - Well-designed custom error classThe custom error class properly extends Error and provides helpful context including operation and original error information.
21-53
: LGTM - Robust type validationThe type guard comprehensively validates cached data structure with proper handling of required fields, optional fields, and edge cases.
66-154
: LGTM - Improved error handling and cache validationThe method now properly throws custom errors instead of silently returning empty arrays, and includes robust cache validation with fallback to fresh data fetch.
156-214
: LGTM - Smart cache update implementationThe method implements intelligent cache refresh logic with age-based thresholds, proper filtering, and comprehensive error handling.
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
Outdated
Show resolved
Hide resolved
067fcef
to
2087d47
Compare
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.
Actionable comments posted: 2
♻️ Duplicate comments (7)
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts (4)
153-194
: Use real webhook handler instead of inline mock.This test creates an inline mock implementation instead of using the imported webhook handler. This pattern doesn't validate the actual handler behavior for empty notifications.
Replace the inline mock with the real webhook handler:
- const webhookHandler = vi.fn().mockImplementation((req, res) => { - if (req.method === "POST" && req.body.value && req.body.value.length === 0) { - res.status(200).json({ - message: "No notifications to process", - processed: 0, - failed: 0, - skipped: 0, - errors: [], - }); - } - }); - - webhookHandler(mockRequest, mockResponse); + await webhookHandler(mockRequest, mockResponse);
197-342
: Replace mock implementations with real webhook handler testing.Both deduplication tests create inline mock implementations that simulate deduplication logic instead of testing the actual webhook handler. This approach doesn't validate the real implementation's deduplication behavior.
Update both tests to use the imported webhook handler and verify deduplication through the actual response:
- const webhookHandler = vi.fn().mockImplementation((req, res) => { - // Mock deduplication logic... - }); - - webhookHandler(mockRequest, mockResponse); + await webhookHandler(mockRequest, mockResponse);Then verify the response contains the expected deduplication metrics from the real handler.
344-507
: Test real error handling instead of mock implementations.All error handling tests create inline mock implementations that simulate error scenarios instead of testing how the actual webhook handler behaves under error conditions.
Replace the mock implementations with proper setup to trigger real error conditions and test the actual webhook handler's response:
- const webhookHandler = vi.fn().mockImplementation((req, res) => { - // Mock error handling... - }); + // Set up mocks to cause the real handler to encounter errors + vi.mocked(SelectedCalendarRepository.findManyByOutlookSubscriptionIds).mockRejectedValue(new Error("Cache update failed")); + + await webhookHandler(mockRequest, mockResponse);
509-726
: Test actual security and performance behavior.Both security and performance test sections create inline mock implementations instead of testing the real webhook handler's security validation and performance characteristics.
Replace mock implementations with tests that exercise the real webhook handler:
- For security tests: Set up proper/invalid signatures and test the real handler's validation
- For performance tests: Use the real handler with large payloads and measure actual processing time
This ensures the tests validate the actual implementation's security and performance behavior.
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts (3)
40-41
: Avoid accessing private methods in tests.Using
as any
to access the privatefetcher
method breaks encapsulation and makes tests fragile to implementation changes.Consider refactoring to use proper mocking strategies:
- Mock at the network level using vitest-fetch-mock
- Use dependency injection to provide a test double
- Create a test-friendly interface that exposes necessary functionality
This will make tests more robust and maintainable.
174-175
: Private method access continues to be problematic.The same encapsulation-breaking pattern of accessing the private
fetcher
method withas any
continues throughout the test suite.This architectural issue should be addressed consistently across all tests in this file for better maintainability and robustness.
272-273
: Consistent architectural issue persists.The private method access pattern continues, making the entire test suite fragile to implementation changes.
Consider a comprehensive refactor of the testing approach to eliminate all
as any
usage for accessing private methods.
🧹 Nitpick comments (1)
packages/app-store/office365calendar/lib/CalendarService.ts (1)
971-1028
: Consider Day.js performance impact in chunked availability.The method uses Day.js extensively for date operations. For performance-critical availability calculations, consider using native Date methods or Day.js
.utc()
to reduce overhead, especially when processing multiple chunks.private async getChunkedAvailability( - startDate: dayjs.Dayjs, - endDate: dayjs.Dayjs, + startDate: Date, + endDate: Date, calendarIds: string[], shouldServeCache?: boolean ): Promise<EventBusyDate[]> { - const diffInDays = endDate.diff(startDate, "days"); + const diffInDays = Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24)); if (diffInDays <= 90) { return calendarCache.getCacheOrFetchAvailability( - startDate.toISOString(), - endDate.toISOString(), + startDate.toISOString(), + endDate.toISOString(), calendarIds, shouldServeCache ); } - const chunks = this.chunkDateRange(startDate.toDate(), endDate.toDate()); + const chunks = this.chunkDateRange(startDate, endDate);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/TeamEvents.test.ts
(1 hunks)packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
(1 hunks)packages/app-store/office365calendar/lib/CalendarService.ts
(8 hunks)packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/app-store/office365calendar/tests/unit_tests/TeamEvents.test.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
**/*.ts
: For Prisma queries, only select data you need; never useinclude
, always useselect
Ensure thecredential.key
field is never returned from tRPC endpoints or APIs
Files:
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
packages/app-store/office365calendar/lib/CalendarService.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()
in hot paths like loops
Files:
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
packages/app-store/office365calendar/lib/CalendarService.ts
**/*Service.ts
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Service files must include
Service
suffix, use PascalCase matching exported class, and avoid generic names (e.g.,MembershipService.ts
)
Files:
packages/app-store/office365calendar/lib/CalendarService.ts
🧠 Learnings (9)
📓 Common learnings
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: For large pull requests (>500 lines changed or >10 files touched), advise splitting into smaller, focused PRs by feature, layer, dependency chain, or file/module
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
📚 Learning: the office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is spec...
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Applied to files:
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
packages/app-store/office365calendar/lib/CalendarService.ts
📚 Learning: applies to **/*.{ts,tsx} : flag excessive day.js use in performance-critical code; prefer native dat...
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.{ts,tsx} : Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js `.utc()` in hot paths like loops
Applied to files:
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
packages/app-store/office365calendar/lib/CalendarService.ts
📚 Learning: applies to **/*.tsx : always use `t()` for text localization in frontend code; direct text embedding...
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.tsx : Always use `t()` for text localization in frontend code; direct text embedding should trigger a warning
Applied to files:
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
📚 Learning: for microsoft graph webhook handlers, when dealing with internal configuration errors (like missing ...
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:50-60
Timestamp: 2025-07-18T17:54:04.613Z
Learning: For Microsoft Graph webhook handlers, when dealing with internal configuration errors (like missing MICROSOFT_WEBHOOK_TOKEN), it's better to return 200 OK with errors tracked in the response body rather than throwing 5xx errors. This prevents retry storms from Microsoft Graph and maintains webhook subscription health, while still providing visibility through error logs and structured error responses.
Applied to files:
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts
packages/app-store/office365calendar/lib/CalendarService.ts
📚 Learning: for e2e integration tests that require real third-party service credentials (like outlook calendar),...
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: .env.example:354-357
Timestamp: 2025-07-18T08:49:18.779Z
Learning: For E2E integration tests that require real third-party service credentials (like Outlook calendar), it's acceptable to temporarily include actual test account credentials in .env.example during feature development and validation, provided there's a clear plan to replace them with placeholder values before final release. Test credentials should be for dedicated test tenants/accounts, not production systems.
Applied to files:
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
📚 Learning: applies to **/*.ts : ensure the `credential.key` field is never returned from trpc endpoints or apis...
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : Ensure the `credential.key` field is never returned from tRPC endpoints or APIs
Applied to files:
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts
packages/app-store/office365calendar/lib/CalendarService.ts
📚 Learning: the outlook calendar integration in cal.com intentionally reuses subscription ids across multiple ev...
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: The Outlook Calendar integration in Cal.com intentionally reuses subscription IDs across multiple event types for efficiency. The `upsertSelectedCalendarsForEventTypeIds` method creates separate SelectedCalendar records for each eventTypeId, all sharing the same outlookSubscriptionId. This subscription sharing pattern means that unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be applied as they would prevent this intended functionality.
Applied to files:
packages/app-store/office365calendar/lib/CalendarService.ts
📚 Learning: in cal.com's calendar integration, both google calendar and outlook calendar are designed to allow m...
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/prisma/schema.prisma:891-891
Timestamp: 2025-07-18T08:47:01.264Z
Learning: In Cal.com's calendar integration, both Google Calendar and Outlook Calendar are designed to allow multiple eventTypeIds to share the same subscription ID (googleChannelId or outlookSubscriptionId). This is an intentional design pattern to reuse existing subscriptions for efficiency rather than creating separate subscriptions for each event type. Therefore, unique constraints like `@@unique([outlookSubscriptionId, eventTypeId])` should not be added as they would break this subscription sharing functionality.
Applied to files:
packages/app-store/office365calendar/lib/CalendarService.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (23)
packages/app-store/office365calendar/__tests__/unit_tests/CalendarCache.test.ts (3)
1-46
: LGTM! Well-structured test setup.The test setup follows good practices with comprehensive mocking of external dependencies and proper cleanup in afterEach.
48-163
: Excellent cache behavior validation.The test scenarios comprehensively cover cache hits, misses, and expiration handling. The cache expiration test correctly uses a 6-minute offset to exceed the 5-minute TTL, ensuring proper expiration detection.
165-250
: Robust concurrent cache testing.The cache update tests effectively validate both single updates and concurrent operations. The concurrent test properly simulates real-world scenarios by creating separate credentials and services, ensuring thread safety of the cache implementation.
packages/app-store/office365calendar/__tests__/unit_tests/Webhook.test.ts (1)
43-80
: Good webhook validation testing.These tests properly use the actual webhook handler to test validation token processing, which ensures the real implementation behavior is validated.
packages/app-store/office365calendar/__tests__/unit_tests/SubscriptionManager.test.ts (2)
469-472
: Good improvement - testing actual implementation.The test now calls the actual
getSubscriptionsNeedingRenewal
method instead of reimplementing the renewal threshold logic, which properly validates the real implementation.
642-644
: Excellent lifecycle integration testing.The complete subscription lifecycle test provides valuable end-to-end validation of create, renew, and delete operations working together properly.
packages/app-store/office365calendar/lib/Office365SubscriptionManager.ts (5)
1-32
: Well-structured class with proper encapsulation.The class design follows good practices with appropriate dependency injection, reasonable TTL constants, and proper handling of different Microsoft Graph user endpoint formats.
34-85
: Excellent subscription creation with proper security.The method properly handles subscription creation with comprehensive error handling and correctly redacts sensitive clientState information in logs, addressing previous security concerns.
87-128
: Proper renewal and deletion implementation.Both methods are correctly implemented with appropriate error handling. The delete method properly treats 404 responses as success, which is the correct behavior for idempotent deletion operations.
130-142
: Clean subscription listing implementation.The method correctly handles the Microsoft Graph response format and provides appropriate fallback behavior.
144-155
: Proper renewal threshold logic.The method correctly identifies subscriptions needing renewal based on expiration time and threshold, enabling proactive subscription management.
packages/app-store/office365calendar/lib/CalendarService.ts (12)
73-81
: Excellent environment validation at startup.The fail-fast approach with environment validation in the constructor prevents runtime issues and provides clear error messages for missing configuration. This is a solid defensive programming practice.
190-198
: Good caching optimization for user data.The caching of
azureUserId
and improved error handling for missinguserPrincipalName
will reduce API calls and provide better debugging information.
277-286
: Efficient caching implementation for getUserEndpoint.The caching of
cachedUserEndpoint
is a smart optimization that will prevent repeated calculations of the same endpoint.
345-383
: Well-structured availability method refactor.The addition of caching parameters, comprehensive logging, and delegation to chunked availability processing improves both functionality and maintainability. The early return for empty calendar IDs is a good optimization.
488-496
: Appropriate visibility change for external usage.Making the
fetcher
method public enables the caching and webhook components to reuse the authenticated HTTP client, which is a good architectural decision.
620-640
: Performance optimization successfully implemented.The use of
Array.prototype.push.apply
instead of spread syntax addresses the O(n²) complexity issue identified in previous reviews. The addition of source metadata to busy times will improve debugging capabilities.
651-676
: Improved error handling with security considerations.The enhanced error logging with structured information while omitting the error body prevents sensitive information exposure, addressing previous security concerns.
678-744
: Robust subscription management with efficient reuse.The
watchCalendar
method correctly implements subscription sharing across event types as intended by the architecture. The logic for checking existing subscriptions, creating new ones when needed, and handling errors is well-structured.
746-832
: Comprehensive cleanup logic in unwatchCalendar.The unwatching logic properly handles the complex scenario of shared subscriptions, only deleting from Microsoft when no other event types are using the subscription. The cache refresh for remaining calendars is a thoughtful touch.
834-852
: Well-designed cache refresh method.The
fetchAvailabilityAndSetCache
method properly filters calendars by integration and handles errors gracefully, making it suitable for webhook-triggered updates.
854-904
: Comprehensive direct availability fetching.The
fetchAvailability
method provides a clean interface for direct API calls with proper error handling and reuses existing batch processing logic effectively.
1030-1047
: Simple and effective date chunking utility.The
chunkDateRange
method provides a clean way to split large date ranges into manageable chunks. The 90-day default chunk size is reasonable for API rate limiting.
Pull Request: Office365 Calendar Cache & Webhook System
Fixes: Outlook Cache – Bounty-to-Hire #21050
/claim Outlook Cache – Bounty-to-Hire #21050
@maintainer-username - Please attach below labels.
Labels :
bounty claim
,area: calendar
,community
,.env changes
,feature
,migrations
,teams
,$500
💎 Bounty
calendar-apps
community
✨ feature
teams
webhooks
$500
Review from a Team member: @PeerRich, @pumfleet , @hbjORbj @hariombalhara , @zomars , @sean-brydon , @keithwillcode , @joeauyeung
What This PR Solves
This PR tackles a critical performance bottleneck where every Office365 calendar was being checked on each booking page visit. Instead of making expensive API calls every time, we now cache availability data and update it in real-time through Microsoft's webhook notifications.
The Problem: Teams with multiple Office365 calendars experienced slow booking pages and high API costs due to repeated availability checks.
The Solution: A comprehensive caching system with webhook-driven updates that reduces API calls by 60-80% while maintaining real-time accuracy.
How It Works
Setup & Subscription Management
Office365SubscriptionManager
creates subscriptions for calendar change notifications (create/update/delete events)Real-time Update Flow
/api/integrations/office365calendar/webhook
)fetchAvailabilityAndSetCache()
with fresh availability dataIntelligent Cache Management
Instead of calling Microsoft's API every time someone visits a booking page (which was slow and expensive), we now store calendar availability in our database. The cache automatically:
Subscription Lifecycle
We built a subscription manager that prevents duplicate webhook subscriptions and integrates with the existing cron job system (through
/api/calendar-cache/cron?apiKey=
). This ensures we're not creating unnecessary subscriptions or missing important calendar updates.Key Changes Made
Key points:
Performance Results
Our Office365 calendar cache system delivers significant performance improvements:
Before this implementation:
After this implementation:
Manual Testing Evidence
Test Environment: OutlookTeam_Cache with Office365 calendars
Scenarios: Round Robin & Collective scheduling
Date Range: June 12-13, 2025
Time zone: Asia/Kolkata (UTC+5:30)
Collective Scheduling Results:
Round Robin Scheduling Results:
Cache Miss Handling:
Webhook Processing Architecture Analysis
During implementation, I discovered a significant optimization opportunity in our webhook processing. Currently, we process notifications sequentially, which creates bottlenecks during peak usage.
Current State: 10 simultaneous calendar changes take 23 seconds to process
Impact: Stale availability data for 20+ seconds, potential double bookings
Three Approaches Evaluated
Why We Chose Sequential Processing (The Smart Choice)
Reasons FOR Sequential Processing:
Production Safety First
Achieves Core Goals
Risk vs Reward Analysis
Why Promise.all is DANGEROUS (The Risky Trap):
Memory Explosion Risk
API Rate Limiting Disaster
Single Point of Failure
Database Connection Exhaustion
Reasons for NOT Implementing Parallel Processing Now:
Risk Management: Our current implementation works reliably and achieves the main goals (60-80% API reduction, 95%+ cache hit rate)
Time Constraints: Simple Promise.all would require more efforts of additional testing to validate memory usage, rate limiting, and error handling
Production Stability: Sequential processing is predictable and won't cause system crashes during peak load
Feature Completeness: We prioritized delivering a complete, working cache system over optimization
Incremental Improvement: Better to ship working solution now and optimize later with proper testing
When to Consider Scalable Webhook Processor:
Business Impact Analysis
Immediate Value (Current Implementation)
Recommendation Summary
Current PR (Ship This):
Next Release Priorities:
Business Value Timeline:
Mandatory Tasks (DO NOT REMOVE)
Environment Changes Required
How Should This Be Tested?
Manual Testing Steps
calendar-cache
andcalendar-cache-serve
to true?cal.cache=true
parameter to see cache effectsRedis Two-Tier Caching Enhancement
Current vs Enhanced Architecture
Current Database-Only Caching:
Enhanced Two-Tier Caching with Redis:
Business Benefits
Why Not Event Bus at This Stage?
Event Bus would be overkill because:
When Event Bus makes sense:
Current Priority: Focus on proven, simple solutions that deliver immediate business value. It's worth to analyze Redis Pub/Sub approach before implementing Two-Tier Caching with Redis.
Critical Issue Discovered: Time zone Normalization
Time zone Normalization Issue Discovered
During implementation, we discovered a critical time zone handling issue affecting multi-time zone teams using Round Robin scheduling.
Report to Stockholders : [ @PeerRich, @pumfleet , @hbjORbj @hariombalhara , @zomars , @sean-brydon , @keithwillcode , @joeauyeung
Reported by : @din-prajapati
Problem Description
Round Robin team scheduling shows incorrect availability when team members have Office365 calendars configured in different time zones. The system fails to normalize time zone formats, causing availability calculation errors.
The Problem in Plain English
Imagine you have a team with 3 members for Round Robin scheduling:
Here's the thing: All three meetings are happening at THE EXACT SAME TIME in the real world, just expressed in different time zones!
What Goes Wrong Without the Fix
Real-World Impact
This fix directly resolves the bug where:
getUserAvailability.ts
before Round Robin logicSimple Analogy
Think of it like converting currencies:
Without normalization: System thinks they have different amounts
With normalization: Convert all to USD → All have $1.20
Result: System correctly sees they all have the same amount!
Same with time zones - we convert everything to UTC so the system can compare apples to apples.
Steps to Reproduce
Impact Analysis
Technical Root Cause
Proposed Solution
Implement UTC normalization in
getUserAvailability.ts
to standardize all time zone formats before Round Robin calculations:Ask From Team
Proposed Solution: Implement UTC normalization in
getUserAvailability.ts
before Round Robin calculations.Business Risk: Potential double-bookings for distributed teams until fixed.
Summary by Merge
Added comprehensive caching and webhook support for Office365 calendar integration to dramatically improve performance and enable real-time availability updates, reducing Microsoft Graph API calls by 60-80%.
New Features:
Summary by cubic
Added Office365 calendar caching and webhook support to speed up booking pages and reduce Microsoft Graph API calls by 60-80%, with real-time availability updates.