From 300cd31efb8b5af2b97e2d10c2fa76ca2ce7c06d Mon Sep 17 00:00:00 2001 From: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:21:55 +0300 Subject: [PATCH] chore: redis cache for calendars in api v2 (#23622) * chore: implement redis cache for calendars api v2 * fixup! chore: implement redis cache for calendars api v2 * fixup! fixup! chore: implement redis cache for calendars api v2 * fix leverage genetic type of redis.get * refactor: address supalarry's PR feedback - Create CalendarsCacheService to separate cache responsibilities - Rename cache methods to be more descriptive (getConnectedAndDestinationCalendarsCache, setConnectedAndDestinationCalendarsCache) - Remove unused redisService injection from CalendarsController - Move all cache-related functionality to dedicated service Addresses comments 9, 10, and 11 from supalarry on PR #23622 Co-Authored-By: morgan@cal.com * refactor: address supalarry's latest PR feedback - Remove redundant deleteConnectedAndDestinationCalendarsCache from CalendarsService - Update controller to directly inject and use CalendarsCacheService - Extract TTL constant and remove manual JSON.stringify in cache service Co-Authored-By: morgan@cal.com * fix: update IcsFeedService to use CalendarsCacheService directly - Inject CalendarsCacheService into IcsFeedService constructor - Replace calendarsService.deleteCalendarCache with calendarsCacheService.deleteConnectedAndDestinationCalendarsCache - Completes the refactoring to eliminate all old cache method references Co-Authored-By: morgan@cal.com * fix: update destination-calendars and selected-calendars services to use CalendarsCacheService directly - Inject CalendarsCacheService in both service constructors - Replace calendarsService.deleteCalendarCache calls with calendarsCacheService.deleteConnectedAndDestinationCalendarsCache - Add CalendarsCacheService to module providers for proper dependency injection - Completes migration of all cache method references to use dedicated cache service Co-Authored-By: morgan@cal.com * chore: use CalendarsCacheService --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../ee/bookings/2024-04-15/bookings.module.ts | 2 + .../ee/bookings/2024-08-13/bookings.module.ts | 2 + .../v2/src/ee/calendars/calendars.module.ts | 5 +- .../controllers/calendars.controller.ts | 4 + .../services/calendars-cache.service.ts | 36 ++++++ .../calendars/services/calendars.service.ts | 18 ++- .../ee/calendars/services/ics-feed.service.ts | 9 +- .../event-types.module.ts | 5 +- apps/api/v2/src/ee/gcal/gcal.module.ts | 5 +- .../cal-unified-calendars.module.ts | 5 +- .../destination-calendars.module.ts | 5 +- .../services/destination-calendars.service.ts | 3 + .../oauth-clients/oauth-client.module.ts | 2 + .../selected-calendars.module.ts | 5 +- .../services/selected-calendars.service.ts | 6 +- apps/api/v2/swagger/documentation.json | 11 +- docs/api-reference/v2/openapi.json | 103 +++++++++++++++++- 17 files changed, 205 insertions(+), 21 deletions(-) create mode 100644 apps/api/v2/src/ee/calendars/services/calendars-cache.service.ts diff --git a/apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts b/apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts index 2f64282407..26ee747425 100644 --- a/apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts +++ b/apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts @@ -1,6 +1,7 @@ import { BookingsController_2024_04_15 } from "@/ee/bookings/2024-04-15/controllers/bookings.controller"; import { PlatformBookingsService } from "@/ee/bookings/shared/platform-bookings.service"; import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { EventTypesModule_2024_04_15 } from "@/ee/event-types/event-types_2024_04_15/event-types.module"; import { EventTypesModule_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.module"; @@ -41,6 +42,7 @@ import { Module } from "@nestjs/common"; OAuthClientUsersService, PlatformBookingsService, CalendarsService, + CalendarsCacheService, CredentialsRepository, AppsRepository, CalendarsRepository, diff --git a/apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts b/apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts index faa856e291..860b15428d 100644 --- a/apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts +++ b/apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts @@ -10,6 +10,7 @@ import { OutputBookingReferencesService_2024_08_13 } from "@/ee/bookings/2024-08 import { OutputBookingsService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/output.service"; import { PlatformBookingsService } from "@/ee/bookings/shared/platform-bookings.service"; import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { EventTypesModule_2024_04_15 } from "@/ee/event-types/event-types_2024_04_15/event-types.module"; import { EventTypesModule_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.module"; @@ -71,6 +72,7 @@ import { Module } from "@nestjs/common"; ApiKeysRepository, PlatformBookingsService, CalendarsService, + CalendarsCacheService, CredentialsRepository, AppsRepository, CalendarsRepository, diff --git a/apps/api/v2/src/ee/calendars/calendars.module.ts b/apps/api/v2/src/ee/calendars/calendars.module.ts index a45fae0648..4d467a4f46 100644 --- a/apps/api/v2/src/ee/calendars/calendars.module.ts +++ b/apps/api/v2/src/ee/calendars/calendars.module.ts @@ -3,6 +3,7 @@ import { BookingsRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/bookings import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; import { CalendarsController } from "@/ee/calendars/controllers/calendars.controller"; import { AppleCalendarService } from "@/ee/calendars/services/apple-calendar.service"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { GoogleCalendarService } from "@/ee/calendars/services/gcal.service"; import { IcsFeedService } from "@/ee/calendars/services/ics-feed.service"; @@ -10,16 +11,18 @@ import { OutlookService } from "@/ee/calendars/services/outlook.service"; import { AppsRepository } from "@/modules/apps/apps.repository"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; import { PrismaModule } from "@/modules/prisma/prisma.module"; +import { RedisModule } from "@/modules/redis/redis.module"; import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository"; import { TokensModule } from "@/modules/tokens/tokens.module"; import { UsersModule } from "@/modules/users/users.module"; import { Module } from "@nestjs/common"; @Module({ - imports: [PrismaModule, UsersModule, TokensModule], + imports: [PrismaModule, UsersModule, TokensModule, RedisModule], providers: [ CredentialsRepository, CalendarsService, + CalendarsCacheService, OutlookService, GoogleCalendarService, AppleCalendarService, diff --git a/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts b/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts index 9a84c8c3ad..f2d0441ac8 100644 --- a/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts +++ b/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts @@ -9,6 +9,7 @@ import { DeletedCalendarCredentialsOutputDto, } from "@/ee/calendars/outputs/delete-calendar-credentials.output"; import { AppleCalendarService } from "@/ee/calendars/services/apple-calendar.service"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { GoogleCalendarService } from "@/ee/calendars/services/gcal.service"; import { IcsFeedService } from "@/ee/calendars/services/ics-feed.service"; @@ -79,6 +80,7 @@ const calendarStateSchema = z.object({ export class CalendarsController { constructor( private readonly calendarsService: CalendarsService, + private readonly calendarsCacheService: CalendarsCacheService, private readonly outlookService: OutlookService, private readonly googleCalendarService: GoogleCalendarService, private readonly appleCalendarService: AppleCalendarService, @@ -307,6 +309,8 @@ export class CalendarsController { credentialId ); + this.calendarsCacheService.deleteConnectedAndDestinationCalendarsCache(user.id); + return { status: SUCCESS_STATUS, data: plainToClass( diff --git a/apps/api/v2/src/ee/calendars/services/calendars-cache.service.ts b/apps/api/v2/src/ee/calendars/services/calendars-cache.service.ts new file mode 100644 index 0000000000..c0bcc0c743 --- /dev/null +++ b/apps/api/v2/src/ee/calendars/services/calendars-cache.service.ts @@ -0,0 +1,36 @@ +import { RedisService } from "@/modules/redis/redis.service"; +import { Injectable } from "@nestjs/common"; + +import type { getConnectedDestinationCalendarsAndEnsureDefaultsInDb } from "@calcom/platform-libraries"; + +export const REDIS_CALENDARS_CACHE_KEY = (userId: number) => `apiv2:user:${userId}:calendars`; +export const CALENDARS_CACHE_TTL_MS = 10_000; + +type ConnectedDestinationCalendars = Awaited< + ReturnType +>; + +@Injectable() +export class CalendarsCacheService { + constructor(private readonly redisService: RedisService) {} + + async deleteConnectedAndDestinationCalendarsCache(userId: number) { + await this.redisService.del(REDIS_CALENDARS_CACHE_KEY(userId)); + } + + async getConnectedAndDestinationCalendarsCache(userId: number) { + const cachedResult = await this.redisService.get( + REDIS_CALENDARS_CACHE_KEY(userId) + ); + return cachedResult; + } + + async setConnectedAndDestinationCalendarsCache( + userId: number, + calendars: ConnectedDestinationCalendars + ): Promise { + await this.redisService.set(REDIS_CALENDARS_CACHE_KEY(userId), calendars, { + ttl: CALENDARS_CACHE_TTL_MS, + }); + } +} diff --git a/apps/api/v2/src/ee/calendars/services/calendars.service.ts b/apps/api/v2/src/ee/calendars/services/calendars.service.ts index c57608c903..676c05d419 100644 --- a/apps/api/v2/src/ee/calendars/services/calendars.service.ts +++ b/apps/api/v2/src/ee/calendars/services/calendars.service.ts @@ -1,4 +1,5 @@ import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { AppsRepository } from "@/modules/apps/apps.repository"; import { CredentialsRepository, @@ -37,7 +38,8 @@ export class CalendarsService { private readonly appsRepository: AppsRepository, private readonly calendarsRepository: CalendarsRepository, private readonly dbWrite: PrismaWriteService, - private readonly selectedCalendarsRepository: SelectedCalendarsRepository + private readonly selectedCalendarsRepository: SelectedCalendarsRepository, + private readonly calendarsCacheService: CalendarsCacheService ) {} private buildNonDelegationCredentials(credentials: TCredential[]) { @@ -52,11 +54,17 @@ export class CalendarsService { } async getCalendars(userId: number) { + const cachedResult = await this.calendarsCacheService.getConnectedAndDestinationCalendarsCache(userId); + + if (cachedResult) { + return cachedResult; + } + const userWithCalendars = await this.usersRepository.findByIdWithCalendars(userId); if (!userWithCalendars) { throw new NotFoundException("User not found"); } - return getConnectedDestinationCalendarsAndEnsureDefaultsInDb({ + const result = await getConnectedDestinationCalendarsAndEnsureDefaultsInDb({ user: { ...userWithCalendars, allSelectedCalendars: userWithCalendars.selectedCalendars, @@ -68,6 +76,10 @@ export class CalendarsService { eventTypeId: null, prisma: this.dbWrite.prisma as unknown as PrismaClient, }); + console.log("saving cache", JSON.stringify(result)); + await this.calendarsCacheService.setConnectedAndDestinationCalendarsCache(userId, result); + + return result; } async getBusyTimes( @@ -187,6 +199,8 @@ export class CalendarsService { userId, calendarType ); + + await this.calendarsCacheService.deleteConnectedAndDestinationCalendarsCache(userId); } async checkCalendarCredentialValidity(userId: number, credentialId: number, type: string) { diff --git a/apps/api/v2/src/ee/calendars/services/ics-feed.service.ts b/apps/api/v2/src/ee/calendars/services/ics-feed.service.ts index 725d4bebae..047dfb5a82 100644 --- a/apps/api/v2/src/ee/calendars/services/ics-feed.service.ts +++ b/apps/api/v2/src/ee/calendars/services/ics-feed.service.ts @@ -1,7 +1,9 @@ import { ICSFeedCalendarApp } from "@/ee/calendars/calendars.interface"; import { CreateIcsFeedOutputResponseDto } from "@/ee/calendars/input/create-ics.output"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; +import { RedisService } from "@/modules/redis/redis.service"; import { BadRequestException, UnauthorizedException, Logger } from "@nestjs/common"; import { Injectable } from "@nestjs/common"; @@ -13,7 +15,9 @@ import { IcsFeedCalendarService } from "@calcom/platform-libraries/app-store"; export class IcsFeedService implements ICSFeedCalendarApp { constructor( private readonly calendarsService: CalendarsService, - private readonly credentialRepository: CredentialsRepository + private readonly calendarsCacheService: CalendarsCacheService, + private readonly credentialRepository: CredentialsRepository, + private readonly redisService: RedisService ) {} private logger = new Logger("IcsFeedService"); @@ -58,6 +62,9 @@ export class IcsFeedService implements ICSFeedCalendarApp { data.key, userId ); + + await this.calendarsCacheService.deleteConnectedAndDestinationCalendarsCache(userId); + return { status: SUCCESS_STATUS, data: { diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts index 23b8cda8e3..0f7bd4683b 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts @@ -1,4 +1,5 @@ import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { EventTypesController_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/controllers/event-types.controller"; import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.repository"; @@ -11,6 +12,7 @@ import { AppsRepository } from "@/modules/apps/apps.repository"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; import { MembershipsModule } from "@/modules/memberships/memberships.module"; import { PrismaModule } from "@/modules/prisma/prisma.module"; +import { RedisModule } from "@/modules/redis/redis.module"; import { SelectedCalendarsModule } from "@/modules/selected-calendars/selected-calendars.module"; import { TokensModule } from "@/modules/tokens/tokens.module"; import { UsersService } from "@/modules/users/services/users.service"; @@ -18,7 +20,7 @@ import { UsersRepository } from "@/modules/users/users.repository"; import { Module } from "@nestjs/common"; @Module({ - imports: [PrismaModule, MembershipsModule, TokensModule, SelectedCalendarsModule], + imports: [PrismaModule, MembershipsModule, TokensModule, SelectedCalendarsModule, RedisModule], providers: [ EventTypesRepository_2024_06_14, EventTypesService_2024_06_14, @@ -29,6 +31,7 @@ import { Module } from "@nestjs/common"; SchedulesRepository_2024_06_11, EventTypeResponseTransformPipe, CalendarsService, + CalendarsCacheService, CredentialsRepository, AppsRepository, CalendarsRepository, diff --git a/apps/api/v2/src/ee/gcal/gcal.module.ts b/apps/api/v2/src/ee/gcal/gcal.module.ts index ea7eae9e53..8a0319031d 100644 --- a/apps/api/v2/src/ee/gcal/gcal.module.ts +++ b/apps/api/v2/src/ee/gcal/gcal.module.ts @@ -1,4 +1,5 @@ import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { GcalController } from "@/ee/gcal/gcal.controller"; import { AppsRepository } from "@/modules/apps/apps.repository"; @@ -6,6 +7,7 @@ import { GCalService } from "@/modules/apps/services/gcal.service"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; import { OAuthClientModule } from "@/modules/oauth-clients/oauth-client.module"; import { PrismaModule } from "@/modules/prisma/prisma.module"; +import { RedisModule } from "@/modules/redis/redis.module"; import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository"; import { TokensModule } from "@/modules/tokens/tokens.module"; import { UsersRepository } from "@/modules/users/users.repository"; @@ -13,7 +15,7 @@ import { Module } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; @Module({ - imports: [PrismaModule, TokensModule, OAuthClientModule], + imports: [PrismaModule, TokensModule, OAuthClientModule, RedisModule], providers: [ AppsRepository, ConfigService, @@ -21,6 +23,7 @@ import { ConfigService } from "@nestjs/config"; SelectedCalendarsRepository, GCalService, CalendarsService, + CalendarsCacheService, UsersRepository, CalendarsRepository, ], diff --git a/apps/api/v2/src/modules/cal-unified-calendars/cal-unified-calendars.module.ts b/apps/api/v2/src/modules/cal-unified-calendars/cal-unified-calendars.module.ts index 0a5c4bfc3c..e9cebf0fcc 100644 --- a/apps/api/v2/src/modules/cal-unified-calendars/cal-unified-calendars.module.ts +++ b/apps/api/v2/src/modules/cal-unified-calendars/cal-unified-calendars.module.ts @@ -1,5 +1,6 @@ import { BookingReferencesRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/booking-references.repository"; import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { GoogleCalendarService as GCalService } from "@/ee/calendars/services/gcal.service"; import { AppsRepository } from "@/modules/apps/apps.repository"; @@ -8,13 +9,14 @@ import { GoogleCalendarService } from "@/modules/cal-unified-calendars/services/ import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; +import { RedisModule } from "@/modules/redis/redis.module"; import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository"; import { TokensModule } from "@/modules/tokens/tokens.module"; import { UsersRepository } from "@/modules/users/users.repository"; import { Module } from "@nestjs/common"; @Module({ - imports: [TokensModule], + imports: [TokensModule, RedisModule], providers: [ GCalService, GoogleCalendarService, @@ -22,6 +24,7 @@ import { Module } from "@nestjs/common"; BookingReferencesRepository_2024_08_13, CredentialsRepository, CalendarsService, + CalendarsCacheService, SelectedCalendarsRepository, PrismaReadService, PrismaWriteService, diff --git a/apps/api/v2/src/modules/destination-calendars/destination-calendars.module.ts b/apps/api/v2/src/modules/destination-calendars/destination-calendars.module.ts index 4610749075..87f383bf91 100644 --- a/apps/api/v2/src/modules/destination-calendars/destination-calendars.module.ts +++ b/apps/api/v2/src/modules/destination-calendars/destination-calendars.module.ts @@ -1,4 +1,5 @@ import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { AppsRepository } from "@/modules/apps/apps.repository"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; @@ -6,15 +7,17 @@ import { DestinationCalendarsController } from "@/modules/destination-calendars/ import { DestinationCalendarsRepository } from "@/modules/destination-calendars/destination-calendars.repository"; import { DestinationCalendarsService } from "@/modules/destination-calendars/services/destination-calendars.service"; import { PrismaModule } from "@/modules/prisma/prisma.module"; +import { RedisModule } from "@/modules/redis/redis.module"; import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository"; import { UsersRepository } from "@/modules/users/users.repository"; import { Module } from "@nestjs/common"; @Module({ - imports: [PrismaModule], + imports: [PrismaModule, RedisModule], providers: [ CalendarsRepository, CalendarsService, + CalendarsCacheService, DestinationCalendarsService, DestinationCalendarsRepository, UsersRepository, diff --git a/apps/api/v2/src/modules/destination-calendars/services/destination-calendars.service.ts b/apps/api/v2/src/modules/destination-calendars/services/destination-calendars.service.ts index a3a299eb44..828369ca1f 100644 --- a/apps/api/v2/src/modules/destination-calendars/services/destination-calendars.service.ts +++ b/apps/api/v2/src/modules/destination-calendars/services/destination-calendars.service.ts @@ -1,4 +1,5 @@ import { ConnectedCalendar, Calendar } from "@/ee/calendars/outputs/connected-calendars.output"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { DestinationCalendarsRepository } from "@/modules/destination-calendars/destination-calendars.repository"; import { Injectable, NotFoundException } from "@nestjs/common"; @@ -7,6 +8,7 @@ import { Injectable, NotFoundException } from "@nestjs/common"; export class DestinationCalendarsService { constructor( private readonly calendarsService: CalendarsService, + private readonly calendarsCacheService: CalendarsCacheService, private readonly destinationCalendarsRepository: DestinationCalendarsRepository ) {} @@ -60,6 +62,7 @@ export class DestinationCalendarsService { delegatedCalendar ? delegationCredentialId : undefined ); + this.calendarsCacheService.deleteConnectedAndDestinationCalendarsCache(userId); return { userId: updatedCalendarUserId, integration: updatedCalendarIntegration, diff --git a/apps/api/v2/src/modules/oauth-clients/oauth-client.module.ts b/apps/api/v2/src/modules/oauth-clients/oauth-client.module.ts index 095faa6f50..cfddc757c9 100644 --- a/apps/api/v2/src/modules/oauth-clients/oauth-client.module.ts +++ b/apps/api/v2/src/modules/oauth-clients/oauth-client.module.ts @@ -1,4 +1,5 @@ import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { EventTypesModule_2024_04_15 } from "@/ee/event-types/event-types_2024_04_15/event-types.module"; import { SchedulesModule_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/schedules.module"; @@ -49,6 +50,7 @@ import { JwtService } from "@nestjs/jwt"; TokensRepository, OAuthFlowService, CalendarsService, + CalendarsCacheService, CredentialsRepository, AppsRepository, CalendarsRepository, diff --git a/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts b/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts index 20b65eeb2e..10b1d37e40 100644 --- a/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts +++ b/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts @@ -1,4 +1,5 @@ import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { AppsRepository } from "@/modules/apps/apps.repository"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; @@ -7,6 +8,7 @@ import { OrganizationsMembershipRepository } from "@/modules/organizations/membe import { OrganizationsMembershipOutputService } from "@/modules/organizations/memberships/services/organizations-membership-output.service"; import { OrganizationsMembershipService } from "@/modules/organizations/memberships/services/organizations-membership.service"; import { PrismaModule } from "@/modules/prisma/prisma.module"; +import { RedisModule } from "@/modules/redis/redis.module"; import { SelectedCalendarsController } from "@/modules/selected-calendars/controllers/selected-calendars.controller"; import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository"; import { SelectedCalendarsService } from "@/modules/selected-calendars/services/selected-calendars.service"; @@ -14,11 +16,12 @@ import { UsersRepository } from "@/modules/users/users.repository"; import { Module } from "@nestjs/common"; @Module({ - imports: [PrismaModule], + imports: [PrismaModule, RedisModule], providers: [ SelectedCalendarsRepository, CalendarsRepository, CalendarsService, + CalendarsCacheService, UsersRepository, CredentialsRepository, AppsRepository, diff --git a/apps/api/v2/src/modules/selected-calendars/services/selected-calendars.service.ts b/apps/api/v2/src/modules/selected-calendars/services/selected-calendars.service.ts index 6af04f9c56..18230a54ad 100644 --- a/apps/api/v2/src/modules/selected-calendars/services/selected-calendars.service.ts +++ b/apps/api/v2/src/modules/selected-calendars/services/selected-calendars.service.ts @@ -1,3 +1,4 @@ +import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository"; import { OrganizationsMembershipService } from "@/modules/organizations/memberships/services/organizations-membership.service"; @@ -23,6 +24,7 @@ type SelectedCalendarsInputDelegationCredential = SelectedCalendarsInputDto & { export class SelectedCalendarsService { constructor( private readonly calendarsService: CalendarsService, + private readonly calendarsCacheService: CalendarsCacheService, private readonly selectedCalendarsRepository: SelectedCalendarsRepository, private readonly organizationsMembershipService: OrganizationsMembershipService, private readonly organizationsDelegationCredentialRepository: OrganizationsDelegationCredentialRepository @@ -50,6 +52,8 @@ export class SelectedCalendarsService { credentialId ); + await this.calendarsCacheService.deleteConnectedAndDestinationCalendarsCache(user.id); + return userSelectedCalendar; } @@ -122,7 +126,7 @@ export class SelectedCalendarsService { externalId, delegationCredentialId ); - + await this.calendarsCacheService.deleteConnectedAndDestinationCalendarsCache(user.id); return removedCalendarEntry; } catch (error) { if (error instanceof Error) { diff --git a/apps/api/v2/swagger/documentation.json b/apps/api/v2/swagger/documentation.json index 31ec7fe8f9..b820f66862 100644 --- a/apps/api/v2/swagger/documentation.json +++ b/apps/api/v2/swagger/documentation.json @@ -9132,8 +9132,6 @@ { "name": "credentialId", "in": "query", - "description": "The ID of the user's calendar credential used to access the calendar. Retrieve this from your connected calendar credentials via the `/v2/credentials` endpoint.", - "example": 135, "required": true, "schema": { "type": "number" @@ -9142,8 +9140,6 @@ { "name": "externalId", "in": "query", - "description": "The external calendar identifier from the calendar provider (e.g., email address for Google Calendar). This is returned when listing connected calendars.", - "example": "user@gmail.com", "required": true, "schema": { "type": "string" @@ -23642,7 +23638,12 @@ "afterEvent", "rescheduleEvent", "afterHostsCalVideoNoShow", - "afterGuestsCalVideoNoShow" + "afterGuestsCalVideoNoShow", + "bookingRejected", + "bookingRequested", + "bookingPaymentInitiated", + "bookingPaid", + "bookingNoShowUpdated" ] ], "description": "Trigger type for the workflow" diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index 5ec6fc073d..7058a064e5 100644 --- a/docs/api-reference/v2/openapi.json +++ b/docs/api-reference/v2/openapi.json @@ -8746,8 +8746,6 @@ { "name": "credentialId", "in": "query", - "description": "The ID of the user's calendar credential used to access the calendar. Retrieve this from your connected calendar credentials via the `/v2/credentials` endpoint.", - "example": 135, "required": true, "schema": { "type": "number" @@ -8756,8 +8754,6 @@ { "name": "externalId", "in": "query", - "description": "The external calendar identifier from the calendar provider (e.g., email address for Google Calendar). This is returned when listing connected calendars.", - "example": "user@gmail.com", "required": true, "schema": { "type": "string" @@ -20851,7 +20847,12 @@ "afterEvent", "rescheduleEvent", "afterHostsCalVideoNoShow", - "afterGuestsCalVideoNoShow" + "afterGuestsCalVideoNoShow", + "bookingRejected", + "bookingRequested", + "bookingPaymentInitiated", + "bookingPaid", + "bookingNoShowUpdated" ] }, "offset": { @@ -21149,6 +21150,61 @@ }, "required": ["type"] }, + "OnNoShowUpdateTriggerDto": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "bookingNoShowUpdated", + "description": "Trigger type for the workflow" + } + }, + "required": ["type"] + }, + "OnRejectedTriggerDto": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "bookingRejected", + "description": "Trigger type for the workflow" + } + }, + "required": ["type"] + }, + "OnRequestedTriggerDto": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "bookingRequested", + "description": "Trigger type for the workflow" + } + }, + "required": ["type"] + }, + "OnPaymentInitiatedTriggerDto": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "bookingPaymentInitiated", + "description": "Trigger type for the workflow" + } + }, + "required": ["type"] + }, + "OnPaidTriggerDto": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "bookingPaid", + "description": "Trigger type for the workflow" + } + }, + "required": ["type"] + }, "OnAfterCalVideoGuestsNoShowTriggerDto": { "type": "object", "properties": { @@ -21664,7 +21720,12 @@ "afterEvent", "rescheduleEvent", "afterHostsCalVideoNoShow", - "afterGuestsCalVideoNoShow" + "afterGuestsCalVideoNoShow", + "bookingRejected", + "bookingRequested", + "bookingPaymentInitiated", + "bookingPaid", + "bookingNoShowUpdated" ] ], "description": "Trigger type for the workflow" @@ -21732,6 +21793,21 @@ }, { "$ref": "#/components/schemas/OnAfterCalVideoHostsNoShowTriggerDto" + }, + { + "$ref": "#/components/schemas/OnRejectedTriggerDto" + }, + { + "$ref": "#/components/schemas/OnRequestedTriggerDto" + }, + { + "$ref": "#/components/schemas/OnPaidTriggerDto" + }, + { + "$ref": "#/components/schemas/OnPaymentInitiatedTriggerDto" + }, + { + "$ref": "#/components/schemas/OnNoShowUpdateTriggerDto" } ] }, @@ -22269,6 +22345,21 @@ }, { "$ref": "#/components/schemas/OnAfterCalVideoHostsNoShowTriggerDto" + }, + { + "$ref": "#/components/schemas/OnRejectedTriggerDto" + }, + { + "$ref": "#/components/schemas/OnRequestedTriggerDto" + }, + { + "$ref": "#/components/schemas/OnPaidTriggerDto" + }, + { + "$ref": "#/components/schemas/OnPaymentInitiatedTriggerDto" + }, + { + "$ref": "#/components/schemas/OnNoShowUpdateTriggerDto" } ] },