import { CalendarSubscriptionService } from "@calcom/features/calendar-subscription/lib/CalendarSubscriptionService"; import { CalendarCacheEventRepository } from "@calcom/features/calendar-subscription/lib/cache/CalendarCacheEventRepository"; import { CalendarCacheEventService } from "@calcom/features/calendar-subscription/lib/cache/CalendarCacheEventService"; import { CalendarCacheWrapper } from "@calcom/features/calendar-subscription/lib/cache/CalendarCacheWrapper"; import { CalendarTelemetryWrapper } from "@calcom/features/calendar-subscription/lib/telemetry/CalendarTelemetryWrapper"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import logger from "@calcom/lib/logger"; import { isTelemetryEnabled } from "@calcom/lib/sentryWrapper"; import { prisma } from "@calcom/prisma"; import type { Calendar } from "@calcom/types/Calendar"; import type { CredentialForCalendarService } from "@calcom/types/Credential"; import { CalendarServiceMap } from "../calendar.services.generated"; const log = logger.getSubLogger({ prefix: ["CalendarManager"] }); export const getCalendar = async ( credential: CredentialForCalendarService | null, shouldServeCache?: boolean ): Promise => { if (!credential || !credential.key) return null; let { type: calendarType } = credential; if (calendarType?.endsWith("_other_calendar")) { calendarType = calendarType.split("_other_calendar")[0]; } // Backwards compatibility until CRM manager is created if (calendarType?.endsWith("_crm")) { calendarType = calendarType.split("_crm")[0]; } const calendarAppImportFn = CalendarServiceMap[calendarType.split("_").join("") as keyof typeof CalendarServiceMap]; if (!calendarAppImportFn) { log.warn(`calendar of type ${calendarType} is not implemented`); return null; } const calendarApp = await calendarAppImportFn; const CalendarService = calendarApp.default; if (!CalendarService || typeof CalendarService !== "function") { log.warn(`calendar of type ${calendarType} is not implemented`); return null; } // if shouldServeCache is not supplied, determine on the fly. if (typeof shouldServeCache === "undefined") { const featuresRepository = new FeaturesRepository(prisma); const [isCalendarSubscriptionCacheEnabled, isCalendarSubscriptionCacheEnabledForUser] = await Promise.all( [ featuresRepository.checkIfFeatureIsEnabledGlobally( CalendarSubscriptionService.CALENDAR_SUBSCRIPTION_CACHE_FEATURE ), featuresRepository.checkIfUserHasFeatureNonHierarchical( credential.userId as number, CalendarSubscriptionService.CALENDAR_SUBSCRIPTION_CACHE_FEATURE ), ] ); shouldServeCache = isCalendarSubscriptionCacheEnabled && isCalendarSubscriptionCacheEnabledForUser; log.debug("Cache feature flag check", { credentialId: credential.id, userId: credential.userId, isCalendarSubscriptionCacheEnabled, isCalendarSubscriptionCacheEnabledForUser, shouldServeCache, }); } const isCacheSupported = CalendarCacheEventService.isCalendarTypeSupported(calendarType); const originalCalendar = new CalendarService(credential as any); // Determine if we should use cache const useCache = isCacheSupported && shouldServeCache; // Build the calendar chain: original -> cache (if enabled) -> telemetry (if enabled) let calendar: Calendar = originalCalendar; if (useCache) { log.info(`Calendar Cache is enabled, using CalendarCacheWrapper for credential ${credential.id}`); const calendarCacheEventRepository = new CalendarCacheEventRepository(prisma); calendar = new CalendarCacheWrapper({ originalCalendar: calendar, calendarCacheEventRepository, }); } // Wrap ALL calendars with telemetry when telemetry is enabled // This provides consistent metrics for all calendar types if (isTelemetryEnabled()) { log.info( `Using CalendarTelemetryWrapper for credential ${credential.id} (cacheSupported: ${isCacheSupported}, cacheEnabled: ${useCache})` ); calendar = new CalendarTelemetryWrapper({ originalCalendar: calendar, calendarType, cacheSupported: isCacheSupported, cacheEnabled: useCache, credentialId: credential.id, }); } return calendar; };