in connected account, refresh-token can fail with network error (#12815)
This PR fixes this issue from the connected account refresh token service that is This PR fixes error handling in `handleDriverException` by ensuring that errors resembling `MessageImportDriverException` are correctly detected, even if they are plain objects and not true class instances. This prevents missed exception handling due to failed `instanceof` checks. Was introduced by [this PR](https://github.com/twentyhq/twenty/pull/12233) that did not know all provider cases that can occur. Fixes https://github.com/twentyhq/twenty/issues/12589
This commit is contained in:
@ -13,4 +13,5 @@ export enum ConnectedAccountRefreshAccessTokenExceptionCode {
|
||||
REFRESH_TOKEN_NOT_FOUND = 'REFRESH_TOKEN_NOT_FOUND',
|
||||
REFRESH_ACCESS_TOKEN_FAILED = 'REFRESH_ACCESS_TOKEN_FAILED',
|
||||
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||
TEMPORARY_NETWORK_ERROR = 'TEMPORARY_NETWORK_ERROR',
|
||||
}
|
||||
|
||||
@ -93,9 +93,26 @@ export class ConnectedAccountRefreshTokensService {
|
||||
}
|
||||
} catch (error) {
|
||||
if (error?.name === 'AggregateError') {
|
||||
this.logger.log(error.message);
|
||||
this.logger.log(error.name);
|
||||
const firstErrorCode = error?.errors?.[0]?.code;
|
||||
const networkErrorCodes = [
|
||||
'ENETUNREACH',
|
||||
'ETIMEDOUT',
|
||||
'ECONNABORTED',
|
||||
'ERR_NETWORK',
|
||||
];
|
||||
const isTemporaryNetworkError =
|
||||
networkErrorCodes.includes(firstErrorCode);
|
||||
|
||||
this.logger.log(error?.message);
|
||||
this.logger.log(firstErrorCode);
|
||||
this.logger.log(error?.errors);
|
||||
|
||||
if (isTemporaryNetworkError) {
|
||||
throw new ConnectedAccountRefreshAccessTokenException(
|
||||
`Error refreshing tokens for connected account ${connectedAccount.id.slice(0, 7)} in workspace ${workspaceId.slice(0, 7)}: ${firstErrorCode}`,
|
||||
ConnectedAccountRefreshAccessTokenExceptionCode.TEMPORARY_NETWORK_ERROR,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.logger.log(error);
|
||||
}
|
||||
|
||||
@ -14,4 +14,5 @@ export enum MessageImportDriverExceptionCode {
|
||||
UNKNOWN_NETWORK_ERROR = 'UNKNOWN_NETWORK_ERROR',
|
||||
NO_NEXT_SYNC_CURSOR = 'NO_NEXT_SYNC_CURSOR',
|
||||
SYNC_CURSOR_ERROR = 'SYNC_CURSOR_ERROR',
|
||||
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||
}
|
||||
|
||||
@ -11,8 +11,10 @@ import {
|
||||
MessageChannelSyncStage,
|
||||
MessageChannelWorkspaceEntity,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
import { MessageImportDriverExceptionCode } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { MessageImportExceptionCode } from 'src/modules/messaging/message-import-manager/exceptions/message-import.exception';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { MessagingFullMessageListFetchService } from 'src/modules/messaging/message-import-manager/services/messaging-full-message-list-fetch.service';
|
||||
import {
|
||||
MessageImportExceptionHandlerService,
|
||||
@ -90,6 +92,11 @@ export class MessagingMessageListFetchJob {
|
||||
);
|
||||
} catch (error) {
|
||||
switch (error.code) {
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.TEMPORARY_NETWORK_ERROR:
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
);
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_ACCESS_TOKEN_FAILED:
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_TOKEN_NOT_FOUND:
|
||||
await this.messagingMonitoringService.track({
|
||||
@ -99,15 +106,15 @@ export class MessagingMessageListFetchJob {
|
||||
messageChannelId: messageChannel.id,
|
||||
message: `${error.code}: ${error.reason ?? ''}`,
|
||||
});
|
||||
throw {
|
||||
code: MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
message: error.message,
|
||||
};
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
);
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.PROVIDER_NOT_SUPPORTED:
|
||||
throw {
|
||||
code: MessageImportExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
message: error.message,
|
||||
};
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
);
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ export class MessageImportExceptionHandlerService {
|
||||
>,
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
if (exception instanceof MessageImportDriverException) {
|
||||
if ('code' in exception) {
|
||||
switch (exception.code) {
|
||||
case MessageImportDriverExceptionCode.NOT_FOUND:
|
||||
await this.handleNotFoundException(
|
||||
|
||||
@ -16,9 +16,11 @@ import {
|
||||
MessageChannelSyncStage,
|
||||
MessageChannelWorkspaceEntity,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
import { MessageImportDriverExceptionCode } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import {
|
||||
MessageImportDriverException,
|
||||
MessageImportDriverExceptionCode,
|
||||
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
|
||||
import { MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant';
|
||||
import { MessageImportExceptionCode } from 'src/modules/messaging/message-import-manager/exceptions/message-import.exception';
|
||||
import { MessagingGetMessagesService } from 'src/modules/messaging/message-import-manager/services/messaging-get-messages.service';
|
||||
import {
|
||||
MessageImportExceptionHandlerService,
|
||||
@ -80,6 +82,11 @@ export class MessagingMessagesImportService {
|
||||
);
|
||||
} catch (error) {
|
||||
switch (error.code) {
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.TEMPORARY_NETWORK_ERROR:
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.TEMPORARY_ERROR,
|
||||
);
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_ACCESS_TOKEN_FAILED:
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_TOKEN_NOT_FOUND:
|
||||
await this.messagingMonitoringService.track({
|
||||
@ -89,15 +96,15 @@ export class MessagingMessagesImportService {
|
||||
messageChannelId: messageChannel.id,
|
||||
message: `${error.code}: ${error.reason}`,
|
||||
});
|
||||
throw {
|
||||
code: MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
message: error.message,
|
||||
};
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||
);
|
||||
case ConnectedAccountRefreshAccessTokenExceptionCode.PROVIDER_NOT_SUPPORTED:
|
||||
throw {
|
||||
code: MessageImportExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
message: error.message,
|
||||
};
|
||||
throw new MessageImportDriverException(
|
||||
error.message,
|
||||
MessageImportDriverExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||
);
|
||||
default:
|
||||
this.logger.error(
|
||||
`Error (${error.code}) refreshing access token for account ${connectedAccount.id}`,
|
||||
|
||||
Reference in New Issue
Block a user