Refactor calendar to use new sync statuses and stages (#6141)

- Refactor calendar modules and some messaging modules to better
organize them by business rules and decouple them
- Work toward a common architecture for the different calendar providers
by introducing interfaces for the drivers
- Modify cron job to use the new sync statuses and stages
This commit is contained in:
bosiraphael
2024-07-08 17:01:06 +02:00
committed by GitHub
parent 1c3ea9b106
commit f458322303
69 changed files with 1300 additions and 884 deletions

View File

@ -6,14 +6,12 @@ import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.mod
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 { AddPersonIdAndWorkspaceMemberIdModule } from 'src/modules/calendar-messaging-participant/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.module';
import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant-manager/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service';
import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service';
import { MessagingErrorHandlingService } from 'src/modules/messaging/common/services/messaging-error-handling.service';
import { MessagingFetchByBatchesService } from 'src/modules/messaging/common/services/messaging-fetch-by-batch.service';
import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service';
import { MessagingMessageThreadService } from 'src/modules/messaging/common/services/messaging-message-thread.service';
import { MessagingMessageService } from 'src/modules/messaging/common/services/messaging-message.service';
import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service';
import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.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';
@ -34,26 +32,22 @@ import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/perso
MessageThreadWorkspaceEntity,
]),
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
AddPersonIdAndWorkspaceMemberIdModule,
],
providers: [
MessagingMessageService,
MessagingMessageThreadService,
MessagingSaveMessagesAndEnqueueContactCreationService,
MessagingErrorHandlingService,
MessagingTelemetryService,
MessagingChannelSyncStatusService,
MessagingMessageParticipantService,
MessagingFetchByBatchesService,
AddPersonIdAndWorkspaceMemberIdService,
],
exports: [
MessagingMessageService,
MessagingMessageThreadService,
MessagingSaveMessagesAndEnqueueContactCreationService,
MessagingErrorHandlingService,
MessagingTelemetryService,
MessagingChannelSyncStatusService,
MessagingMessageParticipantService,
MessagingFetchByBatchesService,
],
})

View File

@ -61,8 +61,6 @@ export class MessagingChannelSyncStatusService {
`messages-to-import:${workspaceId}:gmail:${messageChannelId}`,
);
// TODO: remove nextPageToken from cache
await this.messageChannelRepository.resetSyncCursor(
messageChannelId,
workspaceId,

View File

@ -5,6 +5,7 @@ import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module';
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
import { EmailAliasManagerModule } from 'src/modules/connected-account/email-alias-manager/email-alias-manager.module';
import { OAuth2ClientManagerModule } from 'src/modules/connected-account/oauth2-client-manager/oauth2-client-manager.module';
import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module';
@ -20,6 +21,8 @@ import { MessagingGmailFullMessageListFetchService } from 'src/modules/messaging
import { MessagingGmailHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service';
import { MessagingGmailMessagesImportService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service';
import { MessagingGmailPartialMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service';
import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-save-messages-and-enqueue-contact-creation.service';
import { MessageParticipantManagerModule } from 'src/modules/messaging/message-participant-manager/message-participant-manager.module';
@Module({
imports: [
@ -36,6 +39,8 @@ import { MessagingGmailPartialMessageListFetchService } from 'src/modules/messag
OAuth2ClientManagerModule,
EmailAliasManagerModule,
FeatureFlagModule,
WorkspaceDataSourceModule,
MessageParticipantManagerModule,
],
providers: [
MessagingGmailClientProvider,
@ -45,6 +50,7 @@ import { MessagingGmailPartialMessageListFetchService } from 'src/modules/messag
MessagingGmailFullMessageListFetchService,
MessagingGmailMessagesImportService,
MessagingGmailFetchMessageIdsToExcludeService,
MessagingSaveMessagesAndEnqueueContactCreationService,
],
exports: [
MessagingGmailClientProvider,

View File

@ -12,7 +12,10 @@ export class MessagingGmailClientProvider {
) {}
public async getGmailClient(
connectedAccount: ConnectedAccountWorkspaceEntity,
connectedAccount: Pick<
ConnectedAccountWorkspaceEntity,
'provider' | 'refreshToken'
>,
): Promise<gmail_v1.Gmail> {
const oAuth2Client =
await this.oAuth2ClientManagerService.getOAuth2Client(connectedAccount);

View File

@ -15,7 +15,6 @@ import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/s
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 { MessagingErrorHandlingService } from 'src/modules/messaging/common/services/messaging-error-handling.service';
import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service';
import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service';
import {
MessageChannelSyncStage,
@ -23,6 +22,7 @@ import {
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant';
import { MessagingGmailFetchMessagesByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service';
import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-save-messages-and-enqueue-contact-creation.service';
import { filterEmails } from 'src/modules/messaging/message-import-manager/utils/filter-emails.util';
@Injectable()

View File

@ -14,7 +14,6 @@ import {
CreateCompanyAndContactJobData,
} from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/create-company-and-contact.job';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service';
import { MessagingMessageService } from 'src/modules/messaging/common/services/messaging-message.service';
import {
MessageChannelContactAutoCreationPolicy,
@ -26,6 +25,7 @@ import {
Participant,
ParticipantWithMessageId,
} from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message';
import { MessagingMessageParticipantService } from 'src/modules/messaging/message-participant-manager/services/messaging-message-participant.service';
import { isGroupEmail } from 'src/utils/is-group-email';
import { isWorkEmail } from 'src/utils/is-work-email';

View File

@ -1,25 +0,0 @@
import { MESSAGING_THROTTLE_DURATION } from 'src/modules/messaging/common/constants/messaging-throttle-duration';
export const isThrottled = (
syncStageStartedAt: string | null,
throttleFailureCount: number,
): boolean => {
if (!syncStageStartedAt) {
return false;
}
return (
computeThrottlePauseUntil(syncStageStartedAt, throttleFailureCount) >
new Date()
);
};
const computeThrottlePauseUntil = (
syncStageStartedAt: string,
throttleFailureCount: number,
): Date => {
return new Date(
new Date(syncStageStartedAt).getTime() +
MESSAGING_THROTTLE_DURATION * Math.pow(2, throttleFailureCount - 1),
);
};

View File

@ -14,7 +14,7 @@ import {
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { MessagingGmailFullMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service';
import { MessagingGmailPartialMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service';
import { isThrottled } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-throttled';
import { isThrottled } from 'src/modules/connected-account/utils/is-throttled';
export type MessagingMessageListFetchJobData = {
messageChannelId: string;

View File

@ -13,7 +13,7 @@ import {
MessageChannelWorkspaceEntity,
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { MessagingGmailMessagesImportService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service';
import { isThrottled } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/is-throttled';
import { isThrottled } from 'src/modules/connected-account/utils/is-throttled';
export type MessagingMessagesImportJobData = {
messageChannelId: string;

View File

@ -21,9 +21,11 @@ import { MessagingMessagesImportJob } from 'src/modules/messaging/message-import
import { MessagingOngoingStaleJob } from 'src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job';
import { MessagingMessageImportManagerMessageChannelListener } from 'src/modules/messaging/message-import-manager/listeners/messaging-import-manager-message-channel.listener';
import { BillingModule } from 'src/engine/core-modules/billing/billing.module';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
@Module({
imports: [
WorkspaceDataSourceModule,
MessagingGmailDriverModule,
MessagingCommonModule,
TypeOrmModule.forFeature([Workspace], 'core'),

View File

@ -1,4 +1,4 @@
import { isEmailBlocklisted } from 'src/modules/calendar-messaging-participant/utils/is-email-blocklisted.util';
import { isEmailBlocklisted } from 'src/modules/calendar-messaging-participant-manager/utils/is-email-blocklisted.util';
import { GmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message';
// Todo: refactor this into several utils

View File

@ -0,0 +1,35 @@
import { Scope } from '@nestjs/common';
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessagingMessageParticipantService } from 'src/modules/messaging/message-participant-manager/services/messaging-message-participant.service';
export type MessageParticipantMatchParticipantJobData = {
workspaceId: string;
email: string;
personId?: string;
workspaceMemberId?: string;
};
@Processor({
queueName: MessageQueue.messagingQueue,
scope: Scope.REQUEST,
})
export class MessageParticipantMatchParticipantJob {
constructor(
private readonly messageParticipantService: MessagingMessageParticipantService,
) {}
@Process(MessageParticipantMatchParticipantJob.name)
async handle(data: MessageParticipantMatchParticipantJobData): Promise<void> {
const { workspaceId, email, personId, workspaceMemberId } = data;
await this.messageParticipantService.matchMessageParticipants(
workspaceId,
email,
personId,
workspaceMemberId,
);
}
}

View File

@ -0,0 +1,37 @@
import { Scope } from '@nestjs/common';
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessagingMessageParticipantService } from 'src/modules/messaging/message-participant-manager/services/messaging-message-participant.service';
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
export type MessageParticipantUnmatchParticipantJobData = {
workspaceId: string;
email: string;
personId?: string;
workspaceMemberId?: string;
};
@Processor({
queueName: MessageQueue.messagingQueue,
scope: Scope.REQUEST,
})
export class MessageParticipantUnmatchParticipantJob {
constructor(
private readonly messageParticipantService: MessagingMessageParticipantService,
) {}
@Process(MessageParticipantUnmatchParticipantJob.name)
async handle(
data: MessageParticipantUnmatchParticipantJobData,
): Promise<void> {
const { workspaceId, email, personId, workspaceMemberId } = data;
await this.messageParticipantService.unmatchMessageParticipants(
workspaceId,
email,
personId,
workspaceMemberId,
);
}
}

View File

@ -0,0 +1,74 @@
import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event';
import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event';
import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util';
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
import {
MessageParticipantMatchParticipantJobData,
MessageParticipantMatchParticipantJob,
} from 'src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job';
import {
MessageParticipantUnmatchParticipantJobData,
MessageParticipantUnmatchParticipantJob,
} from 'src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
@Injectable()
export class MessageParticipantPersonListener {
constructor(
@InjectMessageQueue(MessageQueue.messagingQueue)
private readonly messageQueueService: MessageQueueService,
) {}
@OnEvent('person.created')
async handleCreatedEvent(
payload: ObjectRecordCreateEvent<PersonWorkspaceEntity>,
) {
if (payload.properties.after.email === null) {
return;
}
await this.messageQueueService.add<MessageParticipantMatchParticipantJobData>(
MessageParticipantMatchParticipantJob.name,
{
workspaceId: payload.workspaceId,
email: payload.properties.after.email,
personId: payload.recordId,
},
);
}
@OnEvent('person.updated')
async handleUpdatedEvent(
payload: ObjectRecordUpdateEvent<PersonWorkspaceEntity>,
) {
if (
objectRecordUpdateEventChangedProperties(
payload.properties.before,
payload.properties.after,
).includes('email')
) {
await this.messageQueueService.add<MessageParticipantUnmatchParticipantJobData>(
MessageParticipantUnmatchParticipantJob.name,
{
workspaceId: payload.workspaceId,
email: payload.properties.before.email,
personId: payload.recordId,
},
);
await this.messageQueueService.add<MessageParticipantMatchParticipantJobData>(
MessageParticipantMatchParticipantJob.name,
{
workspaceId: payload.workspaceId,
email: payload.properties.after.email,
personId: payload.recordId,
},
);
}
}
}

View File

@ -0,0 +1,74 @@
import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event';
import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event';
import { objectRecordChangedProperties as objectRecordUpdateEventChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util';
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
import {
MessageParticipantMatchParticipantJobData,
MessageParticipantMatchParticipantJob,
} from 'src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job';
import {
MessageParticipantUnmatchParticipantJobData,
MessageParticipantUnmatchParticipantJob,
} from 'src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@Injectable()
export class MessageParticipantWorkspaceMemberListener {
constructor(
@InjectMessageQueue(MessageQueue.messagingQueue)
private readonly messageQueueService: MessageQueueService,
) {}
@OnEvent('workspaceMember.created')
async handleCreatedEvent(
payload: ObjectRecordCreateEvent<WorkspaceMemberWorkspaceEntity>,
) {
if (payload.properties.after.userEmail === null) {
return;
}
await this.messageQueueService.add<MessageParticipantMatchParticipantJobData>(
MessageParticipantMatchParticipantJob.name,
{
workspaceId: payload.workspaceId,
email: payload.properties.after.userEmail,
workspaceMemberId: payload.properties.after.id,
},
);
}
@OnEvent('workspaceMember.updated')
async handleUpdatedEvent(
payload: ObjectRecordUpdateEvent<WorkspaceMemberWorkspaceEntity>,
) {
if (
objectRecordUpdateEventChangedProperties<WorkspaceMemberWorkspaceEntity>(
payload.properties.before,
payload.properties.after,
).includes('userEmail')
) {
await this.messageQueueService.add<MessageParticipantUnmatchParticipantJobData>(
MessageParticipantUnmatchParticipantJob.name,
{
workspaceId: payload.workspaceId,
email: payload.properties.before.userEmail,
personId: payload.recordId,
},
);
await this.messageQueueService.add<MessageParticipantMatchParticipantJobData>(
MessageParticipantMatchParticipantJob.name,
{
workspaceId: payload.workspaceId,
email: payload.properties.after.userEmail,
workspaceMemberId: payload.recordId,
},
);
}
}
}

View File

@ -7,19 +7,23 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant-manager/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service';
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { AutoCompaniesAndContactsCreationModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module';
import { MessagingGmailDriverModule } from 'src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module';
import { CalendarCreateCompanyAndContactAfterSyncJob } from 'src/modules/messaging/message-participants-manager/jobs/calendar-create-company-and-contact-after-sync.job';
import { MessagingCreateCompanyAndContactAfterSyncJob } from 'src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job';
import { MessageParticipantListener } from 'src/modules/messaging/message-participants-manager/listeners/message-participant.listener';
import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module';
import { MessageParticipantMatchParticipantJob } from 'src/modules/messaging/message-participant-manager/jobs/message-participant-match-participant.job';
import { MessageParticipantUnmatchParticipantJob } from 'src/modules/messaging/message-participant-manager/jobs/message-participant-unmatch-participant.job';
import { MessagingCreateCompanyAndContactAfterSyncJob } from 'src/modules/messaging/message-participant-manager/jobs/messaging-create-company-and-contact-after-sync.job';
import { MessageParticipantPersonListener } from 'src/modules/messaging/message-participant-manager/listeners/message-participant-person.listener';
import { MessageParticipantWorkspaceMemberListener } from 'src/modules/messaging/message-participant-manager/listeners/message-participant-workspace-member.listener';
import { MessageParticipantListener } from 'src/modules/messaging/message-participant-manager/listeners/message-participant.listener';
import { MessagingMessageParticipantService } from 'src/modules/messaging/message-participant-manager/services/messaging-message-participant.service';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
@Module({
imports: [
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
AnalyticsModule,
MessagingGmailDriverModule,
AutoCompaniesAndContactsCreationModule,
WorkspaceDataSourceModule,
ObjectMetadataRepositoryModule.forFeature([
@ -27,11 +31,18 @@ import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-o
]),
TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'),
TwentyORMModule.forFeature([CalendarChannelWorkspaceEntity]),
MessagingCommonModule,
],
providers: [
MessagingMessageParticipantService,
MessageParticipantMatchParticipantJob,
MessageParticipantUnmatchParticipantJob,
MessagingCreateCompanyAndContactAfterSyncJob,
CalendarCreateCompanyAndContactAfterSyncJob,
MessageParticipantListener,
MessageParticipantPersonListener,
MessageParticipantWorkspaceMemberListener,
AddPersonIdAndWorkspaceMemberIdService,
],
exports: [MessagingMessageParticipantService],
})
export class MessaginParticipantsManagerModule {}
export class MessageParticipantManagerModule {}

View File

@ -8,13 +8,11 @@ import { PersonRepository } from 'src/modules/person/repositories/person.reposit
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/calendar/calendar-event-import-manager/utils/get-flattened-values-and-values-string-for-batch-raw-query.util';
import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service';
import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant-manager/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service';
import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository';
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
import { ParticipantWithMessageId } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message';
// Todo: this is not the right place for this file. The code needs to be refactored in term of business modules with a precise scope.
// Putting it here to avoid circular dependencies for now.
@Injectable()
export class MessagingMessageParticipantService {
constructor(

View File

@ -1,99 +0,0 @@
import { Logger, Scope } from '@nestjs/common';
import { IsNull } from 'typeorm';
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service';
import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
export type CalendarCreateCompanyAndContactAfterSyncJobData = {
workspaceId: string;
calendarChannelId: string;
};
@Processor({
queueName: MessageQueue.calendarQueue,
scope: Scope.REQUEST,
})
export class CalendarCreateCompanyAndContactAfterSyncJob {
private readonly logger = new Logger(
CalendarCreateCompanyAndContactAfterSyncJob.name,
);
constructor(
private readonly createCompanyAndContactService: CreateCompanyAndContactService,
@InjectWorkspaceRepository(CalendarChannelWorkspaceEntity)
private readonly calendarChannelRepository: WorkspaceRepository<CalendarChannelWorkspaceEntity>,
@InjectWorkspaceRepository(CalendarEventParticipantWorkspaceEntity)
private readonly calendarEventParticipantRepository: WorkspaceRepository<CalendarEventParticipantWorkspaceEntity>,
) {}
@Process(CalendarCreateCompanyAndContactAfterSyncJob.name)
async handle(
data: CalendarCreateCompanyAndContactAfterSyncJobData,
): Promise<void> {
this.logger.log(
`create contacts and companies after sync for workspace ${data.workspaceId} and calendarChannel ${data.calendarChannelId}`,
);
const { workspaceId, calendarChannelId } = data;
const calendarChannel = await this.calendarChannelRepository.findOne({
where: {
id: calendarChannelId,
},
relations: ['connectedAccount.accountOwner'],
});
if (!calendarChannel) {
throw new Error(
`Calendar channel with id ${calendarChannelId} not found in workspace ${workspaceId}`,
);
}
const { handle, isContactAutoCreationEnabled, connectedAccount } =
calendarChannel;
if (!isContactAutoCreationEnabled || !handle) {
return;
}
if (!connectedAccount) {
throw new Error(
`Connected account not found in workspace ${workspaceId}`,
);
}
const calendarEventParticipantsWithoutPersonIdAndWorkspaceMemberId =
await this.calendarEventParticipantRepository.find({
where: {
calendarEvent: {
calendarChannelEventAssociations: {
calendarChannelId,
},
calendarEventParticipants: {
person: IsNull(),
workspaceMember: IsNull(),
},
},
},
relations: [
'calendarEvent.calendarChannelEventAssociations',
'calendarEvent.calendarEventParticipants',
],
});
await this.createCompanyAndContactService.createCompaniesAndContactsAndUpdateParticipants(
connectedAccount,
calendarEventParticipantsWithoutPersonIdAndWorkspaceMemberId,
workspaceId,
);
this.logger.log(
`create contacts and companies after sync for workspace ${data.workspaceId} and calendarChannel ${data.calendarChannelId} done`,
);
}
}

View File

@ -3,14 +3,14 @@ import { Module } from '@nestjs/common';
import { MessagingBlocklistManagerModule } from 'src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module';
import { MessagingMessageCleanerModule } from 'src/modules/messaging/message-cleaner/messaging-message-cleaner.module';
import { MessagingImportManagerModule } from 'src/modules/messaging/message-import-manager/messaging-import-manager.module';
import { MessaginParticipantsManagerModule } from 'src/modules/messaging/message-participants-manager/messaging-participants-manager.module';
import { MessageParticipantManagerModule } from 'src/modules/messaging/message-participant-manager/message-participant-manager.module';
import { MessagingMonitoringModule } from 'src/modules/messaging/monitoring/messaging-monitoring.module';
@Module({
imports: [
MessagingImportManagerModule,
MessagingMessageCleanerModule,
MessaginParticipantsManagerModule,
MessageParticipantManagerModule,
MessagingBlocklistManagerModule,
MessagingMonitoringModule,
],