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_TOKEN_NOT_FOUND = 'REFRESH_TOKEN_NOT_FOUND',
|
||||||
REFRESH_ACCESS_TOKEN_FAILED = 'REFRESH_ACCESS_TOKEN_FAILED',
|
REFRESH_ACCESS_TOKEN_FAILED = 'REFRESH_ACCESS_TOKEN_FAILED',
|
||||||
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||||
|
TEMPORARY_NETWORK_ERROR = 'TEMPORARY_NETWORK_ERROR',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,9 +93,26 @@ export class ConnectedAccountRefreshTokensService {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error?.name === 'AggregateError') {
|
if (error?.name === 'AggregateError') {
|
||||||
this.logger.log(error.message);
|
const firstErrorCode = error?.errors?.[0]?.code;
|
||||||
this.logger.log(error.name);
|
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);
|
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 {
|
} else {
|
||||||
this.logger.log(error);
|
this.logger.log(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,4 +14,5 @@ export enum MessageImportDriverExceptionCode {
|
|||||||
UNKNOWN_NETWORK_ERROR = 'UNKNOWN_NETWORK_ERROR',
|
UNKNOWN_NETWORK_ERROR = 'UNKNOWN_NETWORK_ERROR',
|
||||||
NO_NEXT_SYNC_CURSOR = 'NO_NEXT_SYNC_CURSOR',
|
NO_NEXT_SYNC_CURSOR = 'NO_NEXT_SYNC_CURSOR',
|
||||||
SYNC_CURSOR_ERROR = 'SYNC_CURSOR_ERROR',
|
SYNC_CURSOR_ERROR = 'SYNC_CURSOR_ERROR',
|
||||||
|
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,10 @@ import {
|
|||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
MessageChannelWorkspaceEntity,
|
MessageChannelWorkspaceEntity,
|
||||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
} 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 {
|
||||||
import { MessageImportExceptionCode } from 'src/modules/messaging/message-import-manager/exceptions/message-import.exception';
|
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 { MessagingFullMessageListFetchService } from 'src/modules/messaging/message-import-manager/services/messaging-full-message-list-fetch.service';
|
||||||
import {
|
import {
|
||||||
MessageImportExceptionHandlerService,
|
MessageImportExceptionHandlerService,
|
||||||
@ -90,6 +92,11 @@ export class MessagingMessageListFetchJob {
|
|||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
switch (error.code) {
|
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_ACCESS_TOKEN_FAILED:
|
||||||
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_TOKEN_NOT_FOUND:
|
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_TOKEN_NOT_FOUND:
|
||||||
await this.messagingMonitoringService.track({
|
await this.messagingMonitoringService.track({
|
||||||
@ -99,15 +106,15 @@ export class MessagingMessageListFetchJob {
|
|||||||
messageChannelId: messageChannel.id,
|
messageChannelId: messageChannel.id,
|
||||||
message: `${error.code}: ${error.reason ?? ''}`,
|
message: `${error.code}: ${error.reason ?? ''}`,
|
||||||
});
|
});
|
||||||
throw {
|
throw new MessageImportDriverException(
|
||||||
code: MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
error.message,
|
||||||
message: error.message,
|
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||||
};
|
);
|
||||||
case ConnectedAccountRefreshAccessTokenExceptionCode.PROVIDER_NOT_SUPPORTED:
|
case ConnectedAccountRefreshAccessTokenExceptionCode.PROVIDER_NOT_SUPPORTED:
|
||||||
throw {
|
throw new MessageImportDriverException(
|
||||||
code: MessageImportExceptionCode.PROVIDER_NOT_SUPPORTED,
|
error.message,
|
||||||
message: error.message,
|
MessageImportDriverExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||||
};
|
);
|
||||||
default:
|
default:
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export class MessageImportExceptionHandlerService {
|
|||||||
>,
|
>,
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (exception instanceof MessageImportDriverException) {
|
if ('code' in exception) {
|
||||||
switch (exception.code) {
|
switch (exception.code) {
|
||||||
case MessageImportDriverExceptionCode.NOT_FOUND:
|
case MessageImportDriverExceptionCode.NOT_FOUND:
|
||||||
await this.handleNotFoundException(
|
await this.handleNotFoundException(
|
||||||
|
|||||||
@ -16,9 +16,11 @@ import {
|
|||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
MessageChannelWorkspaceEntity,
|
MessageChannelWorkspaceEntity,
|
||||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
} 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 { 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 { MessagingGetMessagesService } from 'src/modules/messaging/message-import-manager/services/messaging-get-messages.service';
|
||||||
import {
|
import {
|
||||||
MessageImportExceptionHandlerService,
|
MessageImportExceptionHandlerService,
|
||||||
@ -80,6 +82,11 @@ export class MessagingMessagesImportService {
|
|||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
switch (error.code) {
|
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_ACCESS_TOKEN_FAILED:
|
||||||
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_TOKEN_NOT_FOUND:
|
case ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_TOKEN_NOT_FOUND:
|
||||||
await this.messagingMonitoringService.track({
|
await this.messagingMonitoringService.track({
|
||||||
@ -89,15 +96,15 @@ export class MessagingMessagesImportService {
|
|||||||
messageChannelId: messageChannel.id,
|
messageChannelId: messageChannel.id,
|
||||||
message: `${error.code}: ${error.reason}`,
|
message: `${error.code}: ${error.reason}`,
|
||||||
});
|
});
|
||||||
throw {
|
throw new MessageImportDriverException(
|
||||||
code: MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
error.message,
|
||||||
message: error.message,
|
MessageImportDriverExceptionCode.INSUFFICIENT_PERMISSIONS,
|
||||||
};
|
);
|
||||||
case ConnectedAccountRefreshAccessTokenExceptionCode.PROVIDER_NOT_SUPPORTED:
|
case ConnectedAccountRefreshAccessTokenExceptionCode.PROVIDER_NOT_SUPPORTED:
|
||||||
throw {
|
throw new MessageImportDriverException(
|
||||||
code: MessageImportExceptionCode.PROVIDER_NOT_SUPPORTED,
|
error.message,
|
||||||
message: error.message,
|
MessageImportDriverExceptionCode.PROVIDER_NOT_SUPPORTED,
|
||||||
};
|
);
|
||||||
default:
|
default:
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Error (${error.code}) refreshing access token for account ${connectedAccount.id}`,
|
`Error (${error.code}) refreshing access token for account ${connectedAccount.id}`,
|
||||||
|
|||||||
Reference in New Issue
Block a user