From 411cb33137c313c442904fcaf4cb66f70c03eb9f Mon Sep 17 00:00:00 2001 From: Guillim Date: Thu, 15 May 2025 14:12:32 +0200 Subject: [PATCH] [reconnect account] Reseting calendar status and stage on reconnect (#12061) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description When a calendar channel fails, its status is not reset during the reconnect step. In some cases, resetting is necessary—especially when we’ve deployed a fix and users try to reconnect their accounts after the patch. ## Why reseting to initial state Our processes are idempotent, so we can safely set the status to null to restart the flow. This approach covers all cases and avoids edge conditions caused by inconsistent statuses. Fixes : https://github.com/twentyhq/twenty/issues/12026 --- .../auth/services/google-apis.service.ts | 41 ++++++++++++++++++ .../auth/services/microsoft-apis.service.ts | 42 +++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index 74675a75c..742e77dca 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -20,6 +20,7 @@ import { CalendarEventListFetchJobData, } from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job'; import { + CalendarChannelSyncStage, CalendarChannelVisibility, CalendarChannelWorkspaceEntity, } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; @@ -305,6 +306,46 @@ export class GoogleAPIsService { })), workspaceId, }); + + const calendarChannels = await calendarChannelRepository.find({ + where: { connectedAccountId: newOrExistingConnectedAccountId }, + }); + + const calendarChannelUpdates = await calendarChannelRepository.update( + { + connectedAccountId: newOrExistingConnectedAccountId, + }, + { + syncStage: + CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING, + syncStatus: null, + syncCursor: '', + syncStageStartedAt: null, + }, + manager, + ); + + const calendarChannelMetadata = + await this.objectMetadataRepository.findOneOrFail({ + where: { nameSingular: 'calendarChannel', workspaceId }, + }); + + this.workspaceEventEmitter.emitDatabaseBatchEvent({ + objectMetadataNameSingular: 'calendarChannel', + action: DatabaseEventAction.UPDATED, + events: calendarChannels.map((calendarChannel) => ({ + recordId: calendarChannel.id, + objectMetadata: calendarChannelMetadata, + properties: { + before: calendarChannel, + after: { + ...calendarChannel, + ...calendarChannelUpdates.raw[0], + }, + }, + })), + workspaceId, + }); } }, ); diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts index abda6711d..1e908595c 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/microsoft-apis.service.ts @@ -20,6 +20,7 @@ import { CalendarEventListFetchJobData, } from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job'; import { + CalendarChannelSyncStage, CalendarChannelVisibility, CalendarChannelWorkspaceEntity, } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; @@ -333,6 +334,47 @@ export class MicrosoftAPIsService { })), workspaceId, }); + + // now for the calendar channels + const calendarChannels = await calendarChannelRepository.find({ + where: { connectedAccountId: newOrExistingConnectedAccountId }, + }); + + const calendarChannelUpdates = await calendarChannelRepository.update( + { + connectedAccountId: newOrExistingConnectedAccountId, + }, + { + syncStage: + CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING, + syncStatus: null, + syncCursor: '', + syncStageStartedAt: null, + }, + manager, + ); + + const calendarChannelMetadata = + await this.objectMetadataRepository.findOneOrFail({ + where: { nameSingular: 'calendarChannel', workspaceId }, + }); + + this.workspaceEventEmitter.emitDatabaseBatchEvent({ + objectMetadataNameSingular: 'calendarChannel', + action: DatabaseEventAction.UPDATED, + events: calendarChannels.map((calendarChannel) => ({ + recordId: calendarChannel.id, + objectMetadata: calendarChannelMetadata, + properties: { + before: calendarChannel, + after: { + ...calendarChannel, + ...calendarChannelUpdates.raw[0], + }, + }, + })), + workspaceId, + }); } }, );