refactor messaging error handling (#15416)
This commit is contained in:
+20
@@ -9,6 +9,7 @@ import { type ExceptionHandlerOptions } from 'src/engine/core-modules/exception-
|
||||
|
||||
import { PostgresException } from 'src/engine/api/graphql/workspace-query-runner/utils/postgres-exception';
|
||||
import { type ExceptionHandlerDriverInterface } from 'src/engine/core-modules/exception-handler/interfaces';
|
||||
import { MessageImportDriverException } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class ExceptionHandlerSentryDriver
|
||||
@@ -61,6 +62,20 @@ export class ExceptionHandlerSentryDriver
|
||||
});
|
||||
}
|
||||
|
||||
if ('context' in exception && exception.context) {
|
||||
Object.entries(exception.context).forEach(([key, value]) => {
|
||||
scope.setExtra(key, value);
|
||||
});
|
||||
}
|
||||
|
||||
if ('cause' in exception && exception.cause) {
|
||||
scope.setContext('cause', {
|
||||
name: exception.cause.name,
|
||||
message: exception.cause.message,
|
||||
stack: exception.cause.stack,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
exception instanceof CustomException &&
|
||||
exception.code !== 'UNKNOWN'
|
||||
@@ -84,6 +99,11 @@ export class ExceptionHandlerSentryDriver
|
||||
exception.name = exception.message;
|
||||
}
|
||||
|
||||
if (exception instanceof MessageImportDriverException) {
|
||||
scope.setTag('messageImportDriverCode', exception.code);
|
||||
scope.setFingerprint([exception.code]);
|
||||
}
|
||||
|
||||
const eventId = Sentry.captureException(exception, {
|
||||
contexts: {
|
||||
GraphQL: {
|
||||
|
||||
+3
-3
@@ -8,7 +8,7 @@ import {
|
||||
import { OAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/services/oauth2-client-manager.service';
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
import { MESSAGING_GMAIL_DEFAULT_NOT_SYNCED_LABELS } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-default-not-synced-labels';
|
||||
import { GmailHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-handle-error.service';
|
||||
import { GmailMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-message-list-fetch-error-handler.service';
|
||||
|
||||
@Injectable()
|
||||
export class GmailGetAllFoldersService implements MessageFolderDriver {
|
||||
@@ -16,7 +16,7 @@ export class GmailGetAllFoldersService implements MessageFolderDriver {
|
||||
|
||||
constructor(
|
||||
private readonly oAuth2ClientManagerService: OAuth2ClientManagerService,
|
||||
private readonly gmailHandleErrorService: GmailHandleErrorService,
|
||||
private readonly gmailMessageListFetchErrorHandler: GmailMessageListFetchErrorHandler,
|
||||
) {}
|
||||
|
||||
private isSyncedByDefault(labelId: string): boolean {
|
||||
@@ -44,7 +44,7 @@ export class GmailGetAllFoldersService implements MessageFolderDriver {
|
||||
`Connected account ${connectedAccount.id}: Error fetching labels: ${error.message}`,
|
||||
);
|
||||
|
||||
this.gmailHandleErrorService.handleGmailMessageListFetchError(error);
|
||||
this.gmailMessageListFetchErrorHandler.handleError(error);
|
||||
|
||||
return { data: { labels: [] } };
|
||||
});
|
||||
|
||||
+3
-6
@@ -7,7 +7,7 @@ import {
|
||||
|
||||
import { OAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/services/oauth2-client-manager.service';
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
import { MicrosoftHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service';
|
||||
import { MicrosoftMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-message-list-fetch-error-handler.service';
|
||||
import { StandardFolder } from 'src/modules/messaging/message-import-manager/drivers/types/standard-folder';
|
||||
import { getStandardFolderByRegex } from 'src/modules/messaging/message-import-manager/drivers/utils/get-standard-folder-by-regex';
|
||||
|
||||
@@ -26,8 +26,7 @@ export class MicrosoftGetAllFoldersService implements MessageFolderDriver {
|
||||
|
||||
constructor(
|
||||
private readonly oAuth2ClientManagerService: OAuth2ClientManagerService,
|
||||
|
||||
private readonly microsoftHandleErrorService: MicrosoftHandleErrorService,
|
||||
private readonly microsoftMessageListFetchErrorHandler: MicrosoftMessageListFetchErrorHandler,
|
||||
) {}
|
||||
|
||||
async getAllMessageFolders(
|
||||
@@ -51,9 +50,7 @@ export class MicrosoftGetAllFoldersService implements MessageFolderDriver {
|
||||
this.logger.error(
|
||||
`Connected account ${connectedAccount.id}: Error fetching folders: ${error.message}`,
|
||||
);
|
||||
this.microsoftHandleErrorService.handleMicrosoftGetMessageListError(
|
||||
error,
|
||||
);
|
||||
this.microsoftMessageListFetchErrorHandler.handleError(error);
|
||||
|
||||
return { value: [] };
|
||||
});
|
||||
|
||||
+32
-4
@@ -1,9 +1,37 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
import { type MessageNetworkExceptionCode } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-network.exception';
|
||||
|
||||
export class MessageImportDriverException extends CustomException<
|
||||
MessageImportDriverExceptionCode | MessageNetworkExceptionCode
|
||||
> {}
|
||||
export class MessageImportDriverException extends Error {
|
||||
code: MessageImportDriverExceptionCode | MessageNetworkExceptionCode;
|
||||
cause?: Error;
|
||||
context?: {
|
||||
messageChannelId?: string;
|
||||
workspaceId?: string;
|
||||
syncStep?: string;
|
||||
};
|
||||
|
||||
constructor(
|
||||
message: string,
|
||||
code: MessageImportDriverExceptionCode | MessageNetworkExceptionCode,
|
||||
options?: {
|
||||
cause?: Error;
|
||||
context?: {
|
||||
messageChannelId?: string;
|
||||
workspaceId?: string;
|
||||
syncStep?: string;
|
||||
};
|
||||
},
|
||||
) {
|
||||
super(message);
|
||||
this.name = 'MessageImportDriverException';
|
||||
this.code = code;
|
||||
this.cause = options?.cause;
|
||||
this.context = options?.context;
|
||||
|
||||
if (options?.cause?.stack) {
|
||||
this.stack = `${this.stack}\nCaused by: ${options.cause.stack}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export enum MessageImportDriverExceptionCode {
|
||||
NOT_FOUND = 'NOT_FOUND',
|
||||
|
||||
+9
-4
@@ -15,7 +15,9 @@ import { GmailFetchByBatchService } from 'src/modules/messaging/message-import-m
|
||||
import { GmailGetHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-history.service';
|
||||
import { GmailGetMessageListService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-message-list.service';
|
||||
import { GmailGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-messages.service';
|
||||
import { GmailHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-handle-error.service';
|
||||
import { GmailMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-message-list-fetch-error-handler.service';
|
||||
import { GmailMessagesImportErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-messages-import-error-handler.service';
|
||||
import { GmailNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-network-error-handler.service';
|
||||
import { MessageParticipantManagerModule } from 'src/modules/messaging/message-participant-manager/message-participant-manager.module';
|
||||
|
||||
@Module({
|
||||
@@ -38,13 +40,16 @@ import { MessageParticipantManagerModule } from 'src/modules/messaging/message-p
|
||||
GmailFetchByBatchService,
|
||||
GmailGetMessagesService,
|
||||
GmailGetMessageListService,
|
||||
GmailHandleErrorService,
|
||||
GmailNetworkErrorHandler,
|
||||
GmailMessageListFetchErrorHandler,
|
||||
GmailMessagesImportErrorHandler,
|
||||
],
|
||||
exports: [
|
||||
GmailGetMessagesService,
|
||||
GmailGetMessageListService,
|
||||
|
||||
GmailHandleErrorService,
|
||||
GmailNetworkErrorHandler,
|
||||
GmailMessageListFetchErrorHandler,
|
||||
GmailMessagesImportErrorHandler,
|
||||
],
|
||||
})
|
||||
export class MessagingGmailDriverModule {}
|
||||
|
||||
+3
-3
@@ -3,12 +3,12 @@ import { Injectable } from '@nestjs/common';
|
||||
import { type gmail_v1 } from 'googleapis';
|
||||
|
||||
import { MESSAGING_GMAIL_USERS_HISTORY_MAX_RESULT } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant';
|
||||
import { GmailHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-handle-error.service';
|
||||
import { GmailMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-message-list-fetch-error-handler.service';
|
||||
|
||||
@Injectable()
|
||||
export class GmailGetHistoryService {
|
||||
constructor(
|
||||
private readonly gmailHandleErrorService: GmailHandleErrorService,
|
||||
private readonly gmailMessageListFetchErrorHandler: GmailMessageListFetchErrorHandler,
|
||||
) {}
|
||||
|
||||
public async getHistory(
|
||||
@@ -36,7 +36,7 @@ export class GmailGetHistoryService {
|
||||
labelId,
|
||||
})
|
||||
.catch((error) => {
|
||||
this.gmailHandleErrorService.handleGmailMessageListFetchError(error);
|
||||
this.gmailMessageListFetchErrorHandler.handleError(error);
|
||||
|
||||
return {
|
||||
data: {
|
||||
|
||||
+3
-4
@@ -6,7 +6,7 @@ import { OAuth2ClientManagerService } from 'src/modules/connected-account/oauth2
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
import { GmailGetHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-history.service';
|
||||
import { GmailGetMessageListService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-message-list.service';
|
||||
import { GmailHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-handle-error.service';
|
||||
import { GmailMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-message-list-fetch-error-handler.service';
|
||||
|
||||
describe('GmailGetMessageListService', () => {
|
||||
let service: GmailGetMessageListService;
|
||||
@@ -47,10 +47,9 @@ describe('GmailGetMessageListService', () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: GmailHandleErrorService,
|
||||
provide: GmailMessageListFetchErrorHandler,
|
||||
useValue: {
|
||||
handleGmailMessageListFetchError: jest.fn(),
|
||||
handleGmailMessagesImportError: jest.fn(),
|
||||
handleError: jest.fn(),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
+4
-8
@@ -13,7 +13,7 @@ import {
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { MESSAGING_GMAIL_USERS_MESSAGES_LIST_MAX_RESULT } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant';
|
||||
import { GmailGetHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-history.service';
|
||||
import { GmailHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-handle-error.service';
|
||||
import { GmailMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-message-list-fetch-error-handler.service';
|
||||
import { computeGmailExcludeSearchFilter } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-exclude-search-filter.util';
|
||||
import { type GetMessageListsArgs } from 'src/modules/messaging/message-import-manager/types/get-message-lists-args.type';
|
||||
import { type GetMessageListsResponse } from 'src/modules/messaging/message-import-manager/types/get-message-lists-response.type';
|
||||
@@ -25,8 +25,7 @@ export class GmailGetMessageListService {
|
||||
constructor(
|
||||
private readonly gmailGetHistoryService: GmailGetHistoryService,
|
||||
private readonly oAuth2ClientManagerService: OAuth2ClientManagerService,
|
||||
|
||||
private readonly gmailHandleErrorService: GmailHandleErrorService,
|
||||
private readonly gmailMessageListFetchErrorHandler: GmailMessageListFetchErrorHandler,
|
||||
) {}
|
||||
|
||||
private async getMessageListWithoutCursor(
|
||||
@@ -69,7 +68,7 @@ export class GmailGetMessageListService {
|
||||
`Connected account ${connectedAccount.id}: Error fetching message list: ${JSON.stringify(error)}`,
|
||||
);
|
||||
|
||||
this.gmailHandleErrorService.handleGmailMessageListFetchError(error);
|
||||
this.gmailMessageListFetchErrorHandler.handleError(error);
|
||||
|
||||
return {
|
||||
data: {
|
||||
@@ -112,10 +111,7 @@ export class GmailGetMessageListService {
|
||||
id: firstMessageExternalId,
|
||||
})
|
||||
.catch((error) => {
|
||||
this.gmailHandleErrorService.handleGmailMessagesImportError(
|
||||
error,
|
||||
firstMessageExternalId as string,
|
||||
);
|
||||
this.gmailMessageListFetchErrorHandler.handleError(error);
|
||||
});
|
||||
|
||||
const nextSyncCursor = firstMessageContent?.data?.historyId;
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
import { GmailFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-fetch-by-batch.service';
|
||||
import { GmailHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-handle-error.service';
|
||||
import { GmailMessagesImportErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-messages-import-error-handler.service';
|
||||
import { parseAndFormatGmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-and-format-gmail-message.util';
|
||||
import { type MessageWithParticipants } from 'src/modules/messaging/message-import-manager/types/message';
|
||||
|
||||
@@ -14,7 +14,7 @@ import { type MessageWithParticipants } from 'src/modules/messaging/message-impo
|
||||
export class GmailGetMessagesService {
|
||||
constructor(
|
||||
private readonly fetchByBatchesService: GmailFetchByBatchService,
|
||||
private readonly gmailHandleErrorService: GmailHandleErrorService,
|
||||
private readonly gmailMessagesImportErrorHandler: GmailMessagesImportErrorHandler,
|
||||
) {}
|
||||
|
||||
async getMessages(
|
||||
@@ -57,7 +57,7 @@ export class GmailGetMessagesService {
|
||||
|
||||
const messages = parsedResponses.map((response, index) => {
|
||||
if ('error' in response) {
|
||||
this.gmailHandleErrorService.handleGmailMessagesImportError(
|
||||
this.gmailMessagesImportErrorHandler.handleError(
|
||||
response.error,
|
||||
messageIds[index],
|
||||
);
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { isAxiosTemporaryError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-axios-gaxios-error.util';
|
||||
import { parseGmailMessageListFetchError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-message-list-fetch-error.util';
|
||||
import { parseGmailMessagesImportError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-messages-import-error.util';
|
||||
|
||||
@Injectable()
|
||||
export class GmailHandleErrorService {
|
||||
constructor() {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public handleGmailMessageListFetchError(error: any): void {
|
||||
if (isAxiosTemporaryError(error)) {
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
throw parseGmailMessageListFetchError(error);
|
||||
}
|
||||
|
||||
public handleGmailMessagesImportError(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: any,
|
||||
messageExternalId: string,
|
||||
): void {
|
||||
if (isAxiosTemporaryError(error)) {
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
const gmailError = parseGmailMessagesImportError(error, messageExternalId);
|
||||
|
||||
if (gmailError) {
|
||||
throw gmailError;
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { GmailNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-network-error-handler.service';
|
||||
import { parseGmailMessageListFetchError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-message-list-fetch-error.util';
|
||||
|
||||
@Injectable()
|
||||
export class GmailMessageListFetchErrorHandler {
|
||||
private readonly logger = new Logger(GmailMessageListFetchErrorHandler.name);
|
||||
|
||||
constructor(
|
||||
private readonly gmailNetworkErrorHandler: GmailNetworkErrorHandler,
|
||||
) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public handleError(error: any): void {
|
||||
this.logger.log(`Error fetching message list`, error);
|
||||
|
||||
const networkError = this.gmailNetworkErrorHandler.handleError(error);
|
||||
|
||||
if (networkError) {
|
||||
throw networkError;
|
||||
}
|
||||
|
||||
throw parseGmailMessageListFetchError(error, { cause: error });
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { GmailNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-network-error-handler.service';
|
||||
import { parseGmailMessagesImportError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/parse-gmail-messages-import-error.util';
|
||||
|
||||
@Injectable()
|
||||
export class GmailMessagesImportErrorHandler {
|
||||
private readonly logger = new Logger(GmailMessagesImportErrorHandler.name);
|
||||
|
||||
constructor(
|
||||
private readonly gmailNetworkErrorHandler: GmailNetworkErrorHandler,
|
||||
) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public handleError(error: any, messageExternalId: string): void {
|
||||
this.logger.log(`Error fetching messages`, error);
|
||||
|
||||
const networkError = this.gmailNetworkErrorHandler.handleError(error);
|
||||
|
||||
if (networkError) {
|
||||
throw networkError;
|
||||
}
|
||||
|
||||
const gmailError = parseGmailMessagesImportError(error, messageExternalId, {
|
||||
cause: error,
|
||||
});
|
||||
|
||||
if (gmailError) {
|
||||
throw gmailError;
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { isAxiosTemporaryError } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-axios-gaxios-error.util';
|
||||
|
||||
@Injectable()
|
||||
export class GmailNetworkErrorHandler {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public handleError(error: any): MessageImportDriverException | null {
|
||||
if (isAxiosTemporaryError(error)) {
|
||||
return new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: error },
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+23
-7
@@ -3,13 +3,16 @@ import {
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
|
||||
export const parseGmailMessageListFetchError = (error: {
|
||||
code?: number;
|
||||
errors: {
|
||||
reason: string;
|
||||
message: string;
|
||||
}[];
|
||||
}): MessageImportDriverException => {
|
||||
export const parseGmailMessageListFetchError = (
|
||||
error: {
|
||||
code?: number;
|
||||
errors: {
|
||||
reason: string;
|
||||
message: string;
|
||||
}[];
|
||||
},
|
||||
options?: { cause?: Error },
|
||||
): MessageImportDriverException => {
|
||||
const { code, errors } = error;
|
||||
|
||||
const reason = errors?.[0]?.reason;
|
||||
@@ -21,6 +24,7 @@ export const parseGmailMessageListFetchError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
if (reason === 'failedPrecondition') {
|
||||
@@ -28,30 +32,35 @@ export const parseGmailMessageListFetchError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 404:
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.NOT_FOUND,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 429:
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 403:
|
||||
@@ -63,12 +72,14 @@ export const parseGmailMessageListFetchError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
if (reason === 'domainPolicy') {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -78,12 +89,14 @@ export const parseGmailMessageListFetchError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 503:
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 500:
|
||||
@@ -93,6 +106,7 @@ export const parseGmailMessageListFetchError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,6 +114,7 @@ export const parseGmailMessageListFetchError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
`${code} - ${reason} - ${message}`,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -111,5 +126,6 @@ export const parseGmailMessageListFetchError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
};
|
||||
|
||||
+13
@@ -12,6 +12,7 @@ export const parseGmailMessagesImportError = (
|
||||
}[];
|
||||
},
|
||||
messageExternalId: string,
|
||||
options?: { cause?: Error },
|
||||
): MessageImportDriverException | undefined => {
|
||||
const { code, errors } = error;
|
||||
|
||||
@@ -25,6 +26,7 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
if (reason === 'failedPrecondition') {
|
||||
@@ -32,18 +34,21 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 404:
|
||||
@@ -54,6 +59,7 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 403:
|
||||
@@ -65,12 +71,14 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
if (reason === 'domainPolicy') {
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -80,12 +88,14 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 503:
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
|
||||
case 500:
|
||||
@@ -95,6 +105,7 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -102,6 +113,7 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
`${code} - ${reason} - ${message}`,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -113,5 +125,6 @@ export const parseGmailMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
message,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
};
|
||||
|
||||
+6
-2
@@ -14,11 +14,13 @@ import { ImapFetchByBatchService } from 'src/modules/messaging/message-import-ma
|
||||
import { ImapFindSentFolderService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-find-sent-folder.service';
|
||||
import { ImapGetMessageListService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-get-message-list.service';
|
||||
import { ImapGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-get-messages.service';
|
||||
import { ImapHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-handle-error.service';
|
||||
import { ImapIncrementalSyncService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-incremental-sync.service';
|
||||
import { ImapMessageFetcherService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-message-fetcher.service';
|
||||
import { ImapMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-message-list-fetch-error-handler.service';
|
||||
import { ImapMessageProcessorService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-message-processor.service';
|
||||
import { ImapMessagesImportErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-messages-import-error-handler.service';
|
||||
import { ImapMessageTextExtractorService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-message-text-extractor.service';
|
||||
import { ImapNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-network-error-handler.service';
|
||||
import { MessageParticipantManagerModule } from 'src/modules/messaging/message-participant-manager/message-participant-manager.module';
|
||||
|
||||
@Module({
|
||||
@@ -37,7 +39,9 @@ import { MessageParticipantManagerModule } from 'src/modules/messaging/message-p
|
||||
ImapFetchByBatchService,
|
||||
ImapGetMessagesService,
|
||||
ImapGetMessageListService,
|
||||
ImapHandleErrorService,
|
||||
ImapNetworkErrorHandler,
|
||||
ImapMessageListFetchErrorHandler,
|
||||
ImapMessagesImportErrorHandler,
|
||||
ImapIncrementalSyncService,
|
||||
ImapMessageFetcherService,
|
||||
ImapMessageProcessorService,
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ import { type ImapFlow } from 'imapflow';
|
||||
|
||||
import { type MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity';
|
||||
import { ImapClientProvider } from 'src/modules/messaging/message-import-manager/drivers/imap/providers/imap-client.provider';
|
||||
import { ImapHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-handle-error.service';
|
||||
import { ImapMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-message-list-fetch-error-handler.service';
|
||||
import { ImapIncrementalSyncService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-incremental-sync.service';
|
||||
import { createSyncCursor } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/create-sync-cursor.util';
|
||||
import { extractMailboxState } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/extract-mailbox-state.util';
|
||||
@@ -25,7 +25,7 @@ export class ImapGetMessageListService {
|
||||
constructor(
|
||||
private readonly imapClientProvider: ImapClientProvider,
|
||||
private readonly imapIncrementalSyncService: ImapIncrementalSyncService,
|
||||
private readonly imapHandleErrorService: ImapHandleErrorService,
|
||||
private readonly imapMessageListFetchErrorHandler: ImapMessageListFetchErrorHandler,
|
||||
) {}
|
||||
|
||||
public async getMessageLists({
|
||||
@@ -74,7 +74,7 @@ export class ImapGetMessageListService {
|
||||
error.stack,
|
||||
);
|
||||
|
||||
this.imapHandleErrorService.handleImapMessageListFetchError(error);
|
||||
this.imapMessageListFetchErrorHandler.handleError(error);
|
||||
|
||||
return messageFolders.map((folder) => ({
|
||||
messageExternalIds: [],
|
||||
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import {
|
||||
MessageChannelSyncStatus,
|
||||
type MessageChannelWorkspaceEntity,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
import { parseImapError } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-imap-error.util';
|
||||
import { parseImapMessageListFetchError } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-imap-message-list-fetch-error.util';
|
||||
import { parseImapMessagesImportError } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-imap-messages-import-error.util';
|
||||
|
||||
@Injectable()
|
||||
export class ImapHandleErrorService {
|
||||
private readonly logger = new Logger(ImapHandleErrorService.name);
|
||||
|
||||
constructor(
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
) {}
|
||||
|
||||
async handleError(
|
||||
error: Error,
|
||||
workspaceId: string,
|
||||
messageChannelId: string,
|
||||
): Promise<void> {
|
||||
this.logger.error(
|
||||
`IMAP error for message channel ${messageChannelId}: ${error.message}`,
|
||||
error.stack,
|
||||
);
|
||||
|
||||
try {
|
||||
const messageChannelRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageChannel',
|
||||
);
|
||||
|
||||
await messageChannelRepository.update(
|
||||
{ id: messageChannelId },
|
||||
{
|
||||
syncStatus: MessageChannelSyncStatus.FAILED_UNKNOWN,
|
||||
},
|
||||
);
|
||||
} catch (handleErrorError) {
|
||||
this.logger.error(
|
||||
`Error handling IMAP error: ${handleErrorError.message}`,
|
||||
handleErrorError.stack,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public handleImapMessageListFetchError(error: Error): void {
|
||||
const imapError = parseImapError(error);
|
||||
|
||||
if (imapError) {
|
||||
throw imapError;
|
||||
}
|
||||
|
||||
throw parseImapMessageListFetchError(error);
|
||||
}
|
||||
|
||||
public handleImapMessagesImportError(
|
||||
error: Error,
|
||||
messageExternalId: string,
|
||||
): void {
|
||||
const imapError = parseImapError(error);
|
||||
|
||||
if (imapError) {
|
||||
throw imapError;
|
||||
}
|
||||
|
||||
throw parseImapMessagesImportError(error, messageExternalId);
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { parseImapMessageListFetchError } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-imap-message-list-fetch-error.util';
|
||||
import { ImapNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-network-error-handler.service';
|
||||
|
||||
@Injectable()
|
||||
export class ImapMessageListFetchErrorHandler {
|
||||
constructor(
|
||||
private readonly imapNetworkErrorHandler: ImapNetworkErrorHandler,
|
||||
) {}
|
||||
|
||||
public handleError(error: Error): void {
|
||||
const networkError = this.imapNetworkErrorHandler.handleError(error);
|
||||
|
||||
if (networkError) {
|
||||
throw networkError;
|
||||
}
|
||||
|
||||
throw parseImapMessageListFetchError(error, { cause: error });
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -3,7 +3,7 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
import { type FetchMessageObject, type ImapFlow } from 'imapflow';
|
||||
import { type ParsedMail, simpleParser } from 'mailparser';
|
||||
|
||||
import { ImapHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-handle-error.service';
|
||||
import { ImapMessagesImportErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-messages-import-error-handler.service';
|
||||
|
||||
export type MessageFetchResult = {
|
||||
uid: number;
|
||||
@@ -16,7 +16,7 @@ export class ImapMessageProcessorService {
|
||||
private readonly logger = new Logger(ImapMessageProcessorService.name);
|
||||
|
||||
constructor(
|
||||
private readonly imapHandleErrorService: ImapHandleErrorService,
|
||||
private readonly imapMessagesImportErrorHandler: ImapMessagesImportErrorHandler,
|
||||
) {}
|
||||
|
||||
async processMessagesByUidsInFolder(
|
||||
@@ -174,7 +174,7 @@ export class ImapMessageProcessorService {
|
||||
return uids.map((uid) => {
|
||||
this.logger.error(`Failed to fetch message UID ${uid}: ${error.message}`);
|
||||
|
||||
this.imapHandleErrorService.handleImapMessagesImportError(
|
||||
this.imapMessagesImportErrorHandler.handleError(
|
||||
error,
|
||||
`${folder}:${uid}`,
|
||||
);
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { parseImapMessagesImportError } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-imap-messages-import-error.util';
|
||||
import { ImapNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-network-error-handler.service';
|
||||
|
||||
@Injectable()
|
||||
export class ImapMessagesImportErrorHandler {
|
||||
constructor(
|
||||
private readonly imapNetworkErrorHandler: ImapNetworkErrorHandler,
|
||||
) {}
|
||||
|
||||
public handleError(error: Error, messageExternalId: string): void {
|
||||
const networkError = this.imapNetworkErrorHandler.handleError(error);
|
||||
|
||||
if (networkError) {
|
||||
throw networkError;
|
||||
}
|
||||
|
||||
throw parseImapMessagesImportError(error, messageExternalId, {
|
||||
cause: error,
|
||||
});
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { type MessageImportDriverException } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { parseImapError } from 'src/modules/messaging/message-import-manager/drivers/imap/utils/parse-imap-error.util';
|
||||
|
||||
@Injectable()
|
||||
export class ImapNetworkErrorHandler {
|
||||
public handleError(error: Error): MessageImportDriverException | null {
|
||||
return parseImapError(error, { cause: error });
|
||||
}
|
||||
}
|
||||
+9
@@ -7,6 +7,7 @@ import { isImapFlowError } from 'src/modules/messaging/message-import-manager/dr
|
||||
|
||||
export const parseImapError = (
|
||||
error: Error,
|
||||
options?: { cause?: Error },
|
||||
): MessageImportDriverException | null => {
|
||||
if (!error) {
|
||||
return null;
|
||||
@@ -20,6 +21,7 @@ export const parseImapError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP client not available: ${error.message}`,
|
||||
MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,6 +29,7 @@ export const parseImapError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP connection timeout: ${error.message}`,
|
||||
MessageNetworkExceptionCode.ETIMEDOUT,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -34,6 +37,7 @@ export const parseImapError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP connection error: ${error.message}`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN_NETWORK_ERROR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,6 +46,7 @@ export const parseImapError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP authentication error: ${error.responseText || error.message}`,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,6 +54,7 @@ export const parseImapError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP mailbox not found: ${error.responseText || error.message}`,
|
||||
MessageImportDriverExceptionCode.NOT_FOUND,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -57,6 +63,7 @@ export const parseImapError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP authentication error: ${error.responseText || error.message}`,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,12 +72,14 @@ export const parseImapError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP temporary error: ${error.responseText}`,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
`IMAP command failed: ${error.responseText}`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -6,11 +6,13 @@ import { isImapFlowError } from 'src/modules/messaging/message-import-manager/dr
|
||||
|
||||
export const parseImapMessageListFetchError = (
|
||||
error: Error,
|
||||
options?: { cause?: Error },
|
||||
): MessageImportDriverException => {
|
||||
if (!error) {
|
||||
return new MessageImportDriverException(
|
||||
'Unknown IMAP message list fetch error: No error provided',
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +22,7 @@ export const parseImapMessageListFetchError = (
|
||||
return new MessageImportDriverException(
|
||||
`Unknown IMAP message list fetch error: ${errorMessage}`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,6 +34,7 @@ export const parseImapMessageListFetchError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP sync cursor error: ${error.responseText}`,
|
||||
MessageImportDriverExceptionCode.SYNC_CURSOR_ERROR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,6 +42,7 @@ export const parseImapMessageListFetchError = (
|
||||
return new MessageImportDriverException(
|
||||
'No messages found for next sync cursor',
|
||||
MessageImportDriverExceptionCode.NO_NEXT_SYNC_CURSOR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -46,6 +51,7 @@ export const parseImapMessageListFetchError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP sync cursor error: ${errorMessage}`,
|
||||
MessageImportDriverExceptionCode.SYNC_CURSOR_ERROR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -53,11 +59,13 @@ export const parseImapMessageListFetchError = (
|
||||
return new MessageImportDriverException(
|
||||
'No messages found for next sync cursor',
|
||||
MessageImportDriverExceptionCode.NO_NEXT_SYNC_CURSOR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
`Unknown IMAP message list fetch error: code: ${error.code} | responseText: ${error.responseText} | executedCommand: ${error.executedCommand}`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
};
|
||||
|
||||
+9
@@ -7,11 +7,13 @@ import { isImapFlowError } from 'src/modules/messaging/message-import-manager/dr
|
||||
export const parseImapMessagesImportError = (
|
||||
error: Error,
|
||||
messageExternalId: string,
|
||||
options?: { cause?: Error },
|
||||
): MessageImportDriverException => {
|
||||
if (!error) {
|
||||
return new MessageImportDriverException(
|
||||
`Unknown IMAP message import error for message ${messageExternalId}: No error provided`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -21,6 +23,7 @@ export const parseImapMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
`Unknown IMAP message import error for message ${messageExternalId}: ${errorMessage}`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,6 +32,7 @@ export const parseImapMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP message not found: ${messageExternalId}`,
|
||||
MessageImportDriverExceptionCode.NOT_FOUND,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,6 +40,7 @@ export const parseImapMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP message no longer exists (expunged): ${messageExternalId}`,
|
||||
MessageImportDriverExceptionCode.NOT_FOUND,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,6 +48,7 @@ export const parseImapMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP message fetch error for message ${messageExternalId}: ${error.responseText}`,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -54,6 +60,7 @@ export const parseImapMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP message not found: ${messageExternalId}`,
|
||||
MessageImportDriverExceptionCode.NOT_FOUND,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,11 +68,13 @@ export const parseImapMessagesImportError = (
|
||||
return new MessageImportDriverException(
|
||||
`IMAP message fetch error for message ${messageExternalId}: ${errorMessage}`,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
`Unknown IMAP message import error for message ${messageExternalId}: ${errorMessage}`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause || error },
|
||||
);
|
||||
};
|
||||
|
||||
+8
-3
@@ -8,7 +8,9 @@ import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-
|
||||
import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module';
|
||||
import { MicrosoftFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service';
|
||||
import { MicrosoftGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service';
|
||||
import { MicrosoftHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service';
|
||||
import { MicrosoftMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-message-list-fetch-error-handler.service';
|
||||
import { MicrosoftMessagesImportErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-messages-import-error-handler.service';
|
||||
import { MicrosoftNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-network-error-handler.service';
|
||||
|
||||
import { MicrosoftGetMessageListService } from './services/microsoft-get-message-list.service';
|
||||
|
||||
@@ -25,12 +27,15 @@ import { MicrosoftGetMessageListService } from './services/microsoft-get-message
|
||||
MicrosoftGetMessageListService,
|
||||
MicrosoftGetMessagesService,
|
||||
MicrosoftFetchByBatchService,
|
||||
MicrosoftHandleErrorService,
|
||||
MicrosoftNetworkErrorHandler,
|
||||
MicrosoftMessageListFetchErrorHandler,
|
||||
MicrosoftMessagesImportErrorHandler,
|
||||
],
|
||||
exports: [
|
||||
MicrosoftGetMessageListService,
|
||||
MicrosoftGetMessagesService,
|
||||
MicrosoftHandleErrorService,
|
||||
MicrosoftMessageListFetchErrorHandler,
|
||||
MicrosoftMessagesImportErrorHandler,
|
||||
],
|
||||
})
|
||||
export class MessagingMicrosoftDriverModule {}
|
||||
|
||||
+9
-3
@@ -13,7 +13,7 @@ import { microsoftGraphWithMessagesDeltaLink } from 'src/modules/messaging/messa
|
||||
import { MessageFolderName } from 'src/modules/messaging/message-import-manager/drivers/microsoft/types/folders';
|
||||
|
||||
import { MicrosoftGetMessageListService } from './microsoft-get-message-list.service';
|
||||
import { MicrosoftHandleErrorService } from './microsoft-handle-error.service';
|
||||
import { MicrosoftMessageListFetchErrorHandler } from './microsoft-message-list-fetch-error-handler.service';
|
||||
|
||||
// in case you have "Please provide a valid token" it may be because you need to pass the env varible to the .env.test file
|
||||
const accessToken = 'replace-with-your-access-token';
|
||||
@@ -53,7 +53,10 @@ xdescribe('Microsoft dev tests : get message list service', () => {
|
||||
providers: [
|
||||
MicrosoftGetMessageListService,
|
||||
OAuth2ClientManagerService,
|
||||
MicrosoftHandleErrorService,
|
||||
{
|
||||
provide: MicrosoftMessageListFetchErrorHandler,
|
||||
useValue: { handleError: jest.fn() },
|
||||
},
|
||||
MicrosoftOAuth2ClientManagerService,
|
||||
ConfigService,
|
||||
],
|
||||
@@ -204,7 +207,10 @@ xdescribe('Microsoft dev tests : get message list service for folders', () => {
|
||||
providers: [
|
||||
MicrosoftGetMessageListService,
|
||||
OAuth2ClientManagerService,
|
||||
MicrosoftHandleErrorService,
|
||||
{
|
||||
provide: MicrosoftMessageListFetchErrorHandler,
|
||||
useValue: { handleError: jest.fn() },
|
||||
},
|
||||
MicrosoftOAuth2ClientManagerService,
|
||||
ConfigService,
|
||||
],
|
||||
|
||||
+4
-8
@@ -14,7 +14,7 @@ import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { MicrosoftHandleErrorService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-handle-error.service';
|
||||
import { MicrosoftMessageListFetchErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-message-list-fetch-error-handler.service';
|
||||
import { isAccessTokenRefreshingError } from 'src/modules/messaging/message-import-manager/drivers/microsoft/utils/is-access-token-refreshing-error.utils';
|
||||
import { type GetMessageListsArgs } from 'src/modules/messaging/message-import-manager/types/get-message-lists-args.type';
|
||||
import {
|
||||
@@ -30,7 +30,7 @@ export class MicrosoftGetMessageListService {
|
||||
private readonly logger = new Logger(MicrosoftGetMessageListService.name);
|
||||
constructor(
|
||||
private readonly oAuth2ClientManagerService: OAuth2ClientManagerService,
|
||||
private readonly microsoftHandleErrorService: MicrosoftHandleErrorService,
|
||||
private readonly microsoftMessageListFetchErrorHandler: MicrosoftMessageListFetchErrorHandler,
|
||||
) {}
|
||||
|
||||
public async getMessageLists({
|
||||
@@ -99,9 +99,7 @@ export class MicrosoftGetMessageListService {
|
||||
MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE,
|
||||
);
|
||||
}
|
||||
this.microsoftHandleErrorService.handleMicrosoftGetMessageListError(
|
||||
error,
|
||||
);
|
||||
this.microsoftMessageListFetchErrorHandler.handleError(error);
|
||||
});
|
||||
|
||||
const callback: PageIteratorCallback = (data) => {
|
||||
@@ -127,9 +125,7 @@ export class MicrosoftGetMessageListService {
|
||||
MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE,
|
||||
);
|
||||
}
|
||||
this.microsoftHandleErrorService.handleMicrosoftGetMessageListError(
|
||||
error,
|
||||
);
|
||||
this.microsoftMessageListFetchErrorHandler.handleError(error);
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+5
-2
@@ -9,7 +9,7 @@ import { OAuth2ClientManagerService } from 'src/modules/connected-account/oauth2
|
||||
import { MicrosoftFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service';
|
||||
import { MicrosoftGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service';
|
||||
|
||||
import { MicrosoftHandleErrorService } from './microsoft-handle-error.service';
|
||||
import { MicrosoftMessagesImportErrorHandler } from './microsoft-messages-import-error-handler.service';
|
||||
|
||||
const mockMessageIds = [
|
||||
'AAkALgAAAAAAHYQDEapmEc2byACqAC-EWg0AGnUPtcQC-Eiwmc39SmMpPgAAA8ZAfgAA',
|
||||
@@ -27,7 +27,10 @@ xdescribe('Microsoft dev tests : get messages service', () => {
|
||||
imports: [TwentyConfigModule.forRoot()],
|
||||
providers: [
|
||||
MicrosoftGetMessagesService,
|
||||
MicrosoftHandleErrorService,
|
||||
{
|
||||
provide: MicrosoftMessagesImportErrorHandler,
|
||||
useValue: { handleError: jest.fn() },
|
||||
},
|
||||
OAuth2ClientManagerService,
|
||||
MicrosoftOAuth2ClientManagerService,
|
||||
MicrosoftFetchByBatchService,
|
||||
|
||||
+6
-4
@@ -1,5 +1,5 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { ConnectedAccountProvider } from 'twenty-shared/types';
|
||||
@@ -15,8 +15,7 @@ import {
|
||||
import { MicrosoftFetchByBatchService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-fetch-by-batch.service';
|
||||
import { type MicrosoftGraphBatchResponse } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.interface';
|
||||
import { MicrosoftGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service';
|
||||
|
||||
import { MicrosoftHandleErrorService } from './microsoft-handle-error.service';
|
||||
import { MicrosoftMessagesImportErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-messages-import-error-handler.service';
|
||||
|
||||
describe('Microsoft get messages service', () => {
|
||||
let service: MicrosoftGetMessagesService;
|
||||
@@ -25,7 +24,10 @@ describe('Microsoft get messages service', () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
MicrosoftGetMessagesService,
|
||||
MicrosoftHandleErrorService,
|
||||
{
|
||||
provide: MicrosoftMessagesImportErrorHandler,
|
||||
useValue: { handleError: jest.fn() },
|
||||
},
|
||||
OAuth2ClientManagerService,
|
||||
GoogleOAuth2ClientManagerService,
|
||||
MicrosoftOAuth2ClientManagerService,
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@ import { formatAddressObjectAsParticipants } from 'src/modules/messaging/message
|
||||
import { safeParseEmailAddress } from 'src/modules/messaging/message-import-manager/utils/safe-parse.util';
|
||||
|
||||
import { MicrosoftFetchByBatchService } from './microsoft-fetch-by-batch.service';
|
||||
import { MicrosoftHandleErrorService } from './microsoft-handle-error.service';
|
||||
import { MicrosoftMessagesImportErrorHandler } from './microsoft-messages-import-error-handler.service';
|
||||
|
||||
type ConnectedAccountType = Pick<
|
||||
ConnectedAccountWorkspaceEntity,
|
||||
@@ -31,7 +31,7 @@ export class MicrosoftGetMessagesService {
|
||||
|
||||
constructor(
|
||||
private readonly microsoftFetchByBatchService: MicrosoftFetchByBatchService,
|
||||
private readonly microsoftHandleErrorService: MicrosoftHandleErrorService,
|
||||
private readonly microsoftMessagesImportErrorHandler: MicrosoftMessagesImportErrorHandler,
|
||||
) {}
|
||||
|
||||
async getMessages(
|
||||
@@ -52,7 +52,7 @@ export class MicrosoftGetMessagesService {
|
||||
|
||||
return messages;
|
||||
} catch (error) {
|
||||
this.microsoftHandleErrorService.handleMicrosoftGetMessagesError(error);
|
||||
this.microsoftMessagesImportErrorHandler.handleError(error);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { MicrosoftNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-network-error-handler.service';
|
||||
import { parseMicrosoftMessagesImportError } from 'src/modules/messaging/message-import-manager/drivers/microsoft/utils/parse-microsoft-messages-import.util';
|
||||
|
||||
@Injectable()
|
||||
export class MicrosoftMessageListFetchErrorHandler {
|
||||
private readonly logger = new Logger(
|
||||
MicrosoftMessageListFetchErrorHandler.name,
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly microsoftNetworkErrorHandler: MicrosoftNetworkErrorHandler,
|
||||
) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public handleError(error: any): void {
|
||||
this.logger.log(`Error fetching message list`, error);
|
||||
|
||||
const networkError = this.microsoftNetworkErrorHandler.handleError(error);
|
||||
|
||||
if (networkError) {
|
||||
throw networkError;
|
||||
}
|
||||
|
||||
throw parseMicrosoftMessagesImportError(error, { cause: error });
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { MicrosoftNetworkErrorHandler } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-network-error-handler.service';
|
||||
import { parseMicrosoftMessagesImportError } from 'src/modules/messaging/message-import-manager/drivers/microsoft/utils/parse-microsoft-messages-import.util';
|
||||
|
||||
@Injectable()
|
||||
export class MicrosoftMessagesImportErrorHandler {
|
||||
private readonly logger = new Logger(
|
||||
MicrosoftMessagesImportErrorHandler.name,
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly microsoftNetworkErrorHandler: MicrosoftNetworkErrorHandler,
|
||||
) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public handleError(error: any): void {
|
||||
this.logger.log(`Error fetching messages`, error);
|
||||
|
||||
const networkError = this.microsoftNetworkErrorHandler.handleError(error);
|
||||
|
||||
if (networkError) {
|
||||
throw networkError;
|
||||
}
|
||||
|
||||
throw parseMicrosoftMessagesImportError(error, { cause: error });
|
||||
}
|
||||
}
|
||||
+8
-14
@@ -6,25 +6,18 @@ import {
|
||||
} 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';
|
||||
|
||||
@Injectable()
|
||||
export class MicrosoftHandleErrorService {
|
||||
private readonly logger = new Logger(MicrosoftHandleErrorService.name);
|
||||
export class MicrosoftNetworkErrorHandler {
|
||||
private readonly logger = new Logger(MicrosoftNetworkErrorHandler.name);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
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);
|
||||
public handleError(error: any): MessageImportDriverException | null {
|
||||
if (isAccessTokenRefreshingError(error?.body)) {
|
||||
throw new MessageImportDriverException(
|
||||
return new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.CLIENT_NOT_AVAILABLE,
|
||||
{ cause: error },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,12 +26,13 @@ export class MicrosoftHandleErrorService {
|
||||
isBodyString && isMicrosoftClientTemporaryError(error.body);
|
||||
|
||||
if (isTemporaryError) {
|
||||
throw new MessageImportDriverException(
|
||||
return new MessageImportDriverException(
|
||||
`code: ${error.code} - body: ${error.body}`,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: error },
|
||||
);
|
||||
}
|
||||
|
||||
throw parseMicrosoftMessagesImportError(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+14
-5
@@ -3,15 +3,19 @@ import {
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
|
||||
export const parseMicrosoftMessagesImportError = (error: {
|
||||
statusCode: number;
|
||||
message?: string;
|
||||
code?: string;
|
||||
}): MessageImportDriverException => {
|
||||
export const parseMicrosoftMessagesImportError = (
|
||||
error: {
|
||||
statusCode: number;
|
||||
message?: string;
|
||||
code?: string;
|
||||
},
|
||||
options?: { cause?: Error },
|
||||
): MessageImportDriverException => {
|
||||
if (error.statusCode === 401) {
|
||||
return new MessageImportDriverException(
|
||||
'Unauthorized access to Microsoft Graph API',
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,6 +23,7 @@ export const parseMicrosoftMessagesImportError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
'Forbidden access to Microsoft Graph API',
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,11 +36,13 @@ export const parseMicrosoftMessagesImportError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
`Disabled, deleted, inactive or no licence Microsoft account - code:${error.code}`,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
} else {
|
||||
return new MessageImportDriverException(
|
||||
`Not found - code:${error.code}`,
|
||||
MessageImportDriverExceptionCode.NOT_FOUND,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -48,11 +55,13 @@ export const parseMicrosoftMessagesImportError = (error: {
|
||||
return new MessageImportDriverException(
|
||||
`Microsoft Graph API ${error.code} ${error.statusCode} error: ${error.message}`,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
}
|
||||
|
||||
return new MessageImportDriverException(
|
||||
`Microsoft Graph API unknown error: ${error} with status code ${error.statusCode}`,
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
{ cause: options?.cause },
|
||||
);
|
||||
};
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
import { CustomException } from 'src/utils/custom-exception';
|
||||
|
||||
export class MessageImportException extends CustomException<MessageImportExceptionCode> {}
|
||||
|
||||
export enum MessageImportExceptionCode {
|
||||
UNKNOWN = 'UNKNOWN',
|
||||
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||
}
|
||||
+6
-6
@@ -7,13 +7,13 @@ import {
|
||||
type MessageChannelWorkspaceEntity,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
import { MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { GmailGetMessageListService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-message-list.service';
|
||||
import { ImapGetMessageListService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-get-message-list.service';
|
||||
import { MicrosoftGetMessageListService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-message-list.service';
|
||||
import {
|
||||
MessageImportException,
|
||||
MessageImportExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/exceptions/message-import.exception';
|
||||
import { type GetMessageListsResponse } from 'src/modules/messaging/message-import-manager/types/get-message-lists-response.type';
|
||||
|
||||
type MessageFolder = Pick<
|
||||
@@ -60,9 +60,9 @@ export class MessagingGetMessageListService {
|
||||
});
|
||||
}
|
||||
default:
|
||||
throw new MessageImportException(
|
||||
throw new MessageImportDriverException(
|
||||
`Provider ${messageChannel.connectedAccount.provider} is not supported`,
|
||||
MessageImportExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
MessageImportDriverExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -3,13 +3,13 @@ import { Injectable } from '@nestjs/common';
|
||||
import { ConnectedAccountProvider } from 'twenty-shared/types';
|
||||
|
||||
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 { GmailGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-messages.service';
|
||||
import { ImapGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/imap/services/imap-get-messages.service';
|
||||
import { MicrosoftGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service';
|
||||
import {
|
||||
MessageImportException,
|
||||
MessageImportExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/exceptions/message-import.exception';
|
||||
import { type MessageWithParticipants } from 'src/modules/messaging/message-import-manager/types/message';
|
||||
|
||||
export type GetMessagesResponse = MessageWithParticipants[];
|
||||
@@ -53,9 +53,9 @@ export class MessagingGetMessagesService {
|
||||
connectedAccount,
|
||||
);
|
||||
default:
|
||||
throw new MessageImportException(
|
||||
throw new MessageImportDriverException(
|
||||
`Provider ${connectedAccount.provider} is not supported`,
|
||||
MessageImportExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
MessageImportDriverExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-52
@@ -1,7 +1,5 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'class-validator';
|
||||
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import {
|
||||
type TwentyORMException,
|
||||
@@ -19,10 +17,6 @@ import {
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { MessageNetworkExceptionCode } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-network.exception';
|
||||
import {
|
||||
MessageImportException,
|
||||
MessageImportExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/exceptions/message-import.exception';
|
||||
|
||||
export enum MessageImportSyncStep {
|
||||
MESSAGE_LIST_FETCH = 'MESSAGE_LIST_FETCH',
|
||||
@@ -47,6 +41,19 @@ export class MessageImportExceptionHandlerService {
|
||||
>,
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
if (exception instanceof MessageImportDriverException) {
|
||||
exception.context = {
|
||||
...exception.context,
|
||||
messageChannelId: messageChannel.id,
|
||||
workspaceId,
|
||||
syncStep,
|
||||
};
|
||||
}
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([exception], {
|
||||
workspace: { id: workspaceId },
|
||||
});
|
||||
|
||||
if ('code' in exception) {
|
||||
switch (exception.code) {
|
||||
case MessageImportDriverExceptionCode.NOT_FOUND:
|
||||
@@ -78,24 +85,16 @@ export class MessageImportExceptionHandlerService {
|
||||
);
|
||||
break;
|
||||
case MessageImportDriverExceptionCode.SYNC_CURSOR_ERROR:
|
||||
await this.handlePermanentException(
|
||||
exception,
|
||||
messageChannel,
|
||||
workspaceId,
|
||||
);
|
||||
await this.handlePermanentException(messageChannel, workspaceId);
|
||||
break;
|
||||
case MessageImportDriverExceptionCode.UNKNOWN:
|
||||
case MessageImportDriverExceptionCode.UNKNOWN_NETWORK_ERROR:
|
||||
default:
|
||||
await this.handleUnknownException(
|
||||
exception,
|
||||
messageChannel,
|
||||
workspaceId,
|
||||
);
|
||||
await this.handleUnknownException(messageChannel, workspaceId);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
await this.handleUnknownException(exception, messageChannel, workspaceId);
|
||||
await this.handleUnknownException(messageChannel, workspaceId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +118,9 @@ export class MessageImportExceptionHandlerService {
|
||||
|
||||
this.exceptionHandlerService.captureExceptions(
|
||||
[
|
||||
`Temporary error occurred ${MESSAGING_THROTTLE_MAX_ATTEMPTS} times while importing messages for message channel ${messageChannel.id.slice(0, 5)}... in workspace ${workspaceId}: ${exception?.message}`,
|
||||
new Error(
|
||||
`Temporary error occurred ${MESSAGING_THROTTLE_MAX_ATTEMPTS} times while importing messages for message channel ${messageChannel.id.slice(0, 5)}... in workspace ${workspaceId}: ${exception?.message}`,
|
||||
),
|
||||
],
|
||||
{
|
||||
additionalData: {
|
||||
@@ -129,10 +130,7 @@ export class MessageImportExceptionHandlerService {
|
||||
},
|
||||
);
|
||||
|
||||
throw new MessageImportException(
|
||||
`Temporary error occurred multiple times while importing messages for message channel ${messageChannel.id} in workspace ${workspaceId}: ${exception?.message}`,
|
||||
MessageImportExceptionCode.UNKNOWN,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const messageChannelRepository =
|
||||
@@ -179,7 +177,6 @@ export class MessageImportExceptionHandlerService {
|
||||
}
|
||||
|
||||
private async handleUnknownException(
|
||||
exception: MessageImportDriverException | Error,
|
||||
messageChannel: Pick<MessageChannelWorkspaceEntity, 'id'>,
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
@@ -188,27 +185,9 @@ export class MessageImportExceptionHandlerService {
|
||||
workspaceId,
|
||||
MessageChannelSyncStatus.FAILED_UNKNOWN,
|
||||
);
|
||||
|
||||
const messageImportException = new MessageImportException(
|
||||
isDefined(exception.name)
|
||||
? `${exception.name}: ${exception.message}`
|
||||
: exception.message,
|
||||
MessageImportExceptionCode.UNKNOWN,
|
||||
);
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([messageImportException], {
|
||||
additionalData: {
|
||||
exception,
|
||||
messageChannelId: messageChannel.id,
|
||||
},
|
||||
workspace: { id: workspaceId },
|
||||
});
|
||||
|
||||
throw messageImportException;
|
||||
}
|
||||
|
||||
private async handlePermanentException(
|
||||
exception: MessageImportDriverException,
|
||||
messageChannel: Pick<MessageChannelWorkspaceEntity, 'id'>,
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
@@ -217,11 +196,6 @@ export class MessageImportExceptionHandlerService {
|
||||
workspaceId,
|
||||
MessageChannelSyncStatus.FAILED_UNKNOWN,
|
||||
);
|
||||
|
||||
throw new MessageImportException(
|
||||
`Permanent error occurred while importing messages for message channel ${messageChannel.id} in workspace ${workspaceId}: ${exception.message}`,
|
||||
MessageImportExceptionCode.UNKNOWN,
|
||||
);
|
||||
}
|
||||
|
||||
private async handleNotFoundException(
|
||||
@@ -230,14 +204,27 @@ export class MessageImportExceptionHandlerService {
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
if (syncStep === MessageImportSyncStep.MESSAGE_LIST_FETCH) {
|
||||
await this.handleUnknownException(
|
||||
new MessageImportDriverException(
|
||||
'Not Found exception occurred while fetching message list, which should never happen',
|
||||
MessageImportDriverExceptionCode.UNKNOWN,
|
||||
),
|
||||
messageChannel,
|
||||
await this.messageChannelSyncStatusService.markAsFailed(
|
||||
[messageChannel.id],
|
||||
workspaceId,
|
||||
MessageChannelSyncStatus.FAILED_UNKNOWN,
|
||||
);
|
||||
|
||||
this.exceptionHandlerService.captureExceptions(
|
||||
[
|
||||
new Error(
|
||||
'Not Found exception occurred while fetching message list, which should never happen',
|
||||
),
|
||||
],
|
||||
{
|
||||
additionalData: {
|
||||
messageChannelId: messageChannel.id,
|
||||
},
|
||||
workspace: { id: workspaceId },
|
||||
},
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await this.messageChannelSyncStatusService.resetAndScheduleMessageListFetch(
|
||||
|
||||
Reference in New Issue
Block a user