From 349b15e81f3e1cf464127c322d45fc206c7e625b Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Fri, 19 Sep 2025 12:31:19 +0200 Subject: [PATCH] Add scripts to relaunch message and calendar channels (#14579) ## Context 1. We are debugging the experience on messaging and calendar sync. I'm adding two scripts to relaunch messaging and calendar channels 2. We are seeing errors in Sentry regarding microsoft drivers errors. I was about to fix them but I'm refactoring / simplifying a bit the logic first. It will be a betters starting point --- .../workspace-event-emitter.ts | 2 +- .../calendar-event-import-manager.module.ts | 2 + ...launch-failed-calendar-channels.command.ts | 85 ++++++++++++++++++ .../calendar-event-list-fetch.cron.job.ts | 2 +- ...elaunch-failed-message-channels.command.ts | 84 ++++++++++++++++++ .../messaging-message-list-fetch.cron.job.ts | 2 +- .../microsoft-fetch-by-batch.service.ts | 45 +--------- .../microsoft-handle-error.service.ts | 86 ++++--------------- .../parse-microsoft-messages-import.util.ts | 7 +- .../messaging-import-manager.module.ts | 6 +- 10 files changed, 204 insertions(+), 117 deletions(-) create mode 100644 packages/twenty-server/src/modules/calendar/calendar-event-import-manager/commands/calendar-relaunch-failed-calendar-channels.command.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-relaunch-failed-message-channels.command.ts diff --git a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.ts b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.ts index a50b90edb4b..1178248be0d 100644 --- a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.ts +++ b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.ts @@ -15,8 +15,8 @@ import { ObjectRecordUpdateEvent } from 'src/engine/core-modules/event-emitter/t import { objectRecordChangedValues } from 'src/engine/core-modules/event-emitter/utils/object-record-changed-values'; import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps'; import { type CustomEventName } from 'src/engine/workspace-event-emitter/types/custom-event-name.type'; -import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { computeEventName } from 'src/engine/workspace-event-emitter/utils/compute-event-name'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; type ActionEventMap = { [DatabaseEventAction.CREATED]: ObjectRecordCreateEvent; diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts index 254f187e450..bac02ae2015 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module.ts @@ -10,6 +10,7 @@ import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repos import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { CalendarEventCleanerModule } from 'src/modules/calendar/calendar-event-cleaner/calendar-event-cleaner.module'; +import { CalendarRelaunchFailedCalendarChannelsCommand } from 'src/modules/calendar/calendar-event-import-manager/commands/calendar-relaunch-failed-calendar-channels.command'; import { CalendarEventListFetchCronCommand } from 'src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-event-list-fetch.cron.command'; import { CalendarEventsImportCronCommand } from 'src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-import.cron.command'; import { CalendarOngoingStaleCronCommand } from 'src/modules/calendar/calendar-event-import-manager/crons/commands/calendar-ongoing-stale.cron.command'; @@ -64,6 +65,7 @@ import { RefreshTokensManagerModule } from 'src/modules/connected-account/refres CalendarEventsImportJob, CalendarOngoingStaleCronJob, CalendarOngoingStaleCronCommand, + CalendarRelaunchFailedCalendarChannelsCommand, CalendarOngoingStaleJob, ], exports: [ diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/commands/calendar-relaunch-failed-calendar-channels.command.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/commands/calendar-relaunch-failed-calendar-channels.command.ts new file mode 100644 index 00000000000..93957e12dd8 --- /dev/null +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/commands/calendar-relaunch-failed-calendar-channels.command.ts @@ -0,0 +1,85 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { Repository } from 'typeorm'; + +import { + ActiveOrSuspendedWorkspacesMigrationCommandRunner, + type RunOnWorkspaceArgs, +} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { + CalendarChannelSyncStage, + CalendarChannelSyncStatus, + CalendarChannelWorkspaceEntity, +} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; +import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service'; + +@Command({ + name: 'calendar:relaunch-failed-calendar-channels', + description: 'Relaunch failed message channels', +}) +export class CalendarRelaunchFailedCalendarChannelsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner { + constructor( + @InjectRepository(Workspace) + protected readonly workspaceRepository: Repository, + protected readonly twentyORMGlobalManager: TwentyORMGlobalManager, + protected readonly accountsToReconnectService: AccountsToReconnectService, + ) { + super(workspaceRepository, twentyORMGlobalManager); + } + + override async runOnWorkspace({ + workspaceId, + options, + }: RunOnWorkspaceArgs): Promise { + try { + const calendarChannelRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'calendarChannel', + { shouldBypassPermissionChecks: true }, + ); + + const failedCalendarChannels = await calendarChannelRepository.find({ + where: { + syncStage: CalendarChannelSyncStage.FAILED, + }, + relations: { + connectedAccount: { + accountOwner: true, + }, + }, + }); + + if (!options.dryRun && failedCalendarChannels.length > 0) { + await calendarChannelRepository.update( + failedCalendarChannels.map(({ id }) => id), + { + syncStage: + CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_PENDING, + syncStatus: CalendarChannelSyncStatus.ACTIVE, + }, + ); + + for (const failedCalendarChannel of failedCalendarChannels) { + await this.accountsToReconnectService.removeAccountToReconnect( + failedCalendarChannel.connectedAccount.accountOwner.userId, + failedCalendarChannel.connectedAccountId, + workspaceId, + ); + } + } + + this.logger.log( + `${options.dryRun ? ' (DRY RUN): ' : ''}Relaunched ${failedCalendarChannels.length} failed calendar channels`, + ); + } catch (error) { + this.logger.error( + 'Error while relaunching failed message channels', + error, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts index a9e8f2e8855..83af998a12e 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/crons/jobs/calendar-event-list-fetch.cron.job.ts @@ -51,7 +51,7 @@ export class CalendarEventListFetchCronJob { const schemaName = getWorkspaceSchemaName(activeWorkspace.id); const calendarChannels = await this.coreDataSource.query( - `SELECT * FROM ${schemaName}."calendarChannel" WHERE "isSyncEnabled" = true AND "syncStage" IN ('${CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING}', '${CalendarChannelSyncStage.PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING}')`, + `SELECT * FROM ${schemaName}."calendarChannel" WHERE "isSyncEnabled" = true AND "syncStage" IN ('${CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING}', '${CalendarChannelSyncStage.PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING}', '${CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_PENDING}')`, ); for (const calendarChannel of calendarChannels) { diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-relaunch-failed-message-channels.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-relaunch-failed-message-channels.command.ts new file mode 100644 index 00000000000..630e71bfc5d --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/commands/messaging-relaunch-failed-message-channels.command.ts @@ -0,0 +1,84 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { Repository } from 'typeorm'; + +import { + ActiveOrSuspendedWorkspacesMigrationCommandRunner, + type RunOnWorkspaceArgs, +} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service'; +import { + MessageChannelSyncStage, + MessageChannelSyncStatus, + MessageChannelWorkspaceEntity, +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; + +@Command({ + name: 'messaging:relaunch-failed-message-channels', + description: 'Relaunch failed message channels', +}) +export class MessagingRelaunchFailedMessageChannelsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner { + constructor( + @InjectRepository(Workspace) + protected readonly workspaceRepository: Repository, + protected readonly twentyORMGlobalManager: TwentyORMGlobalManager, + protected readonly accountsToReconnectService: AccountsToReconnectService, + ) { + super(workspaceRepository, twentyORMGlobalManager); + } + + override async runOnWorkspace({ + workspaceId, + options, + }: RunOnWorkspaceArgs): Promise { + try { + const messageChannelRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'messageChannel', + { shouldBypassPermissionChecks: true }, + ); + + const failedMessageChannels = await messageChannelRepository.find({ + where: { + syncStage: MessageChannelSyncStage.FAILED, + }, + relations: { + connectedAccount: { + accountOwner: true, + }, + }, + }); + + if (!options.dryRun && failedMessageChannels.length > 0) { + await messageChannelRepository.update( + failedMessageChannels.map(({ id }) => id), + { + syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_PENDING, + syncStatus: MessageChannelSyncStatus.ACTIVE, + }, + ); + + for (const failedMessageChannel of failedMessageChannels) { + await this.accountsToReconnectService.removeAccountToReconnect( + failedMessageChannel.connectedAccount.accountOwner.userId, + failedMessageChannel.connectedAccountId, + workspaceId, + ); + } + } + + this.logger.log( + `${options.dryRun ? ' (DRY RUN): ' : ''}Relaunched ${failedMessageChannels.length} failed message channels`, + ); + } catch (error) { + this.logger.error( + 'Error while relaunching failed message channels', + error, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts index b3301d79e91..823c9d7d3db 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts @@ -50,7 +50,7 @@ export class MessagingMessageListFetchCronJob { // TODO: deprecate looking for FULL_MESSAGE_LIST_FETCH_PENDING as we introduce MESSAGE_LIST_FETCH_PENDING const messageChannels = await this.coreDataSource.query( - `SELECT * FROM ${schemaName}."messageChannel" WHERE "isSyncEnabled" = true AND "syncStage" IN ('${MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING}', '${MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING}')`, + `SELECT * FROM ${schemaName}."messageChannel" WHERE "isSyncEnabled" = true AND "syncStage" IN ('${MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING}', '${MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING}', '${MessageChannelSyncStage.MESSAGE_LIST_FETCH_PENDING}')`, ); for (const messageChannel of messageChannels) { diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service.ts index 63842833dec..41082a279a9 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service.ts @@ -1,20 +1,13 @@ import { Injectable } from '@nestjs/common'; import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { - MessageImportDriverException, - MessageImportDriverExceptionCode, -} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception'; import { MicrosoftClientProvider } from 'src/modules/messaging/message-import-manager/drivers/microsoft/providers/microsoft-client.provider'; import { type MicrosoftGraphBatchResponse } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.interface'; -import { MicrosoftHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service'; -import { isAccessTokenRefreshingError } from 'src/modules/messaging/message-import-manager/drivers/microsoft/utils/is-access-token-refreshing-error.utils'; @Injectable() export class MicrosoftFetchByBatchService { constructor( private readonly microsoftClientProvider: MicrosoftClientProvider, - private readonly microsoftHandleErrorService: MicrosoftHandleErrorService, ) {} async fetchAllByBatches( @@ -49,23 +42,11 @@ export class MicrosoftFetchByBatchService { }, })); - try { - const batchResponse = await client - .api('/$batch') - .post({ requests: batchRequests }); + const batchResponse = await client + .api('/$batch') + .post({ requests: batchRequests }); - batchResponses.push(batchResponse); - } catch (error) { - if (isAccessTokenRefreshingError(error?.body)) { - throw new MessageImportDriverException( - error.message, - MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE, - ); - } - this.microsoftHandleErrorService.handleMicrosoftMessageFetchByBatchError( - error, - ); - } + batchResponses.push(batchResponse); } return { @@ -73,22 +54,4 @@ export class MicrosoftFetchByBatchService { batchResponses, }; } - - /** - * Microsoft client.api.post sometimes throws (hard to catch) temporary errors like this one: - * - * { - * statusCode: 200, - * code: "SyntaxError", - * requestId: null, - * date: "2025-05-14T11:43:02.024Z", - * body: "SyntaxError: Unexpected token < in JSON at position 19341", - * headers: { - * }, - * } - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private _isTemporaryError(error: any): boolean { - return error?.body?.includes('Unexpected token < in JSON at position'); - } } diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service.ts index f45eb50cc48..68bbf813ed6 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service.ts @@ -4,6 +4,7 @@ import { MessageImportDriverException, MessageImportDriverExceptionCode, } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception'; +import { isAccessTokenRefreshingError } from 'src/modules/messaging/message-import-manager/drivers/microsoft/utils/is-access-token-refreshing-error.utils'; import { isMicrosoftClientTemporaryError } from 'src/modules/messaging/message-import-manager/drivers/microsoft/utils/is-temporary-error.utils'; import { parseMicrosoftMessagesImportError } from 'src/modules/messaging/message-import-manager/drivers/microsoft/utils/parse-microsoft-messages-import.util'; @@ -12,10 +13,20 @@ export class MicrosoftHandleErrorService { private readonly logger = new Logger(MicrosoftHandleErrorService.name); // eslint-disable-next-line @typescript-eslint/no-explicit-any - public handleMicrosoftMessageFetchByBatchError(error: any): void { - // TODO: remove this log once we catch better the error codes - this.logger.error(`Error temporary (${error.code}) fetching messages`); - this.logger.log(error); + public handleMicrosoftGetMessageListError(error: any): void { + this.logger.log(`Error fetching message list`, error); + throw parseMicrosoftMessagesImportError(error); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public handleMicrosoftGetMessagesError(error: any): void { + this.logger.log(`Error fetching messages`, error); + if (isAccessTokenRefreshingError(error?.body)) { + throw new MessageImportDriverException( + error.message, + MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE, + ); + } const isBodyString = error.body && typeof error.body === 'string'; const isTemporaryError = @@ -28,71 +39,6 @@ export class MicrosoftHandleErrorService { ); } - if (!error.statusCode) { - throw new MessageImportDriverException( - `Microsoft Graph API unknown error: ${error}`, - MessageImportDriverExceptionCode.UNKNOWN, - ); - } - - const exception = parseMicrosoftMessagesImportError(error); - - if (exception) { - throw exception; - } - - throw new MessageImportDriverException( - `Microsoft driver error: ${error.message}`, - MessageImportDriverExceptionCode.UNKNOWN, - ); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public handleMicrosoftGetMessageListError(error: any): void { - if (!error.statusCode) { - throw new MessageImportDriverException( - `Microsoft Graph API unknown error: ${error}`, - MessageImportDriverExceptionCode.UNKNOWN, - ); - } - - const exception = parseMicrosoftMessagesImportError(error); - - if (exception) { - throw exception; - } - - throw new MessageImportDriverException( - `Microsoft driver error: ${error.message}`, - MessageImportDriverExceptionCode.UNKNOWN, - ); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - public handleMicrosoftGetMessagesError(error: any): void { - if ( - error instanceof MessageImportDriverException && - error.code === MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE - ) { - throw error; - } - - if (!error.statusCode) { - throw new MessageImportDriverException( - `Microsoft Graph API unknown error: ${error}`, - MessageImportDriverExceptionCode.UNKNOWN, - ); - } - - const exception = parseMicrosoftMessagesImportError(error); - - if (exception) { - throw exception; - } - - throw new MessageImportDriverException( - `Microsoft driver error: ${error.message}`, - MessageImportDriverExceptionCode.UNKNOWN, - ); + throw parseMicrosoftMessagesImportError(error); } } diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/utils/parse-microsoft-messages-import.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/utils/parse-microsoft-messages-import.util.ts index 2a3bbd07207..a27b377be56 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/utils/parse-microsoft-messages-import.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/microsoft/utils/parse-microsoft-messages-import.util.ts @@ -7,7 +7,7 @@ export const parseMicrosoftMessagesImportError = (error: { statusCode: number; message?: string; code?: string; -}): MessageImportDriverException | undefined => { +}): MessageImportDriverException => { if (error.statusCode === 401) { return new MessageImportDriverException( 'Unauthorized access to Microsoft Graph API', @@ -51,5 +51,8 @@ export const parseMicrosoftMessagesImportError = (error: { ); } - return undefined; + return new MessageImportDriverException( + `Microsoft Graph API unknown error: ${error} with status code ${error.statusCode}`, + MessageImportDriverExceptionCode.UNKNOWN, + ); }; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts index b216a1e1b6d..3f1b0a83149 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts @@ -7,10 +7,13 @@ import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-s import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { WorkspaceEventEmitterModule } from 'src/engine/workspace-event-emitter/workspace-event-emitter.module'; +import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module'; import { EmailAliasManagerModule } from 'src/modules/connected-account/email-alias-manager/email-alias-manager.module'; import { RefreshTokensManagerModule } from 'src/modules/connected-account/refresh-tokens-manager/connected-account-refresh-tokens-manager.module'; import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; import { MessagingMessageCleanerModule } from 'src/modules/messaging/message-cleaner/messaging-message-cleaner.module'; +import { MessagingFolderSyncManagerModule } from 'src/modules/messaging/message-folder-manager/messaging-folder-sync-manager.module'; +import { MessagingRelaunchFailedMessageChannelsCommand } from 'src/modules/messaging/message-import-manager/commands/messaging-relaunch-failed-message-channels.command'; import { MessagingSingleMessageImportCommand } from 'src/modules/messaging/message-import-manager/commands/messaging-single-message-import.command'; import { MessagingMessageListFetchCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command'; import { MessagingMessagesImportCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command'; @@ -39,7 +42,6 @@ import { MessagingMessagesImportService } from 'src/modules/messaging/message-im import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/message-import-manager/services/messaging-save-messages-and-enqueue-contact-creation.service'; import { MessagingSendMessageService } from 'src/modules/messaging/message-import-manager/services/messaging-send-message.service'; import { MessageParticipantManagerModule } from 'src/modules/messaging/message-participant-manager/message-participant-manager.module'; -import { MessagingFolderSyncManagerModule } from 'src/modules/messaging/message-folder-manager/messaging-folder-sync-manager.module'; import { MessagingMonitoringModule } from 'src/modules/messaging/monitoring/messaging-monitoring.module'; @Module({ imports: [ @@ -62,12 +64,14 @@ import { MessagingMonitoringModule } from 'src/modules/messaging/monitoring/mess MessagingMonitoringModule, MessagingMessageCleanerModule, WorkspaceEventEmitterModule, + ConnectedAccountModule, ], providers: [ MessagingMessageListFetchCronCommand, MessagingMessagesImportCronCommand, MessagingOngoingStaleCronCommand, MessagingSingleMessageImportCommand, + MessagingRelaunchFailedMessageChannelsCommand, MessagingMessageListFetchJob, MessagingMessagesImportJob, MessagingOngoingStaleJob,