6430 Part 1: remove all raw queries from the messaging and calendar modules (#6572)
Part 1 of #6430 - Remove all repositories which contained raw queries in `messaging` module - Replace them using `twentyORMManager`
This commit is contained in:
@ -30,7 +30,6 @@ import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-m
|
|||||||
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
|
||||||
|
|
||||||
import { AuthResolver } from './auth.resolver';
|
import { AuthResolver } from './auth.resolver';
|
||||||
|
|
||||||
@ -51,7 +50,6 @@ import { JwtAuthStrategy } from './strategies/jwt.auth.strategy';
|
|||||||
),
|
),
|
||||||
ObjectMetadataRepositoryModule.forFeature([
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
ConnectedAccountWorkspaceEntity,
|
ConnectedAccountWorkspaceEntity,
|
||||||
MessageChannelWorkspaceEntity,
|
|
||||||
]),
|
]),
|
||||||
HttpModule,
|
HttpModule,
|
||||||
UserWorkspaceModule,
|
UserWorkspaceModule,
|
||||||
|
|||||||
@ -23,8 +23,8 @@ import {
|
|||||||
ConnectedAccountProvider,
|
ConnectedAccountProvider,
|
||||||
ConnectedAccountWorkspaceEntity,
|
ConnectedAccountWorkspaceEntity,
|
||||||
} from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
} from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import {
|
import {
|
||||||
|
MessageChannelSyncStage,
|
||||||
MessageChannelSyncStatus,
|
MessageChannelSyncStatus,
|
||||||
MessageChannelType,
|
MessageChannelType,
|
||||||
MessageChannelVisibility,
|
MessageChannelVisibility,
|
||||||
@ -47,8 +47,6 @@ export class GoogleAPIsService {
|
|||||||
private readonly environmentService: EnvironmentService,
|
private readonly environmentService: EnvironmentService,
|
||||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
private readonly accountsToReconnectService: AccountsToReconnectService,
|
private readonly accountsToReconnectService: AccountsToReconnectService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -88,6 +86,11 @@ export class GoogleAPIsService {
|
|||||||
'calendarChannel',
|
'calendarChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageChannelRepository =
|
||||||
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
|
'messageChannel',
|
||||||
|
);
|
||||||
|
|
||||||
const workspaceDataSource = await this.twentyORMManager.getDatasource();
|
const workspaceDataSource = await this.twentyORMManager.getDatasource();
|
||||||
|
|
||||||
await workspaceDataSource.transaction(async (manager: EntityManager) => {
|
await workspaceDataSource.transaction(async (manager: EntityManager) => {
|
||||||
@ -105,7 +108,7 @@ export class GoogleAPIsService {
|
|||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.create(
|
await messageChannelRepository.save(
|
||||||
{
|
{
|
||||||
id: v4(),
|
id: v4(),
|
||||||
connectedAccountId: newOrExistingConnectedAccountId,
|
connectedAccountId: newOrExistingConnectedAccountId,
|
||||||
@ -115,7 +118,7 @@ export class GoogleAPIsService {
|
|||||||
messageVisibility || MessageChannelVisibility.SHARE_EVERYTHING,
|
messageVisibility || MessageChannelVisibility.SHARE_EVERYTHING,
|
||||||
syncStatus: MessageChannelSyncStatus.ONGOING,
|
syncStatus: MessageChannelSyncStatus.ONGOING,
|
||||||
},
|
},
|
||||||
workspaceId,
|
{},
|
||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -159,20 +162,27 @@ export class GoogleAPIsService {
|
|||||||
newOrExistingConnectedAccountId,
|
newOrExistingConnectedAccountId,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.resetSync(
|
await messageChannelRepository.update(
|
||||||
newOrExistingConnectedAccountId,
|
{
|
||||||
workspaceId,
|
connectedAccountId: newOrExistingConnectedAccountId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||||
|
syncStatus: null,
|
||||||
|
syncCursor: '',
|
||||||
|
syncStageStartedAt: null,
|
||||||
|
},
|
||||||
manager,
|
manager,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) {
|
if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) {
|
||||||
const messageChannels =
|
const messageChannels = await messageChannelRepository.find({
|
||||||
await this.messageChannelRepository.getByConnectedAccountId(
|
where: {
|
||||||
newOrExistingConnectedAccountId,
|
connectedAccountId: newOrExistingConnectedAccountId,
|
||||||
workspaceId,
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
for (const messageChannel of messageChannels) {
|
for (const messageChannel of messageChannels) {
|
||||||
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
|
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository';
|
import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository';
|
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository';
|
|
||||||
import { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository';
|
|
||||||
import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository';
|
|
||||||
import { AuditLogRepository } from 'src/modules/timeline/repositiories/audit-log.repository';
|
import { AuditLogRepository } from 'src/modules/timeline/repositiories/audit-log.repository';
|
||||||
import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository';
|
import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository';
|
||||||
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
||||||
@ -13,12 +8,6 @@ export const metadataToRepositoryMapping = {
|
|||||||
AuditLogWorkspaceEntity: AuditLogRepository,
|
AuditLogWorkspaceEntity: AuditLogRepository,
|
||||||
BlocklistWorkspaceEntity: BlocklistRepository,
|
BlocklistWorkspaceEntity: BlocklistRepository,
|
||||||
ConnectedAccountWorkspaceEntity: ConnectedAccountRepository,
|
ConnectedAccountWorkspaceEntity: ConnectedAccountRepository,
|
||||||
MessageChannelMessageAssociationWorkspaceEntity:
|
|
||||||
MessageChannelMessageAssociationRepository,
|
|
||||||
MessageChannelWorkspaceEntity: MessageChannelRepository,
|
|
||||||
MessageWorkspaceEntity: MessageRepository,
|
|
||||||
MessageParticipantWorkspaceEntity: MessageParticipantRepository,
|
|
||||||
MessageThreadWorkspaceEntity: MessageThreadRepository,
|
|
||||||
TimelineActivityWorkspaceEntity: TimelineActivityRepository,
|
TimelineActivityWorkspaceEntity: TimelineActivityRepository,
|
||||||
WorkspaceMemberWorkspaceEntity: WorkspaceMemberRepository,
|
WorkspaceMemberWorkspaceEntity: WorkspaceMemberRepository,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -157,7 +157,7 @@ export class CreateCompanyService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createCompanyMap(companies: CompanyWorkspaceEntity[]) {
|
private createCompanyMap(companies: CompanyWorkspaceEntity[]) {
|
||||||
return companies.reduce(
|
return companies.reduce(
|
||||||
(acc, company) => {
|
(acc, company) => {
|
||||||
if (!company.domainName) {
|
if (!company.domainName) {
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
import { Logger, Scope } from '@nestjs/common';
|
import { Logger, Scope } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Any } from 'typeorm';
|
||||||
|
|
||||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository';
|
import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository';
|
||||||
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
|
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
|
||||||
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository';
|
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
|
||||||
import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service';
|
import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service';
|
||||||
|
|
||||||
export type BlocklistItemDeleteMessagesJobData = {
|
export type BlocklistItemDeleteMessagesJobData = {
|
||||||
@ -25,15 +25,10 @@ export class BlocklistItemDeleteMessagesJob {
|
|||||||
private readonly logger = new Logger(BlocklistItemDeleteMessagesJob.name);
|
private readonly logger = new Logger(BlocklistItemDeleteMessagesJob.name);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
@InjectObjectMetadataRepository(
|
|
||||||
MessageChannelMessageAssociationWorkspaceEntity,
|
|
||||||
)
|
|
||||||
private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository,
|
|
||||||
@InjectObjectMetadataRepository(BlocklistWorkspaceEntity)
|
@InjectObjectMetadataRepository(BlocklistWorkspaceEntity)
|
||||||
private readonly blocklistRepository: BlocklistRepository,
|
private readonly blocklistRepository: BlocklistRepository,
|
||||||
private readonly threadCleanerService: MessagingMessageCleanerService,
|
private readonly threadCleanerService: MessagingMessageCleanerService,
|
||||||
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(BlocklistItemDeleteMessagesJob.name)
|
@Process(BlocklistItemDeleteMessagesJob.name)
|
||||||
@ -65,24 +60,26 @@ export class BlocklistItemDeleteMessagesJob {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageChannels =
|
const messageChannelMessageAssociationRepository =
|
||||||
await this.messageChannelRepository.getIdsByWorkspaceMemberId(
|
await this.twentyORMManager.getRepository<MessageChannelMessageAssociationWorkspaceEntity>(
|
||||||
workspaceMemberId,
|
'messageChannelMessageAssociation',
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const messageChannelIds = messageChannels.map(({ id }) => id);
|
|
||||||
|
|
||||||
const rolesToDelete: ('from' | 'to')[] = ['from', 'to'];
|
const rolesToDelete: ('from' | 'to')[] = ['from', 'to'];
|
||||||
|
|
||||||
for (const messageChannelId of messageChannelIds) {
|
await messageChannelMessageAssociationRepository.delete({
|
||||||
await this.messageChannelMessageAssociationRepository.deleteByMessageParticipantHandleAndMessageChannelIdAndRoles(
|
messageChannel: {
|
||||||
handle,
|
connectedAccount: {
|
||||||
messageChannelId,
|
accountOwnerId: workspaceMemberId,
|
||||||
rolesToDelete,
|
},
|
||||||
workspaceId,
|
},
|
||||||
);
|
message: {
|
||||||
}
|
messageParticipants: {
|
||||||
|
handle,
|
||||||
|
role: Any(rolesToDelete),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await this.threadCleanerService.cleanWorkspaceThreads(workspaceId);
|
await this.threadCleanerService.cleanWorkspaceThreads(workspaceId);
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decora
|
|||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
|
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
@ -15,7 +16,6 @@ import {
|
|||||||
BlocklistItemDeleteMessagesJob,
|
BlocklistItemDeleteMessagesJob,
|
||||||
BlocklistItemDeleteMessagesJobData,
|
BlocklistItemDeleteMessagesJobData,
|
||||||
} from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job';
|
} from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
|
|
||||||
@ -27,8 +27,7 @@ export class MessagingBlocklistListener {
|
|||||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@OnEvent('blocklist.created')
|
@OnEvent('blocklist.created')
|
||||||
@ -61,14 +60,19 @@ export class MessagingBlocklistListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageChannel =
|
const messageChannelRepository =
|
||||||
await this.messageChannelRepository.getByConnectedAccountId(
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
connectedAccount[0].id,
|
'messageChannel',
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageChannel = await messageChannelRepository.findOneOrFail({
|
||||||
|
where: {
|
||||||
|
connectedAccountId: connectedAccount[0].id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch(
|
await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch(
|
||||||
messageChannel[0].id,
|
messageChannel.id,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -98,14 +102,19 @@ export class MessagingBlocklistListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageChannel =
|
const messageChannelRepository =
|
||||||
await this.messageChannelRepository.getByConnectedAccountId(
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
connectedAccount[0].id,
|
'messageChannel',
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageChannel = await messageChannelRepository.findOneOrFail({
|
||||||
|
where: {
|
||||||
|
connectedAccountId: connectedAccount[0].id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch(
|
await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch(
|
||||||
messageChannel[0].id,
|
messageChannel.id,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,22 +2,13 @@ import { Module } from '@nestjs/common';
|
|||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
||||||
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
||||||
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
|
||||||
import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity';
|
|
||||||
import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
WorkspaceDataSourceModule,
|
WorkspaceDataSourceModule,
|
||||||
ObjectMetadataRepositoryModule.forFeature([
|
|
||||||
MessageParticipantWorkspaceEntity,
|
|
||||||
MessageWorkspaceEntity,
|
|
||||||
MessageThreadWorkspaceEntity,
|
|
||||||
]),
|
|
||||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||||
ConnectedAccountModule,
|
ConnectedAccountModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import { ForbiddenException } from '@nestjs/common';
|
import { ForbiddenException } from '@nestjs/common';
|
||||||
|
|
||||||
import groupBy from 'lodash.groupby';
|
import groupBy from 'lodash.groupby';
|
||||||
|
import { Any } from 'typeorm';
|
||||||
|
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
||||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||||
@ -13,12 +14,11 @@ import { isDefined } from 'src/utils/is-defined';
|
|||||||
|
|
||||||
export class CanAccessMessageThreadService {
|
export class CanAccessMessageThreadService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelService: MessageChannelRepository,
|
|
||||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
@InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
|
@InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
|
||||||
private readonly workspaceMemberRepository: WorkspaceMemberRepository,
|
private readonly workspaceMemberRepository: WorkspaceMemberRepository,
|
||||||
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async canAccessMessageThread(
|
public async canAccessMessageThread(
|
||||||
@ -26,12 +26,19 @@ export class CanAccessMessageThreadService {
|
|||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
messageChannelMessageAssociations: any[],
|
messageChannelMessageAssociations: any[],
|
||||||
) {
|
) {
|
||||||
const messageChannels = await this.messageChannelService.getByIds(
|
const messageChannelRepository =
|
||||||
messageChannelMessageAssociations.map(
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
(association) => association.messageChannelId,
|
'messageChannel',
|
||||||
),
|
);
|
||||||
workspaceId,
|
const messageChannels = await messageChannelRepository.find({
|
||||||
);
|
where: {
|
||||||
|
id: Any(
|
||||||
|
messageChannelMessageAssociations.map(
|
||||||
|
(association) => association.messageChannelId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const messageChannelsGroupByVisibility = groupBy(
|
const messageChannelsGroupByVisibility = groupBy(
|
||||||
messageChannels,
|
messageChannels,
|
||||||
|
|||||||
@ -1,19 +1,15 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service';
|
import { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service';
|
||||||
import { MessageFindManyPreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook';
|
import { MessageFindManyPreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook';
|
||||||
import { MessageFindOnePreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook';
|
import { MessageFindOnePreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook';
|
||||||
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
ObjectMetadataRepositoryModule.forFeature([
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
MessageChannelMessageAssociationWorkspaceEntity,
|
|
||||||
MessageChannelWorkspaceEntity,
|
|
||||||
ConnectedAccountWorkspaceEntity,
|
ConnectedAccountWorkspaceEntity,
|
||||||
WorkspaceMemberWorkspaceEntity,
|
WorkspaceMemberWorkspaceEntity,
|
||||||
]),
|
]),
|
||||||
|
|||||||
@ -1,87 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { EntityManager } from 'typeorm';
|
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MessageChannelMessageAssociationRepository {
|
|
||||||
constructor(
|
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async deleteByMessageParticipantHandleAndMessageChannelIdAndRoles(
|
|
||||||
messageParticipantHandle: string,
|
|
||||||
messageChannelId: string,
|
|
||||||
rolesToDelete: ('from' | 'to' | 'cc' | 'bcc')[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const isHandleDomain = messageParticipantHandle.startsWith('@');
|
|
||||||
|
|
||||||
const messageChannel =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."messageChannel"
|
|
||||||
WHERE "id" = $1`,
|
|
||||||
[messageChannelId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
const messageChannelHandle = messageChannel[0].handle;
|
|
||||||
|
|
||||||
const messageChannelMessageAssociationIdsToDelete =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT "messageChannelMessageAssociation".id
|
|
||||||
FROM ${dataSourceSchema}."messageChannelMessageAssociation" "messageChannelMessageAssociation"
|
|
||||||
JOIN ${dataSourceSchema}."message" ON "messageChannelMessageAssociation"."messageId" = ${dataSourceSchema}."message"."id"
|
|
||||||
JOIN ${dataSourceSchema}."messageParticipant" "messageParticipant" ON ${dataSourceSchema}."message"."id" = "messageParticipant"."messageId"
|
|
||||||
WHERE "messageParticipant"."handle" != $1
|
|
||||||
AND "messageParticipant"."handle" ${isHandleDomain ? '~*' : '='} $2
|
|
||||||
AND "messageParticipant"."role" = ANY($3)
|
|
||||||
AND "messageChannelMessageAssociation"."messageChannelId" = $4`,
|
|
||||||
[
|
|
||||||
messageChannelHandle,
|
|
||||||
isHandleDomain
|
|
||||||
? // eslint-disable-next-line no-useless-escape
|
|
||||||
`.+@(.+\.)?${messageParticipantHandle.slice(1)}`
|
|
||||||
: messageParticipantHandle,
|
|
||||||
rolesToDelete,
|
|
||||||
messageChannelId,
|
|
||||||
],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
const messageChannelMessageAssociationIdsToDeleteArray =
|
|
||||||
messageChannelMessageAssociationIdsToDelete.map(
|
|
||||||
(messageChannelMessageAssociation: { id: string }) =>
|
|
||||||
messageChannelMessageAssociation.id,
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.deleteByIds(
|
|
||||||
messageChannelMessageAssociationIdsToDeleteArray,
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deleteByIds(
|
|
||||||
ids: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`DELETE FROM ${dataSourceSchema}."messageChannelMessageAssociation" WHERE "id" = ANY($1)`,
|
|
||||||
[ids],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,320 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { EntityManager } from 'typeorm';
|
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
import {
|
|
||||||
MessageChannelWorkspaceEntity,
|
|
||||||
MessageChannelSyncStatus,
|
|
||||||
MessageChannelSyncStage,
|
|
||||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MessageChannelRepository {
|
|
||||||
constructor(
|
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async create(
|
|
||||||
messageChannel: Pick<
|
|
||||||
MessageChannelWorkspaceEntity,
|
|
||||||
| 'id'
|
|
||||||
| 'connectedAccountId'
|
|
||||||
| 'type'
|
|
||||||
| 'handle'
|
|
||||||
| 'visibility'
|
|
||||||
| 'syncStatus'
|
|
||||||
>,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`INSERT INTO ${dataSourceSchema}."messageChannel" ("id", "connectedAccountId", "type", "handle", "visibility", "syncStatus")
|
|
||||||
VALUES ($1, $2, $3, $4, $5, $6)`,
|
|
||||||
[
|
|
||||||
messageChannel.id,
|
|
||||||
messageChannel.connectedAccountId,
|
|
||||||
messageChannel.type,
|
|
||||||
messageChannel.handle,
|
|
||||||
messageChannel.visibility,
|
|
||||||
messageChannel.syncStatus,
|
|
||||||
],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async resetSync(
|
|
||||||
connectedAccountId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel"
|
|
||||||
SET "syncStatus" = NULL,
|
|
||||||
"syncStage" = '${MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING}',
|
|
||||||
"syncCursor" = '',
|
|
||||||
"syncStageStartedAt" = NULL
|
|
||||||
WHERE "connectedAccountId" = $1`,
|
|
||||||
[connectedAccountId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getAll(
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageChannelWorkspaceEntity[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."messageChannel"`,
|
|
||||||
[],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByConnectedAccountId(
|
|
||||||
connectedAccountId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageChannelWorkspaceEntity[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."messageChannel" WHERE "connectedAccountId" = $1 AND "type" = 'email' LIMIT 1`,
|
|
||||||
[connectedAccountId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getFirstByConnectedAccountIdOrFail(
|
|
||||||
connectedAccountId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
): Promise<MessageChannelWorkspaceEntity> {
|
|
||||||
const messageChannel = await this.getFirstByConnectedAccountId(
|
|
||||||
connectedAccountId,
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!messageChannel) {
|
|
||||||
throw new Error(
|
|
||||||
`Message channel for connected account ${connectedAccountId} not found in workspace ${workspaceId}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return messageChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getFirstByConnectedAccountId(
|
|
||||||
connectedAccountId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageChannelWorkspaceEntity | undefined> {
|
|
||||||
const messageChannels = await this.getByConnectedAccountId(
|
|
||||||
connectedAccountId,
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return messageChannels[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByIds(
|
|
||||||
ids: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageChannelWorkspaceEntity[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."messageChannel" WHERE "id" = ANY($1)`,
|
|
||||||
[ids],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getById(
|
|
||||||
id: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageChannelWorkspaceEntity> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const messageChannels =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."messageChannel" WHERE "id" = $1`,
|
|
||||||
[id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return messageChannels[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getIdsByWorkspaceMemberId(
|
|
||||||
workspaceMemberId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageChannelWorkspaceEntity[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const messageChannelIds =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT "messageChannel".id FROM ${dataSourceSchema}."messageChannel" "messageChannel"
|
|
||||||
JOIN ${dataSourceSchema}."connectedAccount" ON "messageChannel"."connectedAccountId" = ${dataSourceSchema}."connectedAccount"."id"
|
|
||||||
WHERE ${dataSourceSchema}."connectedAccount"."accountOwnerId" = $1`,
|
|
||||||
[workspaceMemberId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return messageChannelIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateSyncStatus(
|
|
||||||
id: string,
|
|
||||||
syncStatus: MessageChannelSyncStatus,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const needsToUpdateSyncedAt =
|
|
||||||
syncStatus === MessageChannelSyncStatus.ACTIVE;
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel" SET "syncStatus" = $1 ${
|
|
||||||
needsToUpdateSyncedAt ? `, "syncedAt" = NOW()` : ''
|
|
||||||
} WHERE "id" = $2`,
|
|
||||||
[syncStatus, id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateSyncStage(
|
|
||||||
id: string,
|
|
||||||
syncStage: MessageChannelSyncStage,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const needsToUpdateSyncStageStartedAt =
|
|
||||||
syncStage === MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING ||
|
|
||||||
syncStage === MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING;
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel" SET "syncStage" = $1 ${
|
|
||||||
needsToUpdateSyncStageStartedAt ? `, "syncStageStartedAt" = NOW()` : ''
|
|
||||||
} WHERE "id" = $2`,
|
|
||||||
[syncStage, id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async resetSyncStageStartedAt(
|
|
||||||
id: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel" SET "syncStageStartedAt" = NULL WHERE "id" = $1`,
|
|
||||||
[id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateLastSyncCursorIfHigher(
|
|
||||||
id: string,
|
|
||||||
syncCursor: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel" SET "syncCursor" = $1
|
|
||||||
WHERE "id" = $2
|
|
||||||
AND ("syncCursor" < $1 OR "syncCursor" = '')`,
|
|
||||||
[syncCursor, id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async resetSyncCursor(
|
|
||||||
id: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel" SET "syncCursor" = ''
|
|
||||||
WHERE "id" = $1`,
|
|
||||||
[id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async incrementThrottleFailureCount(
|
|
||||||
id: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel" SET "throttleFailureCount" = "throttleFailureCount" + 1
|
|
||||||
WHERE "id" = $1`,
|
|
||||||
[id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async resetThrottleFailureCount(
|
|
||||||
id: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageChannel" SET "throttleFailureCount" = 0
|
|
||||||
WHERE "id" = $1`,
|
|
||||||
[id],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,209 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { EntityManager } from 'typeorm';
|
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
|
||||||
import { ParticipantWithId } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MessageParticipantRepository {
|
|
||||||
constructor(
|
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async getByHandles(
|
|
||||||
handles: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageParticipantWorkspaceEntity[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."messageParticipant" WHERE "handle" = ANY($1)`,
|
|
||||||
[handles],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateParticipantsPersonId(
|
|
||||||
participantIds: string[],
|
|
||||||
personId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageParticipant" SET "personId" = $1 WHERE "id" = ANY($2)`,
|
|
||||||
[personId, participantIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateParticipantsPersonIdAndReturn(
|
|
||||||
participantIds: string[],
|
|
||||||
personId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageParticipant" SET "personId" = $1 WHERE "id" = ANY($2) RETURNING *`,
|
|
||||||
[personId, participantIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateParticipantsWorkspaceMemberId(
|
|
||||||
participantIds: string[],
|
|
||||||
workspaceMemberId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageParticipant" SET "workspaceMemberId" = $1 WHERE "id" = ANY($2)`,
|
|
||||||
[workspaceMemberId, participantIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async removePersonIdByHandle(
|
|
||||||
handle: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageParticipant" SET "personId" = NULL WHERE "handle" = $1`,
|
|
||||||
[handle],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async removeWorkspaceMemberIdByHandle(
|
|
||||||
handle: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
) {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`UPDATE ${dataSourceSchema}."messageParticipant" SET "workspaceMemberId" = NULL WHERE "handle" = $1`,
|
|
||||||
[handle],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing(
|
|
||||||
messageChannelId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<ParticipantWithId[]> {
|
|
||||||
if (!messageChannelId || !workspaceId) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const messageParticipants: ParticipantWithId[] =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT "messageParticipant".id,
|
|
||||||
"messageParticipant"."role",
|
|
||||||
"messageParticipant"."handle",
|
|
||||||
"messageParticipant"."displayName",
|
|
||||||
"messageParticipant"."personId",
|
|
||||||
"messageParticipant"."workspaceMemberId",
|
|
||||||
"messageParticipant"."messageId"
|
|
||||||
FROM ${dataSourceSchema}."messageParticipant" "messageParticipant"
|
|
||||||
LEFT JOIN ${dataSourceSchema}."message" ON "messageParticipant"."messageId" = ${dataSourceSchema}."message"."id"
|
|
||||||
LEFT JOIN ${dataSourceSchema}."messageChannelMessageAssociation" ON ${dataSourceSchema}."messageChannelMessageAssociation"."messageId" = ${dataSourceSchema}."message"."id"
|
|
||||||
WHERE ${dataSourceSchema}."messageChannelMessageAssociation"."messageChannelId" = $1
|
|
||||||
AND "messageParticipant"."personId" IS NULL
|
|
||||||
AND "messageParticipant"."workspaceMemberId" IS NULL
|
|
||||||
AND ${dataSourceSchema}."message"."direction" = 'outgoing'`,
|
|
||||||
[messageChannelId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return messageParticipants;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberId(
|
|
||||||
messageChannelId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<ParticipantWithId[]> {
|
|
||||||
if (!messageChannelId || !workspaceId) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const messageParticipants: ParticipantWithId[] =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT "messageParticipant".id,
|
|
||||||
"messageParticipant"."role",
|
|
||||||
"messageParticipant"."handle",
|
|
||||||
"messageParticipant"."displayName",
|
|
||||||
"messageParticipant"."personId",
|
|
||||||
"messageParticipant"."workspaceMemberId",
|
|
||||||
"messageParticipant"."messageId"
|
|
||||||
FROM ${dataSourceSchema}."messageParticipant" "messageParticipant"
|
|
||||||
LEFT JOIN ${dataSourceSchema}."message" ON "messageParticipant"."messageId" = ${dataSourceSchema}."message"."id"
|
|
||||||
LEFT JOIN ${dataSourceSchema}."messageChannelMessageAssociation" ON ${dataSourceSchema}."messageChannelMessageAssociation"."messageId" = ${dataSourceSchema}."message"."id"
|
|
||||||
WHERE ${dataSourceSchema}."messageChannelMessageAssociation"."messageChannelId" = $1
|
|
||||||
AND "messageParticipant"."personId" IS NULL
|
|
||||||
AND "messageParticipant"."workspaceMemberId" IS NULL`,
|
|
||||||
[messageChannelId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return messageParticipants;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getWithoutPersonIdAndWorkspaceMemberId(
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<ParticipantWithId[]> {
|
|
||||||
if (!workspaceId) {
|
|
||||||
throw new Error('WorkspaceId is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const messageParticipants: ParticipantWithId[] =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT "messageParticipant".*
|
|
||||||
FROM ${dataSourceSchema}."messageParticipant" "messageParticipant"
|
|
||||||
WHERE "messageParticipant"."personId" IS NULL
|
|
||||||
AND "messageParticipant"."workspaceMemberId" IS NULL`,
|
|
||||||
[],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return messageParticipants;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { EntityManager } from 'typeorm';
|
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MessageThreadRepository {
|
|
||||||
constructor(
|
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async getOrphanThreadIdsPaginated(
|
|
||||||
limit: number,
|
|
||||||
offset: number,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<string[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const orphanThreads = await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT mt.id
|
|
||||||
FROM ${dataSourceSchema}."messageThread" mt
|
|
||||||
LEFT JOIN ${dataSourceSchema}."message" m ON mt.id = m."messageThreadId"
|
|
||||||
WHERE m."messageThreadId" IS NULL
|
|
||||||
LIMIT $1 OFFSET $2`,
|
|
||||||
[limit, offset],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return orphanThreads.map(({ id }) => id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deleteByIds(
|
|
||||||
messageThreadIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`DELETE FROM ${dataSourceSchema}."messageThread" WHERE id = ANY($1)`,
|
|
||||||
[messageThreadIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async insert(
|
|
||||||
messageThreadId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`INSERT INTO ${dataSourceSchema}."messageThread" (id) VALUES ($1)`,
|
|
||||||
[messageThreadId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,137 +0,0 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
|
||||||
|
|
||||||
import { EntityManager } from 'typeorm';
|
|
||||||
|
|
||||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
||||||
import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class MessageRepository {
|
|
||||||
constructor(
|
|
||||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public async getNonAssociatedMessageIdsPaginated(
|
|
||||||
limit: number,
|
|
||||||
offset: number,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<string[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const nonAssociatedMessages =
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT m.id FROM ${dataSourceSchema}."message" m
|
|
||||||
LEFT JOIN ${dataSourceSchema}."messageChannelMessageAssociation" mcma
|
|
||||||
ON m.id = mcma."messageId"
|
|
||||||
WHERE mcma.id IS NULL
|
|
||||||
LIMIT $1 OFFSET $2`,
|
|
||||||
[limit, offset],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
return nonAssociatedMessages.map(({ id }) => id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getFirstOrNullByHeaderMessageId(
|
|
||||||
headerMessageId: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageWorkspaceEntity | null> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
const messages = await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."message" WHERE "headerMessageId" = $1 LIMIT 1`,
|
|
||||||
[headerMessageId],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!messages || messages.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByIds(
|
|
||||||
messageIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageWorkspaceEntity[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."message" WHERE "id" = ANY($1)`,
|
|
||||||
[messageIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async deleteByIds(
|
|
||||||
messageIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`DELETE FROM ${dataSourceSchema}."message" WHERE "id" = ANY($1)`,
|
|
||||||
[messageIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async getByMessageThreadIds(
|
|
||||||
messageThreadIds: string[],
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<MessageWorkspaceEntity[]> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
return await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`SELECT * FROM ${dataSourceSchema}."message" WHERE "messageThreadId" = ANY($1)`,
|
|
||||||
[messageThreadIds],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async insert(
|
|
||||||
id: string,
|
|
||||||
headerMessageId: string,
|
|
||||||
subject: string,
|
|
||||||
receivedAt: Date,
|
|
||||||
messageDirection: string,
|
|
||||||
messageThreadId: string,
|
|
||||||
text: string,
|
|
||||||
workspaceId: string,
|
|
||||||
transactionManager?: EntityManager,
|
|
||||||
): Promise<void> {
|
|
||||||
const dataSourceSchema =
|
|
||||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
|
||||||
|
|
||||||
await this.workspaceDataSourceService.executeRawQuery(
|
|
||||||
`INSERT INTO ${dataSourceSchema}."message" ("id", "headerMessageId", "subject", "receivedAt", "direction", "messageThreadId", "text") VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
|
||||||
[
|
|
||||||
id,
|
|
||||||
headerMessageId,
|
|
||||||
subject,
|
|
||||||
receivedAt,
|
|
||||||
messageDirection,
|
|
||||||
messageThreadId,
|
|
||||||
text,
|
|
||||||
],
|
|
||||||
workspaceId,
|
|
||||||
transactionManager,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,11 +3,9 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||||
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
||||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
|
||||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service';
|
import { AccountsToReconnectService } from 'src/modules/connected-account/services/accounts-to-reconnect.service';
|
||||||
import { AccountsToReconnectKeys } from 'src/modules/connected-account/types/accounts-to-reconnect-key-value.type';
|
import { AccountsToReconnectKeys } from 'src/modules/connected-account/types/accounts-to-reconnect-key-value.type';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import {
|
import {
|
||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
MessageChannelSyncStatus,
|
MessageChannelSyncStatus,
|
||||||
@ -17,44 +15,57 @@ import {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessagingChannelSyncStatusService {
|
export class MessagingChannelSyncStatusService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly twentyORMManager: TwentyORMManager,
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
private readonly accountsToReconnectService: AccountsToReconnectService,
|
private readonly accountsToReconnectService: AccountsToReconnectService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async scheduleFullMessageListFetch(
|
public async scheduleFullMessageListFetch(messageChannelId: string) {
|
||||||
messageChannelId: string,
|
const messageChannelRepository =
|
||||||
workspaceId: string,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
) {
|
'messageChannel',
|
||||||
await this.messageChannelRepository.updateSyncStage(
|
);
|
||||||
messageChannelId,
|
|
||||||
MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
await messageChannelRepository.update(
|
||||||
workspaceId,
|
{
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async schedulePartialMessageListFetch(
|
public async schedulePartialMessageListFetch(messageChannelId: string) {
|
||||||
messageChannelId: string,
|
const messageChannelRepository =
|
||||||
workspaceId: string,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
) {
|
'messageChannel',
|
||||||
await this.messageChannelRepository.updateSyncStage(
|
);
|
||||||
messageChannelId,
|
|
||||||
MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING,
|
await messageChannelRepository.update(
|
||||||
workspaceId,
|
{
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.PARTIAL_MESSAGE_LIST_FETCH_PENDING,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async scheduleMessagesImport(
|
public async scheduleMessagesImport(messageChannelId: string) {
|
||||||
messageChannelId: string,
|
const messageChannelRepository =
|
||||||
workspaceId: string,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
) {
|
'messageChannel',
|
||||||
await this.messageChannelRepository.updateSyncStage(
|
);
|
||||||
messageChannelId,
|
|
||||||
MessageChannelSyncStage.MESSAGES_IMPORT_PENDING,
|
await messageChannelRepository.update(
|
||||||
workspaceId,
|
{
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_PENDING,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,62 +77,75 @@ export class MessagingChannelSyncStatusService {
|
|||||||
`messages-to-import:${workspaceId}:gmail:${messageChannelId}`,
|
`messages-to-import:${workspaceId}:gmail:${messageChannelId}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.resetSyncCursor(
|
const messageChannelRepository =
|
||||||
messageChannelId,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
|
);
|
||||||
|
|
||||||
|
await messageChannelRepository.update(
|
||||||
|
{
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncCursor: '',
|
||||||
|
syncStageStartedAt: null,
|
||||||
|
throttleFailureCount: 0,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.resetSyncStageStartedAt(
|
await this.scheduleFullMessageListFetch(messageChannelId);
|
||||||
messageChannelId,
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.messageChannelRepository.resetThrottleFailureCount(
|
|
||||||
messageChannelId,
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.scheduleFullMessageListFetch(messageChannelId, workspaceId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async markAsMessagesListFetchOngoing(
|
public async markAsMessagesListFetchOngoing(messageChannelId: string) {
|
||||||
messageChannelId: string,
|
const messageChannelRepository =
|
||||||
workspaceId: string,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
) {
|
'messageChannel',
|
||||||
await this.messageChannelRepository.updateSyncStage(
|
);
|
||||||
messageChannelId,
|
|
||||||
MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING,
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.messageChannelRepository.updateSyncStatus(
|
await messageChannelRepository.update(
|
||||||
messageChannelId,
|
{
|
||||||
MessageChannelSyncStatus.ONGOING,
|
id: messageChannelId,
|
||||||
workspaceId,
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING,
|
||||||
|
syncStatus: MessageChannelSyncStatus.ONGOING,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async markAsCompletedAndSchedulePartialMessageListFetch(
|
public async markAsCompletedAndSchedulePartialMessageListFetch(
|
||||||
messageChannelId: string,
|
messageChannelId: string,
|
||||||
workspaceId: string,
|
|
||||||
) {
|
) {
|
||||||
await this.messageChannelRepository.updateSyncStatus(
|
const messageChannelRepository =
|
||||||
messageChannelId,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
MessageChannelSyncStatus.ACTIVE,
|
'messageChannel',
|
||||||
workspaceId,
|
);
|
||||||
|
|
||||||
|
await messageChannelRepository.update(
|
||||||
|
{
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncStatus: MessageChannelSyncStatus.ACTIVE,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.schedulePartialMessageListFetch(messageChannelId, workspaceId);
|
await this.schedulePartialMessageListFetch(messageChannelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async markAsMessagesImportOngoing(
|
public async markAsMessagesImportOngoing(messageChannelId: string) {
|
||||||
messageChannelId: string,
|
const messageChannelRepository =
|
||||||
workspaceId: string,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
) {
|
'messageChannel',
|
||||||
await this.messageChannelRepository.updateSyncStage(
|
);
|
||||||
messageChannelId,
|
|
||||||
MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING,
|
await messageChannelRepository.update(
|
||||||
workspaceId,
|
{
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,16 +157,19 @@ export class MessagingChannelSyncStatusService {
|
|||||||
`messages-to-import:${workspaceId}:gmail:${messageChannelId}`,
|
`messages-to-import:${workspaceId}:gmail:${messageChannelId}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.updateSyncStage(
|
const messageChannelRepository =
|
||||||
messageChannelId,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
MessageChannelSyncStage.FAILED,
|
'messageChannel',
|
||||||
workspaceId,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
await this.messageChannelRepository.updateSyncStatus(
|
await messageChannelRepository.update(
|
||||||
messageChannelId,
|
{
|
||||||
MessageChannelSyncStatus.FAILED_UNKNOWN,
|
id: messageChannelId,
|
||||||
workspaceId,
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.FAILED,
|
||||||
|
syncStatus: MessageChannelSyncStatus.FAILED_UNKNOWN,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,16 +181,19 @@ export class MessagingChannelSyncStatusService {
|
|||||||
`messages-to-import:${workspaceId}:gmail:${messageChannelId}`,
|
`messages-to-import:${workspaceId}:gmail:${messageChannelId}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.updateSyncStage(
|
const messageChannelRepository =
|
||||||
messageChannelId,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
MessageChannelSyncStage.FAILED,
|
'messageChannel',
|
||||||
workspaceId,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
await this.messageChannelRepository.updateSyncStatus(
|
await messageChannelRepository.update(
|
||||||
messageChannelId,
|
{
|
||||||
MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
|
id: messageChannelId,
|
||||||
workspaceId,
|
},
|
||||||
|
{
|
||||||
|
syncStage: MessageChannelSyncStage.FAILED,
|
||||||
|
syncStatus: MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.addToAccountsToReconnect(messageChannelId, workspaceId);
|
await this.addToAccountsToReconnect(messageChannelId, workspaceId);
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
@ -12,8 +11,7 @@ import { Process } from 'src/engine/integrations/message-queue/decorators/proces
|
|||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import {
|
import {
|
||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
MessageChannelWorkspaceEntity,
|
MessageChannelWorkspaceEntity,
|
||||||
@ -25,15 +23,12 @@ import {
|
|||||||
|
|
||||||
@Processor(MessageQueue.cronQueue)
|
@Processor(MessageQueue.cronQueue)
|
||||||
export class MessagingMessageListFetchCronJob {
|
export class MessagingMessageListFetchCronJob {
|
||||||
private readonly logger = new Logger(MessagingMessageListFetchCronJob.name);
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Workspace, 'core')
|
@InjectRepository(Workspace, 'core')
|
||||||
private readonly workspaceRepository: Repository<Workspace>,
|
private readonly workspaceRepository: Repository<Workspace>,
|
||||||
@InjectMessageQueue(MessageQueue.messagingQueue)
|
@InjectMessageQueue(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(MessagingMessageListFetchCronJob.name)
|
@Process(MessagingMessageListFetchCronJob.name)
|
||||||
@ -45,9 +40,15 @@ export class MessagingMessageListFetchCronJob {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (const activeWorkspace of activeWorkspaces) {
|
for (const activeWorkspace of activeWorkspaces) {
|
||||||
const messageChannels = await this.messageChannelRepository.getAll(
|
const messageChannelRepository =
|
||||||
activeWorkspace.id,
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>(
|
||||||
);
|
activeWorkspace.id,
|
||||||
|
'messageChannel',
|
||||||
|
);
|
||||||
|
|
||||||
|
const messageChannels = await messageChannelRepository.find({
|
||||||
|
select: ['id'],
|
||||||
|
});
|
||||||
|
|
||||||
for (const messageChannel of messageChannels) {
|
for (const messageChannel of messageChannels) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -12,8 +12,7 @@ import { Process } from 'src/engine/integrations/message-queue/decorators/proces
|
|||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import {
|
import {
|
||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
MessageChannelWorkspaceEntity,
|
MessageChannelWorkspaceEntity,
|
||||||
@ -32,8 +31,7 @@ export class MessagingMessagesImportCronJob {
|
|||||||
private readonly workspaceRepository: Repository<Workspace>,
|
private readonly workspaceRepository: Repository<Workspace>,
|
||||||
@InjectMessageQueue(MessageQueue.messagingQueue)
|
@InjectMessageQueue(MessageQueue.messagingQueue)
|
||||||
private readonly messageQueueService: MessageQueueService,
|
private readonly messageQueueService: MessageQueueService,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(MessagingMessagesImportCronJob.name)
|
@Process(MessagingMessagesImportCronJob.name)
|
||||||
@ -45,9 +43,15 @@ export class MessagingMessagesImportCronJob {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (const activeWorkspace of activeWorkspaces) {
|
for (const activeWorkspace of activeWorkspaces) {
|
||||||
const messageChannels = await this.messageChannelRepository.getAll(
|
const messageChannelRepository =
|
||||||
activeWorkspace.id,
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>(
|
||||||
);
|
activeWorkspace.id,
|
||||||
|
'messageChannel',
|
||||||
|
);
|
||||||
|
|
||||||
|
const messageChannels = await messageChannelRepository.find({
|
||||||
|
select: ['id', 'isSyncEnabled', 'syncStage'],
|
||||||
|
});
|
||||||
|
|
||||||
for (const messageChannel of messageChannels) {
|
for (const messageChannel of messageChannels) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@ -12,8 +12,6 @@ import { EmailAliasManagerModule } from 'src/modules/connected-account/email-ali
|
|||||||
import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module';
|
import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module';
|
import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module';
|
||||||
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
|
||||||
import { MessagingGmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider';
|
import { MessagingGmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider';
|
||||||
import { MessagingGmailFetchByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-by-batch.service';
|
import { MessagingGmailFetchByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-by-batch.service';
|
||||||
import { MessagingGmailFetchMessagesByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service';
|
import { MessagingGmailFetchMessagesByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service';
|
||||||
@ -29,8 +27,6 @@ import { MessageParticipantManagerModule } from 'src/modules/messaging/message-p
|
|||||||
EnvironmentModule,
|
EnvironmentModule,
|
||||||
ObjectMetadataRepositoryModule.forFeature([
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
ConnectedAccountWorkspaceEntity,
|
ConnectedAccountWorkspaceEntity,
|
||||||
MessageChannelWorkspaceEntity,
|
|
||||||
MessageChannelMessageAssociationWorkspaceEntity,
|
|
||||||
BlocklistWorkspaceEntity,
|
BlocklistWorkspaceEntity,
|
||||||
]),
|
]),
|
||||||
MessagingCommonModule,
|
MessagingCommonModule,
|
||||||
|
|||||||
@ -4,10 +4,10 @@ import { Process } from 'src/engine/integrations/message-queue/decorators/proces
|
|||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { isThrottled } from 'src/modules/connected-account/utils/is-throttled';
|
import { isThrottled } from 'src/modules/connected-account/utils/is-throttled';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import {
|
import {
|
||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
MessageChannelWorkspaceEntity,
|
MessageChannelWorkspaceEntity,
|
||||||
@ -33,9 +33,8 @@ export class MessagingMessageListFetchJob {
|
|||||||
private readonly messagingPartialMessageListFetchService: MessagingPartialMessageListFetchService,
|
private readonly messagingPartialMessageListFetchService: MessagingPartialMessageListFetchService,
|
||||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
private readonly messagingTelemetryService: MessagingTelemetryService,
|
private readonly messagingTelemetryService: MessagingTelemetryService,
|
||||||
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(MessagingMessageListFetchJob.name)
|
@Process(MessagingMessageListFetchJob.name)
|
||||||
@ -48,10 +47,16 @@ export class MessagingMessageListFetchJob {
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const messageChannel = await this.messageChannelRepository.getById(
|
const messageChannelRepository =
|
||||||
messageChannelId,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageChannel = await messageChannelRepository.findOne({
|
||||||
|
where: {
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!messageChannel) {
|
if (!messageChannel) {
|
||||||
await this.messagingTelemetryService.track({
|
await this.messagingTelemetryService.track({
|
||||||
|
|||||||
@ -4,10 +4,10 @@ import { Process } from 'src/engine/integrations/message-queue/decorators/proces
|
|||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { isThrottled } from 'src/modules/connected-account/utils/is-throttled';
|
import { isThrottled } from 'src/modules/connected-account/utils/is-throttled';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import {
|
import {
|
||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
MessageChannelWorkspaceEntity,
|
MessageChannelWorkspaceEntity,
|
||||||
@ -29,9 +29,8 @@ export class MessagingMessagesImportJob {
|
|||||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
private readonly gmailFetchMessageContentFromCacheService: MessagingMessagesImportService,
|
private readonly gmailFetchMessageContentFromCacheService: MessagingMessagesImportService,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
private readonly messagingTelemetryService: MessagingTelemetryService,
|
private readonly messagingTelemetryService: MessagingTelemetryService,
|
||||||
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(MessagingMessagesImportJob.name)
|
@Process(MessagingMessagesImportJob.name)
|
||||||
@ -44,10 +43,16 @@ export class MessagingMessagesImportJob {
|
|||||||
messageChannelId,
|
messageChannelId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const messageChannel = await this.messageChannelRepository.getById(
|
const messageChannelRepository =
|
||||||
messageChannelId,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageChannel = await messageChannelRepository.findOne({
|
||||||
|
where: {
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!messageChannel) {
|
if (!messageChannel) {
|
||||||
await this.messagingTelemetryService.track({
|
await this.messagingTelemetryService.track({
|
||||||
|
|||||||
@ -59,13 +59,11 @@ export class MessagingOngoingStaleJob {
|
|||||||
case MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING:
|
case MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING:
|
||||||
await this.messagingChannelSyncStatusService.schedulePartialMessageListFetch(
|
await this.messagingChannelSyncStatusService.schedulePartialMessageListFetch(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING:
|
case MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING:
|
||||||
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -3,9 +3,9 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import snakeCase from 'lodash.snakecase';
|
import snakeCase from 'lodash.snakecase';
|
||||||
|
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
import { MESSAGING_THROTTLE_MAX_ATTEMPTS } from 'src/modules/messaging/message-import-manager/constants/messaging-throttle-max-attempts';
|
import { MESSAGING_THROTTLE_MAX_ATTEMPTS } from 'src/modules/messaging/message-import-manager/constants/messaging-throttle-max-attempts';
|
||||||
@ -28,8 +28,7 @@ export class MessagingErrorHandlingService {
|
|||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
||||||
private readonly messagingTelemetryService: MessagingTelemetryService,
|
private readonly messagingTelemetryService: MessagingTelemetryService,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async handleGmailError(
|
public async handleGmailError(
|
||||||
@ -263,21 +262,18 @@ export class MessagingErrorHandlingService {
|
|||||||
case 'full-message-list-fetch':
|
case 'full-message-list-fetch':
|
||||||
await this.messagingChannelSyncStatusService.scheduleFullMessageListFetch(
|
await this.messagingChannelSyncStatusService.scheduleFullMessageListFetch(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'partial-message-list-fetch':
|
case 'partial-message-list-fetch':
|
||||||
await this.messagingChannelSyncStatusService.schedulePartialMessageListFetch(
|
await this.messagingChannelSyncStatusService.schedulePartialMessageListFetch(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'messages-import':
|
case 'messages-import':
|
||||||
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -290,9 +286,17 @@ export class MessagingErrorHandlingService {
|
|||||||
messageChannel: MessageChannelWorkspaceEntity,
|
messageChannel: MessageChannelWorkspaceEntity,
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.messageChannelRepository.incrementThrottleFailureCount(
|
const messageChannelRepository =
|
||||||
messageChannel.id,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
|
);
|
||||||
|
|
||||||
|
await messageChannelRepository.increment(
|
||||||
|
{
|
||||||
|
id: messageChannel.id,
|
||||||
|
},
|
||||||
|
'throttleFailureCount',
|
||||||
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messagingTelemetryService.track({
|
await this.messagingTelemetryService.track({
|
||||||
|
|||||||
@ -7,10 +7,8 @@ import { Any, EntityManager } from 'typeorm';
|
|||||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||||
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
||||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
|
||||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
||||||
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
@ -31,8 +29,6 @@ export class MessagingFullMessageListFetchService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService,
|
||||||
@ -47,7 +43,6 @@ export class MessagingFullMessageListFetchService {
|
|||||||
) {
|
) {
|
||||||
await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing(
|
await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const gmailClient: gmail_v1.Gmail =
|
const gmailClient: gmail_v1.Gmail =
|
||||||
@ -70,19 +65,23 @@ export class MessagingFullMessageListFetchService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.messageChannelRepository.resetThrottleFailureCount(
|
const messageChannelRepository =
|
||||||
messageChannel.id,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.resetSyncStageStartedAt(
|
await messageChannelRepository.update(
|
||||||
messageChannel.id,
|
{
|
||||||
workspaceId,
|
id: messageChannel.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
throttleFailureCount: 0,
|
||||||
|
syncStageStartedAt: null,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,11 +215,32 @@ export class MessagingFullMessageListFetchService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.messageChannelRepository.updateLastSyncCursorIfHigher(
|
const messageChannelRepository =
|
||||||
messageChannelId,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
historyId,
|
'messageChannel',
|
||||||
workspaceId,
|
);
|
||||||
|
|
||||||
|
const messageChannel = await messageChannelRepository.findOneOrFail(
|
||||||
|
{
|
||||||
|
where: {
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
},
|
||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const currentSyncCursor = messageChannel.syncCursor;
|
||||||
|
|
||||||
|
if (!currentSyncCursor || historyId > currentSyncCursor) {
|
||||||
|
await messageChannelRepository.update(
|
||||||
|
{
|
||||||
|
id: messageChannel.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncCursor: historyId,
|
||||||
|
},
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,13 +6,13 @@ import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache
|
|||||||
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
||||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository';
|
import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository';
|
||||||
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
|
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
|
||||||
import { EmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/services/email-alias-manager.service';
|
import { EmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/services/email-alias-manager.service';
|
||||||
import { RefreshAccessTokenService } from 'src/modules/connected-account/refresh-access-token-manager/services/refresh-access-token.service';
|
import { RefreshAccessTokenService } from 'src/modules/connected-account/refresh-access-token-manager/services/refresh-access-token.service';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
||||||
import {
|
import {
|
||||||
MessageChannelSyncStage,
|
MessageChannelSyncStage,
|
||||||
@ -40,12 +40,11 @@ export class MessagingMessagesImportService {
|
|||||||
private readonly messagingTelemetryService: MessagingTelemetryService,
|
private readonly messagingTelemetryService: MessagingTelemetryService,
|
||||||
@InjectObjectMetadataRepository(BlocklistWorkspaceEntity)
|
@InjectObjectMetadataRepository(BlocklistWorkspaceEntity)
|
||||||
private readonly blocklistRepository: BlocklistRepository,
|
private readonly blocklistRepository: BlocklistRepository,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
private readonly emailAliasManagerService: EmailAliasManagerService,
|
private readonly emailAliasManagerService: EmailAliasManagerService,
|
||||||
private readonly isFeatureEnabledService: IsFeatureEnabledService,
|
private readonly isFeatureEnabledService: IsFeatureEnabledService,
|
||||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async processMessageBatchImport(
|
async processMessageBatchImport(
|
||||||
@ -73,7 +72,6 @@ export class MessagingMessagesImportService {
|
|||||||
|
|
||||||
await this.messagingChannelSyncStatusService.markAsMessagesImportOngoing(
|
await this.messagingChannelSyncStatusService.markAsMessagesImportOngoing(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let accessToken: string;
|
let accessToken: string;
|
||||||
@ -139,7 +137,6 @@ export class MessagingMessagesImportService {
|
|||||||
if (!messageIdsToFetch?.length) {
|
if (!messageIdsToFetch?.length) {
|
||||||
await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch(
|
await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return await this.trackMessageImportCompleted(
|
return await this.trackMessageImportCompleted(
|
||||||
@ -180,23 +177,26 @@ export class MessagingMessagesImportService {
|
|||||||
) {
|
) {
|
||||||
await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch(
|
await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.messageChannelRepository.resetThrottleFailureCount(
|
const messageChannelRepository =
|
||||||
messageChannel.id,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.resetSyncStageStartedAt(
|
await messageChannelRepository.update(
|
||||||
messageChannel.id,
|
{
|
||||||
workspaceId,
|
id: messageChannel.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
throttleFailureCount: 0,
|
||||||
|
syncStageStartedAt: null,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
return await this.trackMessageImportCompleted(
|
return await this.trackMessageImportCompleted(
|
||||||
|
|||||||
@ -6,10 +6,8 @@ import { Any } from 'typeorm';
|
|||||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||||
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
||||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
|
||||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
|
||||||
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
@ -26,8 +24,6 @@ export class MessagingPartialMessageListFetchService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
private readonly gmailClientProvider: MessagingGmailClientProvider,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
@InjectCacheStorage(CacheStorageNamespace.Messaging)
|
||||||
private readonly cacheStorage: CacheStorageService,
|
private readonly cacheStorage: CacheStorageService,
|
||||||
private readonly gmailErrorHandlingService: MessagingErrorHandlingService,
|
private readonly gmailErrorHandlingService: MessagingErrorHandlingService,
|
||||||
@ -44,7 +40,6 @@ export class MessagingPartialMessageListFetchService {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing(
|
await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const lastSyncHistoryId = messageChannel.syncCursor;
|
const lastSyncHistoryId = messageChannel.syncCursor;
|
||||||
@ -69,14 +64,19 @@ export class MessagingPartialMessageListFetchService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.messageChannelRepository.resetThrottleFailureCount(
|
const messageChannelRepository =
|
||||||
messageChannel.id,
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.resetSyncStageStartedAt(
|
await messageChannelRepository.update(
|
||||||
messageChannel.id,
|
{
|
||||||
workspaceId,
|
id: messageChannel.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
throttleFailureCount: 0,
|
||||||
|
syncStageStartedAt: null,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!historyId) {
|
if (!historyId) {
|
||||||
@ -92,7 +92,6 @@ export class MessagingPartialMessageListFetchService {
|
|||||||
|
|
||||||
await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch(
|
await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -147,15 +146,21 @@ export class MessagingPartialMessageListFetchService {
|
|||||||
`Deleted ${messagesDeleted.length} messages for workspace ${workspaceId} and account ${connectedAccount.id}`,
|
`Deleted ${messagesDeleted.length} messages for workspace ${workspaceId} and account ${connectedAccount.id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.messageChannelRepository.updateLastSyncCursorIfHigher(
|
const currentSyncCursor = messageChannel.syncCursor;
|
||||||
messageChannel.id,
|
|
||||||
historyId,
|
if (!currentSyncCursor || historyId > currentSyncCursor) {
|
||||||
workspaceId,
|
await messageChannelRepository.update(
|
||||||
);
|
{
|
||||||
|
id: messageChannel.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
syncCursor: historyId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
await this.messagingChannelSyncStatusService.scheduleMessagesImport(
|
||||||
messageChannel.id,
|
messageChannel.id,
|
||||||
workspaceId,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { Any, IsNull } from 'typeorm';
|
||||||
|
|
||||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
|
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||||
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { CreateCompanyAndContactService } from 'src/modules/contact-creation-manager/services/create-company-and-contact.service';
|
import { CreateCompanyAndContactService } from 'src/modules/contact-creation-manager/services/create-company-and-contact.service';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository';
|
|
||||||
import {
|
import {
|
||||||
MessageChannelContactAutoCreationPolicy,
|
MessageChannelContactAutoCreationPolicy,
|
||||||
MessageChannelWorkspaceEntity,
|
MessageChannelWorkspaceEntity,
|
||||||
@ -28,12 +29,9 @@ export class MessagingCreateCompanyAndContactAfterSyncJob {
|
|||||||
);
|
);
|
||||||
constructor(
|
constructor(
|
||||||
private readonly createCompanyAndContactService: CreateCompanyAndContactService,
|
private readonly createCompanyAndContactService: CreateCompanyAndContactService,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelService: MessageChannelRepository,
|
|
||||||
@InjectObjectMetadataRepository(MessageParticipantWorkspaceEntity)
|
|
||||||
private readonly messageParticipantRepository: MessageParticipantRepository,
|
|
||||||
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
|
private readonly twentyORMManager: TwentyORMManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(MessagingCreateCompanyAndContactAfterSyncJob.name)
|
@Process(MessagingCreateCompanyAndContactAfterSyncJob.name)
|
||||||
@ -45,12 +43,18 @@ export class MessagingCreateCompanyAndContactAfterSyncJob {
|
|||||||
);
|
);
|
||||||
const { workspaceId, messageChannelId } = data;
|
const { workspaceId, messageChannelId } = data;
|
||||||
|
|
||||||
const messageChannel = await this.messageChannelService.getByIds(
|
const messageChannelRepository =
|
||||||
[messageChannelId],
|
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||||
workspaceId,
|
'messageChannel',
|
||||||
);
|
);
|
||||||
|
|
||||||
const { contactAutoCreationPolicy, connectedAccountId } = messageChannel[0];
|
const messageChannel = await messageChannelRepository.findOneOrFail({
|
||||||
|
where: {
|
||||||
|
id: messageChannelId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { contactAutoCreationPolicy, connectedAccountId } = messageChannel;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
contactAutoCreationPolicy === MessageChannelContactAutoCreationPolicy.NONE
|
contactAutoCreationPolicy === MessageChannelContactAutoCreationPolicy.NONE
|
||||||
@ -69,17 +73,29 @@ export class MessagingCreateCompanyAndContactAfterSyncJob {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const contactsToCreate =
|
const messageParticipantRepository =
|
||||||
|
await this.twentyORMManager.getRepository<MessageParticipantWorkspaceEntity>(
|
||||||
|
'messageParticipant',
|
||||||
|
);
|
||||||
|
|
||||||
|
const directionFilter =
|
||||||
contactAutoCreationPolicy ===
|
contactAutoCreationPolicy ===
|
||||||
MessageChannelContactAutoCreationPolicy.SENT_AND_RECEIVED
|
MessageChannelContactAutoCreationPolicy.SENT_AND_RECEIVED
|
||||||
? await this.messageParticipantRepository.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberId(
|
? Any(['incoming', 'outgoing'])
|
||||||
|
: 'outgoing';
|
||||||
|
|
||||||
|
const contactsToCreate = await messageParticipantRepository.find({
|
||||||
|
where: {
|
||||||
|
message: {
|
||||||
|
messageChannelMessageAssociations: {
|
||||||
messageChannelId,
|
messageChannelId,
|
||||||
workspaceId,
|
},
|
||||||
)
|
direction: directionFilter,
|
||||||
: await this.messageParticipantRepository.getByMessageChannelIdWithoutPersonIdAndWorkspaceMemberIdAndMessageOutgoing(
|
},
|
||||||
messageChannelId,
|
personId: IsNull(),
|
||||||
workspaceId,
|
workspaceMemberId: IsNull(),
|
||||||
);
|
},
|
||||||
|
});
|
||||||
|
|
||||||
await this.createCompanyAndContactService.createCompaniesAndContactsAndUpdateParticipants(
|
await this.createCompanyAndContactService.createCompaniesAndContactsAndUpdateParticipants(
|
||||||
connectedAccount,
|
connectedAccount,
|
||||||
|
|||||||
@ -11,8 +11,7 @@ import {
|
|||||||
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
|
||||||
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
|
||||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||||
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
|
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
import { MessagingTelemetryService } from 'src/modules/messaging/monitoring/services/messaging-telemetry.service';
|
import { MessagingTelemetryService } from 'src/modules/messaging/monitoring/services/messaging-telemetry.service';
|
||||||
|
|
||||||
@ -25,9 +24,8 @@ export class MessagingMessageChannelSyncStatusMonitoringCronJob {
|
|||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(Workspace, 'core')
|
@InjectRepository(Workspace, 'core')
|
||||||
private readonly workspaceRepository: Repository<Workspace>,
|
private readonly workspaceRepository: Repository<Workspace>,
|
||||||
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
|
|
||||||
private readonly messageChannelRepository: MessageChannelRepository,
|
|
||||||
private readonly messagingTelemetryService: MessagingTelemetryService,
|
private readonly messagingTelemetryService: MessagingTelemetryService,
|
||||||
|
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Process(MessagingMessageChannelSyncStatusMonitoringCronJob.name)
|
@Process(MessagingMessageChannelSyncStatusMonitoringCronJob.name)
|
||||||
@ -46,9 +44,14 @@ export class MessagingMessageChannelSyncStatusMonitoringCronJob {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for (const activeWorkspace of activeWorkspaces) {
|
for (const activeWorkspace of activeWorkspaces) {
|
||||||
const messageChannels = await this.messageChannelRepository.getAll(
|
const messageChannelRepository =
|
||||||
activeWorkspace.id,
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>(
|
||||||
);
|
'messageChannel',
|
||||||
|
activeWorkspace.id,
|
||||||
|
);
|
||||||
|
const messageChannels = await messageChannelRepository.find({
|
||||||
|
select: ['id', 'syncStatus', 'connectedAccountId'],
|
||||||
|
});
|
||||||
|
|
||||||
for (const messageChannel of messageChannels) {
|
for (const messageChannel of messageChannels) {
|
||||||
if (!messageChannel.syncStatus) {
|
if (!messageChannel.syncStatus) {
|
||||||
|
|||||||
Reference in New Issue
Block a user