From 3173ee016afc2fe4c20b7fc1d350f03a847c6129 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 3 Jun 2024 11:16:05 +0200 Subject: [PATCH] Rework messaging modules (#5710) In this PR, I'm refactoring the messaging module into smaller pieces that have **ONE** responsibility: import messages, clean messages, handle message participant creation, instead of having ~30 modules (1 per service, jobs, cron, ...). This is mandatory to start introducing drivers (gmails, office365, ...) IMO. It is too difficult to enforce common interfaces as we have too many interfaces (30 modules...). All modules should not be exposed Right now, we have services that are almost functions: do-that-and-this.service.ts / do-that-and-this.module.ts I believe we should have something more organized at a high level and it does not matter that much if we have a bit of code duplicates. Note that the proposal is not fully implemented in the current PR that has only focused on messaging folder (biggest part) Here is the high level proposal: - connected-account: token-refresher - blocklist - messaging: message-importer, message-cleaner, message-participants, ... (right now I'm keeping a big messaging-common but this will disappear see below) - calendar: calendar-importer, calendar-cleaner, ... Consequences: 1) It's OK to re-implement several times some things. Example: - error handling in connected-account, messaging, and calendar instead of trying to unify. They are actually different error handling. The only things that might be in common is the GmailError => CommonError parsing and I'm not even sure it makes a lot of sense as these 3 apis might have different format actually - auto-creation. Calendar and Messaging could actually have different rules 2) **We should not have circular dependencies:** - I believe this was the reason why we had so many modules, to be able to cherry pick the one we wanted to avoid circular deps. This is not the right approach IMO, we need architect the whole messaging by defining high level blocks that won't have circular dependencies by design. If we encounter one, we should rethink and break the block in a way that makes sense. - ex: connected-account.resolver is not in the same module as token-refresher. ==> connected-account.resolver => message-importer (as we trigger full sync job when we connect an account) => token-refresher (as we refresh token on message import). connected-account.resolver and token-refresher both in connected-account folder but should be in different modules. Otherwise it's a circular dependency. It does not mean that we should create 1 module per service as it was done before In a nutshell: The code needs to be thought in term of reponsibilities and in a way that enforce high level interfaces (and avoid circular dependencies) Bonus: As you can see, this code is also removing a lot of code because of the removal of many .module.ts (also because I'm removing the sync scripts v2 feature flag end removing old code) Bonus: I have prefixed services name with Messaging to improve dev xp. GmailErrorHandler could be different between MessagingGmailErrorHandler and CalendarGmailErrorHandler for instance --- .../src/command/command.module.ts | 3 +- ...essage-channel-sync-status-enum.command.ts | 2 +- .../typeorm-seeds/core/feature-flags.ts | 5 - .../workspace/message-channels.ts | 2 +- .../workspace-pre-query-hook.config.ts | 4 +- .../workspace-pre-query-hook.module.ts | 2 +- .../engine/core-modules/auth/auth.module.ts | 2 +- .../auth/services/google-apis.service.ts | 20 +- .../feature-flag/feature-flag.entity.ts | 1 - .../integrations/message-queue/jobs.module.ts | 12 +- .../metadata-to-repository.mapping.ts | 12 +- .../commands/add-standard-id.command.ts | 2 - .../standard-objects/index.ts | 10 +- ...lendar-messaging-participant-job.module.ts | 4 +- .../jobs/match-participant.job.ts | 4 +- .../jobs/unmatch-participant.job.ts | 4 +- .../listeners/calendar-channel.listener.ts | 2 +- .../calendar-event-cleaner.service.ts | 2 +- ...-companies-and-contacts-creation.module.ts | 4 +- .../messaging-message-channel.listener.ts | 4 +- .../create-company-and-contact.service.ts | 10 +- .../google-api-refresh-access-token.module.ts | 4 +- ...google-api-refresh-access-token.service.ts | 32 +- .../connected-account.workspace-entity.ts | 2 +- ...ing-blocklist-item-delete-messages.job.ts} | 12 +- ...saging-blocklist-reimport-messages.job.ts} | 13 +- .../listeners/messaging-blocklist.listener.ts | 4 +- .../messaging-blocklist-manager.module.ts | 8 + .../common/messaging-common.module.ts | 60 +++ .../message-find-many.pre-query.hook.ts | 8 +- .../message-find-one.pre-query-hook.ts | 0 .../messaging-query-hook.module.ts | 8 +- ...-channel-message-association.repository.ts | 2 +- .../message-channel.repository.ts | 4 +- .../message-participant.repository.ts | 4 +- .../repositories/message-thread.repository.ts | 0 .../repositories/message.repository.ts | 2 +- .../messaging-channel-sync-status.service.ts} | 6 +- .../messaging-error-handling.service.ts} | 22 +- .../messaging-fetch-by-batch.service.ts} | 6 +- .../messaging-message-participant.service.ts} | 10 +- .../messaging-message-thread.service.ts} | 14 +- .../services/messaging-message.service.ts} | 26 +- ...s-and-enqueue-contact-creation.service.ts} | 20 +- .../services}/messaging-telemetry.service.ts | 0 ...el-message-association.workspace-entity.ts | 6 +- .../message-channel.workspace-entity.ts | 2 +- .../message-participant.workspace-entity.ts | 2 +- .../message-thread.workspace-entity.ts | 4 +- .../message.workspace-entity.ts | 6 +- .../constants/gmail-excluded-categories.ts | 1 - .../gmail-ongoing-sync-timeout.constant.ts | 1 - ...gmail-users-history-max-result.constant.ts | 1 - ...-users-messages-get-batch-size.constant.ts | 1 - ...users-messages-list-max-result.constant.ts | 1 - .../messaging-cron-commands.module.ts | 15 - .../jobs/gmail-messages-import.cron.job.ts | 117 ------ .../crons/jobs/messaging-cron-job.module.ts | 33 -- .../jobs/gmail-full-message-list-fetch.job.ts | 126 ------- .../gmail-partial-message-list-fetch.job.ts | 48 --- .../messaging/jobs/messaging-job.module.ts | 75 ---- ...connected-account-deletion-cleanup.job.ts} | 19 +- ...age-cleaner-connected-account.listener.ts} | 23 +- .../messaging-message-cleaner.module.ts | 27 ++ .../messaging-message-cleaner.service.ts} | 12 +- .../delete-using-pagination.util.spec.ts | 4 +- .../utils/delete-using-pagination.util.ts | 0 ...ng-import-ongoing-sync-timeout.constant.ts | 1 + ...saging-message-list-fetch.cron.command.ts} | 12 +- ...messaging-messages-import.cron.command.ts} | 8 +- .../messaging-message-list-fetch.cron.job.ts} | 57 +-- .../messaging-messages-import.cron.job.ts | 65 ++++ .../messaging-gmail-excluded-categories.ts | 5 + ...gmail-users-history-max-result.constant.ts | 1 + ...-users-messages-get-batch-size.constant.ts | 1 + ...users-messages-list-max-result.constant.ts | 1 + .../gmail/messaging-gmail-driver.module.ts | 53 +++ .../messaging-gmail-client.provider.ts} | 2 +- ...mail-fetch-messages-by-batches.service.ts} | 20 +- ...-fetch-messages-ids-to-exclude.service.ts} | 12 +- ...-gmail-full-message-list-fetch.service.ts} | 44 ++- .../messaging-gmail-history.service.ts} | 8 +- ...essaging-gmail-messages-import.service.ts} | 53 +-- ...ail-partial-message-list-fetch.service.ts} | 38 +- .../types/gmail-message-parsed-response.ts | 0 .../drivers/gmail}/types/gmail-message.ts | 0 .../drivers/gmail}/types/gmail-thread.ts | 0 ...mail-category-excude-search-filter.spec.ts | 2 +- .../compute-gmail-category-label-id.spec.ts | 2 +- ...ute-gmail-category-excude-search-filter.ts | 0 .../utils/compute-gmail-category-label-id.ts | 0 .../jobs/messaging-message-list-fetch.job.ts} | 32 +- .../jobs/messaging-messages-import.job.ts | 61 +++ .../messaging-import-manager.module.ts | 44 +++ .../types/batch-queries.ts | 0 .../types/message-or-thread-query.ts | 0 ...ddress-object-as-participants.util.spec.ts | 2 +- .../create-queries-from-message-ids.util.ts | 2 +- .../utils/filter-emails.util.ts | 2 +- ...mat-address-object-as-participants.util.ts | 2 +- ...eate-company-and-contact-after-sync.job.ts | 8 +- .../messaging-participants-manager.module.ts | 24 ++ .../src/modules/messaging/messaging.module.ts | 24 +- .../fetch-by-batch/fetch-by-batch.module.ts | 15 - .../fetch-messages-by-batches.module.ts | 11 - .../gmail-error-handling.module.ts | 12 - .../gmail-full-message-list-fetch.module.ts | 42 --- .../gmail-full-message-list-fetch.service.ts | 306 --------------- .../gmail-messages-import.module.ts | 44 --- .../gmail-messages-import.service.ts | 320 ---------------- ...gmail-partial-message-list-fetch.module.ts | 46 --- ...mail-partial-message-list-fetch.service.ts | 347 ------------------ .../message-channel-sync-status.module.ts | 14 - .../message-participant.module.ts | 22 -- .../message-thread/message-thread.module.ts | 20 - .../services/message/message.module.ts | 26 -- .../providers/messaging-providers.module.ts | 11 - .../telemetry/messaging-telemetry.module.ts | 11 - .../thread-cleaner/thread-cleaner.module.ts | 18 - .../person.workspace-entity.ts | 2 +- .../workspace-member.workspace-entity.ts | 2 +- 121 files changed, 691 insertions(+), 2066 deletions(-) rename packages/twenty-server/src/modules/{messaging => connected-account/auto-companies-and-contacts-creation}/listeners/messaging-message-channel.listener.ts (89%) rename packages/twenty-server/src/modules/messaging/{jobs/blocklist-item-delete-messages.job.ts => blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts} (85%) rename packages/twenty-server/src/modules/messaging/{jobs/blocklist-reimport-messages.job.ts => blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts} (82%) rename packages/twenty-server/src/modules/messaging/{ => blocklist-manager}/listeners/messaging-blocklist.listener.ts (92%) create mode 100644 packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts create mode 100644 packages/twenty-server/src/modules/messaging/common/messaging-common.module.ts rename packages/twenty-server/src/modules/messaging/{ => common}/query-hooks/message/message-find-many.pre-query.hook.ts (92%) rename packages/twenty-server/src/modules/messaging/{ => common}/query-hooks/message/message-find-one.pre-query-hook.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => common}/query-hooks/messaging-query-hook.module.ts (80%) rename packages/twenty-server/src/modules/messaging/{ => common}/repositories/message-channel-message-association.repository.ts (98%) rename packages/twenty-server/src/modules/messaging/{ => common}/repositories/message-channel.repository.ts (98%) rename packages/twenty-server/src/modules/messaging/{ => common}/repositories/message-participant.repository.ts (97%) rename packages/twenty-server/src/modules/messaging/{ => common}/repositories/message-thread.repository.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => common}/repositories/message.repository.ts (97%) rename packages/twenty-server/src/modules/messaging/{services/message-channel-sync-status/message-channel-sync-status.service.ts => common/services/messaging-channel-sync-status.service.ts} (95%) rename packages/twenty-server/src/modules/messaging/{services/gmail-error-handling/gmail-error-handling.service.ts => common/services/messaging-error-handling.service.ts} (84%) rename packages/twenty-server/src/modules/messaging/{services/fetch-by-batch/fetch-by-batch.service.ts => common/services/messaging-fetch-by-batch.service.ts} (93%) rename packages/twenty-server/src/modules/messaging/{services/message-participant/message-participant.service.ts => common/services/messaging-message-participant.service.ts} (93%) rename packages/twenty-server/src/modules/messaging/{services/message-thread/message-thread.service.ts => common/services/messaging-message-thread.service.ts} (79%) rename packages/twenty-server/src/modules/messaging/{services/message/message.service.ts => common/services/messaging-message.service.ts} (90%) rename packages/twenty-server/src/modules/messaging/{services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service.ts => common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts} (87%) rename packages/twenty-server/src/modules/messaging/{services/telemetry => common/services}/messaging-telemetry.service.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => common}/standard-objects/message-channel-message-association.workspace-entity.ts (94%) rename packages/twenty-server/src/modules/messaging/{ => common}/standard-objects/message-channel.workspace-entity.ts (98%) rename packages/twenty-server/src/modules/messaging/{ => common}/standard-objects/message-participant.workspace-entity.ts (97%) rename packages/twenty-server/src/modules/messaging/{ => common}/standard-objects/message-thread.workspace-entity.ts (91%) rename packages/twenty-server/src/modules/messaging/{ => common}/standard-objects/message.workspace-entity.ts (95%) delete mode 100644 packages/twenty-server/src/modules/messaging/constants/gmail-excluded-categories.ts delete mode 100644 packages/twenty-server/src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant.ts delete mode 100644 packages/twenty-server/src/modules/messaging/constants/gmail-users-history-max-result.constant.ts delete mode 100644 packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant.ts delete mode 100644 packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-list-max-result.constant.ts delete mode 100644 packages/twenty-server/src/modules/messaging/crons/commands/messaging-cron-commands.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/crons/jobs/gmail-messages-import.cron.job.ts delete mode 100644 packages/twenty-server/src/modules/messaging/crons/jobs/messaging-cron-job.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/jobs/gmail-full-message-list-fetch.job.ts delete mode 100644 packages/twenty-server/src/modules/messaging/jobs/gmail-partial-message-list-fetch.job.ts delete mode 100644 packages/twenty-server/src/modules/messaging/jobs/messaging-job.module.ts rename packages/twenty-server/src/modules/messaging/{jobs/delete-connected-account-associated-messaging-data.job.ts => message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts} (50%) rename packages/twenty-server/src/modules/messaging/{listeners/messaging-connected-account.listener.ts => message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts} (65%) create mode 100644 packages/twenty-server/src/modules/messaging/message-cleaner/messaging-message-cleaner.module.ts rename packages/twenty-server/src/modules/messaging/{services/thread-cleaner/thread-cleaner.service.ts => message-cleaner/services/messaging-message-cleaner.service.ts} (67%) rename packages/twenty-server/src/modules/messaging/{services/thread-cleaner/utils => message-cleaner/utils/__tests__}/delete-using-pagination.util.spec.ts (88%) rename packages/twenty-server/src/modules/messaging/{services/thread-cleaner => message-cleaner}/utils/delete-using-pagination.util.ts (100%) create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/constants/messaging-import-ongoing-sync-timeout.constant.ts rename packages/twenty-server/src/modules/messaging/{crons/commands/gmail-message-list-fetch.cron.command.ts => message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts} (61%) rename packages/twenty-server/src/modules/messaging/{crons/commands/gmail-messages-import.cron.command.ts => message-import-manager/crons/commands/messaging-messages-import.cron.command.ts} (70%) rename packages/twenty-server/src/modules/messaging/{crons/jobs/gmail-message-list-fetch.cron.job.ts => message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts} (63%) create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts rename packages/twenty-server/src/modules/messaging/{services/providers/gmail/gmail-client.provider.ts => message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider.ts} (96%) rename packages/twenty-server/src/modules/messaging/{services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts => message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service.ts} (90%) rename packages/twenty-server/src/modules/messaging/{services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service.ts => message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service.ts} (62%) rename packages/twenty-server/src/modules/messaging/{services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service.ts => message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts} (77%) rename packages/twenty-server/src/modules/messaging/{services/gmail-partial-message-list-fetch/gmail-get-history.service.ts => message-import-manager/drivers/gmail/services/messaging-gmail-history.service.ts} (87%) rename packages/twenty-server/src/modules/messaging/{services/gmail-messages-import/gmail-messages-import-v2.service.ts => message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts} (71%) rename packages/twenty-server/src/modules/messaging/{services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service.ts => message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts} (70%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager/drivers/gmail}/types/gmail-message-parsed-response.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager/drivers/gmail}/types/gmail-message.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager/drivers/gmail}/types/gmail-thread.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager/drivers/gmail}/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts (89%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager/drivers/gmail}/utils/__tests__/compute-gmail-category-label-id.spec.ts (78%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager/drivers/gmail}/utils/compute-gmail-category-excude-search-filter.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager/drivers/gmail}/utils/compute-gmail-category-label-id.ts (100%) rename packages/twenty-server/src/modules/messaging/{jobs/gmail-message-list-fetch.job.ts => message-import-manager/jobs/messaging-message-list-fetch.job.ts} (77%) create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts create mode 100644 packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts rename packages/twenty-server/src/modules/messaging/{ => message-import-manager}/types/batch-queries.ts (100%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager}/types/message-or-thread-query.ts (100%) rename packages/twenty-server/src/modules/messaging/{services => message-import-manager}/utils/__tests__/format-address-object-as-participants.util.spec.ts (91%) rename packages/twenty-server/src/modules/messaging/{ => message-import-manager}/utils/create-queries-from-message-ids.util.ts (68%) rename packages/twenty-server/src/modules/messaging/{services => message-import-manager}/utils/filter-emails.util.ts (93%) rename packages/twenty-server/src/modules/messaging/{services => message-import-manager}/utils/format-address-object-as-participants.util.ts (90%) rename packages/twenty-server/src/modules/messaging/{ => message-participants-manager}/jobs/messaging-create-company-and-contact-after-sync.job.ts (93%) create mode 100644 packages/twenty-server/src/modules/messaging/message-participants-manager/messaging-participants-manager.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/message/message.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/providers/messaging-providers.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.module.ts delete mode 100644 packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.module.ts diff --git a/packages/twenty-server/src/command/command.module.ts b/packages/twenty-server/src/command/command.module.ts index fd7e9fd980f43..86c629f928983 100644 --- a/packages/twenty-server/src/command/command.module.ts +++ b/packages/twenty-server/src/command/command.module.ts @@ -7,7 +7,6 @@ import { CalendarCronCommandsModule } from 'src/modules/calendar/crons/commands/ import { AppModule } from 'src/app.module'; import { WorkspaceMigrationRunnerCommandsModule } from 'src/engine/workspace-manager/workspace-migration-runner/commands/workspace-sync-metadata-commands.module'; import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module'; -import { MessagingCronCommandsModule } from 'src/modules/messaging/crons/commands/messaging-cron-commands.module'; import { CalendarCommandsModule } from 'src/modules/calendar/commands/calendar-commands.module'; @Module({ @@ -15,7 +14,7 @@ import { CalendarCommandsModule } from 'src/modules/calendar/commands/calendar-c AppModule, WorkspaceSyncMetadataCommandsModule, DatabaseCommandModule, - MessagingCronCommandsModule, + // MessagingCronCommandsModule, CalendarCronCommandsModule, CalendarCommandsModule, WorkspaceCleanerModule, diff --git a/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts b/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts index 63e2405bd2a09..1a1e345ff232f 100644 --- a/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts +++ b/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts @@ -12,7 +12,7 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { MessageChannelSyncStatus } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelSyncStatus } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; interface UpdateMessageChannelSyncStatusEnumCommandOptions { workspaceId?: string; diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts index cb88f801f9dde..1266723b5c2f0 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts @@ -40,11 +40,6 @@ export const seedFeatureFlags = async ( workspaceId: workspaceId, value: true, }, - { - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - workspaceId: workspaceId, - value: true, - }, { key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled, workspaceId: workspaceId, diff --git a/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts b/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts index a44890197ff98..167061d11e1c6 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts @@ -1,7 +1,7 @@ import { EntityManager } from 'typeorm'; import { DEV_SEED_CONNECTED_ACCOUNT_IDS } from 'src/database/typeorm-seeds/workspace/connected-account'; -import { MessageChannelSyncSubStatus } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelSyncSubStatus } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; const tableName = 'messageChannel'; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts index b0bc2bc88f3bb..518e147241a1e 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts @@ -1,5 +1,3 @@ -import { MessageFindManyPreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook'; -import { MessageFindOnePreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type'; import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook'; import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook'; @@ -8,6 +6,8 @@ import { BlocklistUpdateManyPreQueryHook } from 'src/modules/connected-account/q import { BlocklistUpdateOnePreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook'; import { WorkspaceMemberDeleteOnePreQueryHook } from 'src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook'; import { WorkspaceMemberDeleteManyPreQueryHook } from 'src/modules/workspace-member/query-hooks/workspace-member-delete-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'; // TODO: move to a decorator export const workspacePreQueryHooks: WorkspaceQueryHook = { diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts index 7c367e7b2e3a3..8ea6b6a6e11b7 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; -import { MessagingQueryHookModule } from 'src/modules/messaging/query-hooks/messaging-query-hook.module'; import { WorkspacePreQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service'; import { CalendarQueryHookModule } from 'src/modules/calendar/query-hooks/calendar-query-hook.module'; import { ConnectedAccountQueryHookModule } from 'src/modules/connected-account/query-hooks/connected-account-query-hook.module'; +import { MessagingQueryHookModule } from 'src/modules/messaging/common/query-hooks/messaging-query-hook.module'; import { WorkspaceMemberQueryHookModule } from 'src/modules/workspace-member/query-hooks/workspace-member-query-hook.module'; @Module({ diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts index 9391fbacf9388..32973faabd36e 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts @@ -25,8 +25,8 @@ import { MicrosoftAuthController } from 'src/engine/core-modules/auth/controller import { AppTokenService } from 'src/engine/core-modules/app-token/services/app-token.service'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { AuthResolver } from './auth.resolver'; diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index 3dd53036e9746..bf6d6f6626283 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -1,11 +1,9 @@ import { Injectable, Inject } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository, EntityManager } from 'typeorm'; +import { EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; @@ -25,16 +23,16 @@ import { ConnectedAccountWorkspaceEntity, ConnectedAccountProvider, } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; import { MessageChannelWorkspaceEntity, MessageChannelType, MessageChannelVisibility, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { - GmailFullMessageListFetchJobData, - GmailFullMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; + MessagingMessageListFetchJob, + MessagingMessageListFetchJobData, +} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; @Injectable() export class GoogleAPIsService { @@ -46,8 +44,6 @@ export class GoogleAPIsService { @Inject(MessageQueue.calendarQueue) private readonly calendarQueueService: MessageQueueService, private readonly environmentService: EnvironmentService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) @@ -156,8 +152,8 @@ export class GoogleAPIsService { isCalendarEnabled: boolean, ) { if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) { - await this.messageQueueService.add( - GmailFullMessageListFetchJob.name, + await this.messageQueueService.add( + MessagingMessageListFetchJob.name, { workspaceId, connectedAccountId, diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts index 71e823ad1872a..954461abdc70a 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts @@ -21,7 +21,6 @@ export enum FeatureFlagKeys { IsAirtableIntegrationEnabled = 'IS_AIRTABLE_INTEGRATION_ENABLED', IsPostgreSQLIntegrationEnabled = 'IS_POSTGRESQL_INTEGRATION_ENABLED', IsStripeIntegrationEnabled = 'IS_STRIPE_INTEGRATION_ENABLED', - IsGmailSyncV2Enabled = 'IS_GMAIL_SYNC_V2_ENABLED', IsContactCreationForSentAndReceivedEmailsEnabled = 'IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED', } diff --git a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts b/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts index 6acee1a8b409e..e2223913e4437 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts +++ b/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts @@ -17,18 +17,14 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job'; import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module'; -import { GmailMessagesImportModule } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module'; -import { GmailFullMessageListFetchModule } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module'; -import { GmailPartialMessageListFetchModule } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module'; import { TimelineActivityModule } from 'src/modules/timeline/timeline-activity.module'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; import { CalendarMessagingParticipantJobModule } from 'src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module'; import { CalendarCronJobModule } from 'src/modules/calendar/crons/jobs/calendar-cron-job.module'; import { CalendarJobModule } from 'src/modules/calendar/jobs/calendar-job.module'; import { AutoCompaniesAndContactsCreationJobModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/auto-companies-and-contacts-creation-job.module'; -import { MessagingCronJobModule } from 'src/modules/messaging/crons/jobs/messaging-cron-job.module'; -import { MessagingJobModule } from 'src/modules/messaging/jobs/messaging-job.module'; import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module'; +import { MessagingModule } from 'src/modules/messaging/messaging.module'; @Module({ imports: [ @@ -41,9 +37,7 @@ import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module BillingModule, UserWorkspaceModule, WorkspaceModule, - GmailFullMessageListFetchModule, - GmailMessagesImportModule, - GmailPartialMessageListFetchModule, + MessagingModule, CalendarEventParticipantModule, TimelineActivityModule, StripeModule, @@ -53,8 +47,6 @@ import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module CalendarCronJobModule, CalendarJobModule, AutoCompaniesAndContactsCreationJobModule, - MessagingCronJobModule, - MessagingJobModule, TimelineJobModule, ], providers: [ diff --git a/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts b/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts index d51248fa140f1..17b4d0e8028c9 100644 --- a/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts +++ b/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts @@ -7,15 +7,15 @@ import { BlocklistRepository } from 'src/modules/connected-account/repositories/ import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { AuditLogRepository } from 'src/modules/timeline/repositiories/audit-log.repository'; import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { PersonRepository } from 'src/modules/person/repositories/person.repository'; import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; import { AttachmentRepository } from 'src/modules/attachment/repositories/attachment.repository'; import { CommentRepository } from 'src/modules/activity/repositories/comment.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 { PersonRepository } from 'src/modules/person/repositories/person.repository'; export const metadataToRepositoryMapping = { AuditLogWorkspaceEntity: AuditLogRepository, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts index e08c2cf154669..be810ced1e81e 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts @@ -58,7 +58,6 @@ export class AddStandardIdCommand extends CommandRunner { IS_AIRTABLE_INTEGRATION_ENABLED: true, IS_POSTGRESQL_INTEGRATION_ENABLED: true, IS_STRIPE_INTEGRATION_ENABLED: false, - IS_GMAIL_SYNC_V2_ENABLED: true, IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED: true, }, ); @@ -74,7 +73,6 @@ export class AddStandardIdCommand extends CommandRunner { IS_AIRTABLE_INTEGRATION_ENABLED: true, IS_POSTGRESQL_INTEGRATION_ENABLED: true, IS_STRIPE_INTEGRATION_ENABLED: false, - IS_GMAIL_SYNC_V2_ENABLED: true, IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED: true, }, ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts index bba9e1ac68c66..39ef93760e7ff 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts @@ -10,11 +10,6 @@ import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/co import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; @@ -27,6 +22,11 @@ import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/cale import { AuditLogWorkspaceEntity } from 'src/modules/timeline/standard-objects/audit-log.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; import { BehavioralEventWorkspaceEntity } from 'src/modules/timeline/standard-objects/behavioral-event.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 { 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'; export const standardObjectMetadataDefinitions = [ ActivityTargetWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts index 8328f4772581d..a2c338dace651 100644 --- a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts +++ b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts @@ -3,10 +3,10 @@ import { Module } from '@nestjs/common'; import { MatchParticipantJob } from 'src/modules/calendar-messaging-participant/jobs/match-participant.job'; import { UnmatchParticipantJob } from 'src/modules/calendar-messaging-participant/jobs/unmatch-participant.job'; import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module'; -import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; @Module({ - imports: [MessageParticipantModule, CalendarEventParticipantModule], + imports: [CalendarEventParticipantModule, MessagingCommonModule], providers: [ { provide: MatchParticipantJob.name, diff --git a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts index 109a25e563ecf..8f9015bfcd247 100644 --- a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts +++ b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; import { CalendarEventParticipantService } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; export type MatchParticipantJobData = { workspaceId: string; @@ -17,7 +17,7 @@ export class MatchParticipantJob implements MessageQueueJob { constructor( - private readonly messageParticipantService: MessageParticipantService, + private readonly messageParticipantService: MessagingMessageParticipantService, private readonly calendarEventParticipantService: CalendarEventParticipantService, ) {} diff --git a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts index 73b64fcfd2e34..11fee2cda22f1 100644 --- a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts +++ b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; import { CalendarEventParticipantService } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; export type UnmatchParticipantJobData = { workspaceId: string; @@ -17,7 +17,7 @@ export class UnmatchParticipantJob implements MessageQueueJob { constructor( - private readonly messageParticipantService: MessageParticipantService, + private readonly messageParticipantService: MessagingMessageParticipantService, private readonly calendarEventParticipantService: CalendarEventParticipantService, ) {} diff --git a/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts b/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts index 168aace114bab..3d1e28a557ab3 100644 --- a/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts +++ b/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts @@ -9,7 +9,7 @@ import { CalendarCreateCompanyAndContactAfterSyncJobData, CalendarCreateCompanyAndContactAfterSyncJob, } from 'src/modules/calendar/jobs/calendar-create-company-and-contact-after-sync.job'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() export class CalendarChannelListener { diff --git a/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts b/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts index fc8d111eca7a9..9f3f5d5202989 100644 --- a/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts +++ b/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { CalendarEventRepository } from 'src/modules/calendar/repositories/calendar-event.repository'; import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event.workspace-entity'; -import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util'; +import { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; @Injectable() export class CalendarEventCleanerService { diff --git a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts index 7b11161265e1b..5e6d0fa68a73b 100644 --- a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts @@ -7,11 +7,11 @@ import { CreateContactModule } from 'src/modules/connected-account/auto-companie import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; @Module({ imports: [ @@ -22,7 +22,7 @@ import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature- WorkspaceMemberWorkspaceEntity, CalendarEventParticipantWorkspaceEntity, ]), - MessageParticipantModule, + MessagingCommonModule, WorkspaceDataSourceModule, CalendarEventParticipantModule, TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), diff --git a/packages/twenty-server/src/modules/messaging/listeners/messaging-message-channel.listener.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/listeners/messaging-message-channel.listener.ts similarity index 89% rename from packages/twenty-server/src/modules/messaging/listeners/messaging-message-channel.listener.ts rename to packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/listeners/messaging-message-channel.listener.ts index 6f646f268014f..6b3cde3987beb 100644 --- a/packages/twenty-server/src/modules/messaging/listeners/messaging-message-channel.listener.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/listeners/messaging-message-channel.listener.ts @@ -5,11 +5,11 @@ import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/t import { objectRecordChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessagingCreateCompanyAndContactAfterSyncJobData, MessagingCreateCompanyAndContactAfterSyncJob, -} from 'src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +} from 'src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job'; @Injectable() export class MessagingMessageChannelListener { diff --git a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts index 981110b8349cb..fce9ef65b45de 100644 --- a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { EntityManager, Repository } from 'typeorm'; +import { EntityManager } from 'typeorm'; import compact from 'lodash.compact'; import { getDomainNameFromHandle } from 'src/modules/calendar-messaging-participant/utils/get-domain-name-from-handle.util'; @@ -16,11 +15,10 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta import { getUniqueContactsAndHandles } from 'src/modules/connected-account/auto-companies-and-contacts-creation/utils/get-unique-contacts-and-handles.util'; import { Contacts } from 'src/modules/connected-account/auto-companies-and-contacts-creation/types/contact.type'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; import { CalendarEventParticipantService } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service'; import { filterOutContactsFromCompanyOrWorkspace } from 'src/modules/connected-account/auto-companies-and-contacts-creation/utils/filter-out-contacts-from-company-or-workspace.util'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; @Injectable() export class CreateCompanyAndContactService { @@ -32,10 +30,8 @@ export class CreateCompanyAndContactService { @InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity) private readonly workspaceMemberRepository: WorkspaceMemberRepository, private readonly workspaceDataSourceService: WorkspaceDataSourceService, - private readonly messageParticipantService: MessageParticipantService, + private readonly messageParticipantService: MessagingMessageParticipantService, private readonly calendarEventParticipantService: CalendarEventParticipantService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, ) {} async createCompaniesAndPeople( diff --git a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts index 1e090d1f7364c..0c3180c09a778 100644 --- a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts +++ b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts @@ -3,14 +3,14 @@ import { Module } from '@nestjs/common'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; @Module({ imports: [ ObjectMetadataRepositoryModule.forFeature([ ConnectedAccountWorkspaceEntity, ]), - GmailErrorHandlingModule, + MessagingCommonModule, ], providers: [GoogleAPIRefreshAccessTokenService], exports: [GoogleAPIRefreshAccessTokenService], diff --git a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts index 02a9354715738..0bdfcefb0b0a9 100644 --- a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts +++ b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts @@ -6,9 +6,10 @@ import { EnvironmentService } from 'src/engine/integrations/environment/environm import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; 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 { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; @Injectable() export class GoogleAPIRefreshAccessTokenService { @@ -18,7 +19,8 @@ export class GoogleAPIRefreshAccessTokenService { private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, + private readonly messagingTelemetryService: MessagingTelemetryService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, ) {} async refreshAndSaveAccessToken( @@ -65,13 +67,21 @@ export class GoogleAPIRefreshAccessTokenService { ); } - await this.gmailErrorHandlingService.handleGmailError( - { - code: error.code, - reason: error.response.data.error, - }, - 'messages-import', - messageChannel, + await this.messagingTelemetryService.track({ + eventName: `refresh-token.error.insufficient_permissions`, + workspaceId, + connectedAccountId: messageChannel.connectedAccountId, + messageChannelId: messageChannel.id, + message: `${error.code}: ${error.reason}`, + }); + + await this.messagingChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushMessagesToImport( + messageChannel.id, + workspaceId, + ); + + await this.connectedAccountRepository.updateAuthFailedAt( + messageChannel.connectedAccountId, workspaceId, ); } diff --git a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts index ceef7b7a99b09..481f319703e36 100644 --- a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts +++ b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts @@ -8,7 +8,6 @@ import { import { CONNECTED_ACCOUNT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; @@ -17,6 +16,7 @@ import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/work import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; export enum ConnectedAccountProvider { GOOGLE = 'google', diff --git a/packages/twenty-server/src/modules/messaging/jobs/blocklist-item-delete-messages.job.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts similarity index 85% rename from packages/twenty-server/src/modules/messaging/jobs/blocklist-item-delete-messages.job.ts rename to packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts index b046056938c3a..ac2f6defaa975 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/blocklist-item-delete-messages.job.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts @@ -5,11 +5,11 @@ import { MessageQueueJob } from 'src/engine/integrations/message-queue/interface import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository'; import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.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 { 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'; export type BlocklistItemDeleteMessagesJobData = { workspaceId: string; @@ -31,7 +31,7 @@ export class BlocklistItemDeleteMessagesJob private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) private readonly blocklistRepository: BlocklistRepository, - private readonly threadCleanerService: ThreadCleanerService, + private readonly threadCleanerService: MessagingMessageCleanerService, ) {} async handle(data: BlocklistItemDeleteMessagesJobData): Promise { diff --git a/packages/twenty-server/src/modules/messaging/jobs/blocklist-reimport-messages.job.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts similarity index 82% rename from packages/twenty-server/src/modules/messaging/jobs/blocklist-reimport-messages.job.ts rename to packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts index 485a0a06b7f8f..12952b6ea3360 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/blocklist-reimport-messages.job.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts @@ -5,7 +5,6 @@ import { MessageQueueJob } from 'src/engine/integrations/message-queue/interface import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; 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 { GmailFullMessageListFetchService } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service'; export type BlocklistReimportMessagesJobData = { workspaceId: string; @@ -22,7 +21,6 @@ export class BlocklistReimportMessagesJob constructor( @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, - private readonly gmailFullMessageListFetchService: GmailFullMessageListFetchService, ) {} async handle(data: BlocklistReimportMessagesJobData): Promise { @@ -46,11 +44,12 @@ export class BlocklistReimportMessagesJob return; } - await this.gmailFullMessageListFetchService.fetchConnectedAccountThreads( - workspaceId, - connectedAccount[0].id, - [handle], - ); + // TODO: reimplement that + // await this.gmailMessageListFetchJob.fetchConnectedAccountThreads( + // workspaceId, + // connectedAccount[0].id, + // [handle], + // ); this.logger.log( `Reimporting messages from ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId} done`, diff --git a/packages/twenty-server/src/modules/messaging/listeners/messaging-blocklist.listener.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts similarity index 92% rename from packages/twenty-server/src/modules/messaging/listeners/messaging-blocklist.listener.ts rename to packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts index f612cdc3e1f49..8d2ff5e1f9407 100644 --- a/packages/twenty-server/src/modules/messaging/listeners/messaging-blocklist.listener.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts @@ -9,11 +9,11 @@ import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard import { BlocklistReimportMessagesJob, BlocklistReimportMessagesJobData, -} from 'src/modules/messaging/jobs/blocklist-reimport-messages.job'; +} from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job'; import { BlocklistItemDeleteMessagesJobData, BlocklistItemDeleteMessagesJob, -} from 'src/modules/messaging/jobs/blocklist-item-delete-messages.job'; +} from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job'; import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; @Injectable() diff --git a/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts new file mode 100644 index 0000000000000..0d59ad486348c --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; + +@Module({ + imports: [], + providers: [], + exports: [], +}) +export class MessagingBlocklistManagerModule {} diff --git a/packages/twenty-server/src/modules/messaging/common/messaging-common.module.ts b/packages/twenty-server/src/modules/messaging/common/messaging-common.module.ts new file mode 100644 index 0000000000000..f13575d948d3b --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/common/messaging-common.module.ts @@ -0,0 +1,60 @@ +import { HttpModule } from '@nestjs/axios'; +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module'; +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 { 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'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; + +@Module({ + imports: [ + HttpModule.register({ + baseURL: 'https://www.googleapis.com/batch/gmail/v1', + }), + AnalyticsModule, + WorkspaceDataSourceModule, + ObjectMetadataRepositoryModule.forFeature([ + PersonWorkspaceEntity, + MessageParticipantWorkspaceEntity, + MessageWorkspaceEntity, + MessageThreadWorkspaceEntity, + ]), + TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), + AddPersonIdAndWorkspaceMemberIdModule, + ], + providers: [ + MessagingMessageService, + MessagingMessageThreadService, + MessagingSaveMessagesAndEnqueueContactCreationService, + MessagingErrorHandlingService, + MessagingTelemetryService, + MessagingChannelSyncStatusService, + MessagingMessageParticipantService, + MessagingFetchByBatchesService, + ], + exports: [ + MessagingMessageService, + MessagingMessageThreadService, + MessagingSaveMessagesAndEnqueueContactCreationService, + MessagingErrorHandlingService, + MessagingTelemetryService, + MessagingChannelSyncStatusService, + MessagingMessageParticipantService, + MessagingFetchByBatchesService, + ], +}) +export class MessagingCommonModule {} diff --git a/packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts similarity index 92% rename from packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook.ts rename to packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts index bb83bda454f44..876a3630bcda0 100644 --- a/packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts @@ -10,15 +10,15 @@ import groupBy from 'lodash.groupby'; import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.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 { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook { diff --git a/packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook.ts rename to packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts diff --git a/packages/twenty-server/src/modules/messaging/query-hooks/messaging-query-hook.module.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts similarity index 80% rename from packages/twenty-server/src/modules/messaging/query-hooks/messaging-query-hook.module.ts rename to packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts index 7dfabdeb1c16d..2a80f5152e4f8 100644 --- a/packages/twenty-server/src/modules/messaging/query-hooks/messaging-query-hook.module.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { MessageFindManyPreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook'; -import { MessageFindOnePreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook'; 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 { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +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 { 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'; @Module({ imports: [ diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-channel-message-association.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts similarity index 98% rename from packages/twenty-server/src/modules/messaging/repositories/message-channel-message-association.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts index 35feb096893a3..fddbf24c6a386 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message-channel-message-association.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts @@ -3,8 +3,8 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; @Injectable() export class MessageChannelMessageAssociationRepository { diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-channel.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts similarity index 98% rename from packages/twenty-server/src/modules/messaging/repositories/message-channel.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts index 3eb6f9d76e826..0c86ba4de5120 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message-channel.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts @@ -3,12 +3,12 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; +import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageChannelWorkspaceEntity, MessageChannelSyncStatus, MessageChannelSyncSubStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() export class MessageChannelRepository { diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-participant.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts similarity index 97% rename from packages/twenty-server/src/modules/messaging/repositories/message-participant.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts index 4ae92c68abfaf..c92b19d8ecda2 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message-participant.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts @@ -3,9 +3,9 @@ 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/standard-objects/message-participant.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { ParticipantWithId } from 'src/modules/messaging/types/gmail-message'; +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 { diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-thread.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-thread.repository.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/repositories/message-thread.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-thread.repository.ts diff --git a/packages/twenty-server/src/modules/messaging/repositories/message.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts similarity index 97% rename from packages/twenty-server/src/modules/messaging/repositories/message.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts index 01e088ee7411b..ed75638c1f012 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts @@ -3,8 +3,8 @@ 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/standard-objects/message.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @Injectable() export class MessageRepository { diff --git a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-channel-sync-status.service.ts similarity index 95% rename from packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-channel-sync-status.service.ts index 522d71daec88f..1e1884576cb4d 100644 --- a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-channel-sync-status.service.ts @@ -4,15 +4,15 @@ import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache 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 { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; import { MessageChannelWorkspaceEntity, MessageChannelSyncSubStatus, MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() -export class MessageChannelSyncStatusService { +export class MessagingChannelSyncStatusService { constructor( @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts similarity index 84% rename from packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts index b0f96a8cd12c2..5073ade634489 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts @@ -6,9 +6,9 @@ import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repos import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; 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 { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; type SyncStep = | 'partial-message-list-fetch' @@ -21,11 +21,11 @@ export type GmailError = { }; @Injectable() -export class GmailErrorHandlingService { +export class MessagingErrorHandlingService { constructor( @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, private readonly messagingTelemetryService: MessagingTelemetryService, ) {} @@ -92,7 +92,7 @@ export class GmailErrorHandlingService { break; default: - await this.messageChannelSyncStatusService.markAsFailedUnknownAndFlushMessagesToImport( + await this.messagingChannelSyncStatusService.markAsFailedUnknownAndFlushMessagesToImport( messageChannel.id, workspaceId, ); @@ -116,21 +116,21 @@ export class GmailErrorHandlingService { switch (syncStep) { case 'full-message-list-fetch': - await this.messageChannelSyncStatusService.scheduleFullMessageListFetch( + await this.messagingChannelSyncStatusService.scheduleFullMessageListFetch( messageChannel.id, workspaceId, ); break; case 'partial-message-list-fetch': - await this.messageChannelSyncStatusService.schedulePartialMessageListFetch( + await this.messagingChannelSyncStatusService.schedulePartialMessageListFetch( messageChannel.id, workspaceId, ); break; case 'messages-import': - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); @@ -155,7 +155,7 @@ export class GmailErrorHandlingService { message: `${error.code}: ${error.reason}`, }); - await this.messageChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushMessagesToImport( + await this.messagingChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushMessagesToImport( messageChannel.id, workspaceId, ); @@ -184,7 +184,7 @@ export class GmailErrorHandlingService { message: `404: ${error.reason}`, }); - await this.messageChannelSyncStatusService.resetAndScheduleFullMessageListFetch( + await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch( messageChannel.id, workspaceId, ); diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-fetch-by-batch.service.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-fetch-by-batch.service.ts index 4d12b306b01d7..354ab92659f03 100644 --- a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-fetch-by-batch.service.ts @@ -3,11 +3,11 @@ import { Injectable } from '@nestjs/common'; import { AxiosResponse } from 'axios'; -import { BatchQueries } from 'src/modules/messaging/types/batch-queries'; -import { GmailMessageParsedResponse } from 'src/modules/messaging/types/gmail-message-parsed-response'; +import { GmailMessageParsedResponse } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message-parsed-response'; +import { BatchQueries } from 'src/modules/messaging/message-import-manager/types/batch-queries'; @Injectable() -export class FetchByBatchesService { +export class MessagingFetchByBatchesService { constructor(private readonly httpService: HttpService) {} async fetchAllByBatches( diff --git a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts index 9d23d7e09be32..c9538d444f973 100644 --- a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts @@ -3,18 +3,20 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { ParticipantWithMessageId } from 'src/modules/messaging/types/gmail-message'; import { PersonRepository } from 'src/modules/person/repositories/person.repository'; 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/utils/get-flattened-values-and-values-string-for-batch-raw-query.util'; -import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; 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 { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +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 MessageParticipantService { +export class MessagingMessageParticipantService { constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, @InjectObjectMetadataRepository(MessageParticipantWorkspaceEntity) diff --git a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-thread.service.ts similarity index 79% rename from packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-message-thread.service.ts index 4076dbdc6026f..35c5756385a34 100644 --- a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-thread.service.ts @@ -4,15 +4,15 @@ import { EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository'; +import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.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'; @Injectable() -export class MessageThreadService { +export class MessagingMessageThreadService { constructor( @InjectObjectMetadataRepository( MessageChannelMessageAssociationWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/messaging/services/message/message.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts similarity index 90% rename from packages/twenty-server/src/modules/messaging/services/message/message.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts index 219390b879df4..4b475d095d7da 100644 --- a/packages/twenty-server/src/modules/messaging/services/message/message.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts @@ -4,23 +4,23 @@ import { DataSource, EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { GmailMessage } from 'src/modules/messaging/types/gmail-message'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageThreadService } from 'src/modules/messaging/services/message-thread/message-thread.service'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.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 { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository'; +import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository'; +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 { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { GmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; +import { MessagingMessageThreadService } from 'src/modules/messaging/common/services/messaging-message-thread.service'; @Injectable() -export class MessageService { - private readonly logger = new Logger(MessageService.name); +export class MessagingMessageService { + private readonly logger = new Logger(MessagingMessageService.name); constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, @@ -34,7 +34,7 @@ export class MessageService { private readonly messageChannelRepository: MessageChannelRepository, @InjectObjectMetadataRepository(MessageThreadWorkspaceEntity) private readonly messageThreadRepository: MessageThreadRepository, - private readonly messageThreadService: MessageThreadService, + private readonly messageThreadService: MessagingMessageThreadService, ) {} public async saveMessagesWithinTransaction( diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts similarity index 87% rename from packages/twenty-server/src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts index 63c07ba1a3c2e..4e14d46a5dc21 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts @@ -8,13 +8,6 @@ import { MessageQueueService } from 'src/engine/integrations/message-queue/servi import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; -import { MessageService } from 'src/modules/messaging/services/message/message.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { - GmailMessage, - ParticipantWithMessageId, -} from 'src/modules/messaging/types/gmail-message'; import { CreateCompanyAndContactJobData, CreateCompanyAndContactJob, @@ -23,15 +16,22 @@ import { FeatureFlagEntity, FeatureFlagKeys, } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { + GmailMessage, + ParticipantWithMessageId, +} from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; +import { MessagingMessageService } from 'src/modules/messaging/common/services/messaging-message.service'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; @Injectable() -export class SaveMessagesAndEnqueueContactCreationService { +export class MessagingSaveMessagesAndEnqueueContactCreationService { constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, @Inject(MessageQueue.messagingQueue) private readonly messageQueueService: MessageQueueService, - private readonly messageService: MessageService, - private readonly messageParticipantService: MessageParticipantService, + private readonly messageService: MessagingMessageService, + private readonly messageParticipantService: MessagingMessageParticipantService, @InjectRepository(FeatureFlagEntity, 'core') private readonly featureFlagRepository: Repository, ) {} diff --git a/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-telemetry.service.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-telemetry.service.ts diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts similarity index 94% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts index 55ac9bb446527..91e9fa828209f 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts @@ -3,9 +3,6 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; @@ -14,6 +11,9 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.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'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageChannelMessageAssociation, diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts similarity index 98% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-channel.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts index f947498c73045..b457677a6b24b 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts @@ -8,7 +8,6 @@ import { import { MESSAGE_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; @@ -16,6 +15,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; export enum MessageChannelSyncStatus { // TO BE DEPRECATED diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts similarity index 97% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-participant.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts index 7b8264a34f2ba..b8c1e09f6447e 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts @@ -3,7 +3,6 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; @@ -14,6 +13,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageParticipant, diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts similarity index 91% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-thread.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts index ff38d03d4a24c..64b81723fb02d 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts @@ -6,14 +6,14 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { MESSAGE_THREAD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageThread, diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts similarity index 95% rename from packages/twenty-server/src/modules/messaging/standard-objects/message.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts index 03f5752b48c41..a3ad1ea48c8cc 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts @@ -7,9 +7,6 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { MESSAGE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; @@ -17,6 +14,9 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +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'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.message, diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-excluded-categories.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-excluded-categories.ts deleted file mode 100644 index 1f3dcf828ad9a..0000000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-excluded-categories.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_EXCLUDED_CATEGORIES = ['promotions', 'social', 'forums']; diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant.ts deleted file mode 100644 index c4c67700d9321..0000000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_ONGOING_SYNC_TIMEOUT = 1000 * 60 * 60; // 1 hour diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-users-history-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-users-history-max-result.constant.ts deleted file mode 100644 index d208d7d247e59..0000000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-users-history-max-result.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_USERS_HISTORY_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant.ts deleted file mode 100644 index b8ca7bb59c4ba..0000000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_USERS_MESSAGES_GET_BATCH_SIZE = 20; diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-list-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-list-max-result.constant.ts deleted file mode 100644 index 29b30121555e5..0000000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-list-max-result.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_USERS_MESSAGES_LIST_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/crons/commands/messaging-cron-commands.module.ts b/packages/twenty-server/src/modules/messaging/crons/commands/messaging-cron-commands.module.ts deleted file mode 100644 index 082aff092023c..0000000000000 --- a/packages/twenty-server/src/modules/messaging/crons/commands/messaging-cron-commands.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GmailMessagesImportCronCommand } from 'src/modules/messaging/crons/commands/gmail-messages-import.cron.command'; -import { GmailMessageListFetchCronCommand } from 'src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command'; -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - ]), - ], - providers: [GmailMessageListFetchCronCommand, GmailMessagesImportCronCommand], -}) -export class MessagingCronCommandsModule {} diff --git a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-messages-import.cron.job.ts b/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-messages-import.cron.job.ts deleted file mode 100644 index c34be9edf4044..0000000000000 --- a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-messages-import.cron.job.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository, In } from 'typeorm'; - -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; - -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { GmailMessagesImportService } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { GmailMessagesImportV2Service } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service'; -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; - -@Injectable() -export class GmailMessagesImportCronJob implements MessageQueueJob { - private readonly logger = new Logger(GmailMessagesImportCronJob.name); - - constructor( - @InjectRepository(Workspace, 'core') - private readonly workspaceRepository: Repository, - @InjectRepository(DataSourceEntity, 'metadata') - private readonly dataSourceRepository: Repository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - private readonly gmailFetchMessageContentFromCacheService: GmailMessagesImportService, - private readonly gmailFetchMessageContentFromCacheV2Service: GmailMessagesImportV2Service, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - private readonly environmentService: EnvironmentService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - private readonly messagingTelemetryService: MessagingTelemetryService, - ) {} - - async handle(): Promise { - const workspaceIds = ( - await this.workspaceRepository.find({ - where: this.environmentService.get('IS_BILLING_ENABLED') - ? { - subscriptionStatus: In(['active', 'trialing', 'past_due']), - } - : {}, - select: ['id'], - }) - ).map((workspace) => workspace.id); - - const dataSources = await this.dataSourceRepository.find({ - where: { - workspaceId: In(workspaceIds), - }, - }); - - const workspaceIdsWithDataSources = new Set( - dataSources.map((dataSource) => dataSource.workspaceId), - ); - - for (const workspaceId of workspaceIdsWithDataSources) { - await this.fetchWorkspaceMessages(workspaceId); - } - } - - private async fetchWorkspaceMessages(workspaceId: string): Promise { - const messageChannels = - await this.messageChannelRepository.getAll(workspaceId); - - const isGmailSyncV2EnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - value: true, - }); - - const isGmailSyncV2Enabled = isGmailSyncV2EnabledFeatureFlag?.value; - - for (const messageChannel of messageChannels) { - if (!messageChannel?.isSyncEnabled) { - continue; - } - - if (isGmailSyncV2Enabled) { - await this.messagingTelemetryService.track({ - eventName: 'messages_import.triggered', - workspaceId, - connectedAccountId: messageChannel.connectedAccountId, - messageChannelId: messageChannel.id, - }); - - const connectedAccount = - await this.connectedAccountRepository.getConnectedAccountOrThrow( - workspaceId, - messageChannel.connectedAccountId, - ); - - await this.gmailFetchMessageContentFromCacheV2Service.processMessageBatchImport( - messageChannel, - connectedAccount, - workspaceId, - ); - } else { - await this.gmailFetchMessageContentFromCacheService.fetchMessageContentFromCache( - workspaceId, - messageChannel.connectedAccountId, - ); - } - } - } -} diff --git a/packages/twenty-server/src/modules/messaging/crons/jobs/messaging-cron-job.module.ts b/packages/twenty-server/src/modules/messaging/crons/jobs/messaging-cron-job.module.ts deleted file mode 100644 index b54d9cb344303..0000000000000 --- a/packages/twenty-server/src/modules/messaging/crons/jobs/messaging-cron-job.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { GmailMessagesImportCronJob } from 'src/modules/messaging/crons/jobs/gmail-messages-import.cron.job'; -import { GmailMessageListFetchCronJob } from 'src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job'; -import { GmailMessagesImportModule } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; - -@Module({ - imports: [ - TypeOrmModule.forFeature([Workspace, FeatureFlagEntity], 'core'), - TypeOrmModule.forFeature([DataSourceEntity], 'metadata'), - ObjectMetadataRepositoryModule.forFeature([MessageChannelWorkspaceEntity]), - GmailMessagesImportModule, - MessagingTelemetryModule, - ], - providers: [ - { - provide: GmailMessagesImportCronJob.name, - useClass: GmailMessagesImportCronJob, - }, - { - provide: GmailMessageListFetchCronJob.name, - useClass: GmailMessageListFetchCronJob, - }, - ], -}) -export class MessagingCronJobModule {} diff --git a/packages/twenty-server/src/modules/messaging/jobs/gmail-full-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/jobs/gmail-full-message-list-fetch.job.ts deleted file mode 100644 index d4a82435bdc82..0000000000000 --- a/packages/twenty-server/src/modules/messaging/jobs/gmail-full-message-list-fetch.job.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; - -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; - -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; -import { GmailFullMessageListFetchService } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service'; -import { GmailFullMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -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 { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; - -export type GmailFullMessageListFetchJobData = { - workspaceId: string; - connectedAccountId: string; -}; - -@Injectable() -export class GmailFullMessageListFetchJob - implements MessageQueueJob -{ - private readonly logger = new Logger(GmailFullMessageListFetchJob.name); - - constructor( - private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService, - private readonly gmailFullMessageListFetchService: GmailFullMessageListFetchService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - private readonly gmailFullMessageListFetchV2Service: GmailFullMessageListFetchV2Service, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - private readonly messagingTelemetryService: MessagingTelemetryService, - ) {} - - async handle(data: GmailFullMessageListFetchJobData): Promise { - const { workspaceId, connectedAccountId } = data; - - this.logger.log( - `gmail full-sync for workspace ${workspaceId} and account ${connectedAccountId}`, - ); - - try { - await this.googleAPIsRefreshAccessTokenService.refreshAndSaveAccessToken( - workspaceId, - connectedAccountId, - ); - } catch (e) { - this.logger.error( - `Error refreshing access token for connected account ${connectedAccountId} in workspace ${workspaceId}`, - e, - ); - - return; - } - - const isGmailSyncV2EnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - value: true, - }); - - const isGmailSyncV2Enabled = isGmailSyncV2EnabledFeatureFlag?.value; - - if (isGmailSyncV2Enabled) { - // Todo delete this code block after migration - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - throw new Error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - } - - const messageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!messageChannel) { - throw new Error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - await this.messagingTelemetryService.track({ - eventName: 'full_message_list_fetch.started', - workspaceId, - connectedAccountId, - }); - - await this.gmailFullMessageListFetchV2Service.processMessageListFetch( - messageChannel, - connectedAccount, - workspaceId, - ); - - await this.messagingTelemetryService.track({ - eventName: 'full_message_list_fetch.completed', - workspaceId, - connectedAccountId, - messageChannelId: messageChannel.id, - }); - } else { - await this.gmailFullMessageListFetchService.fetchConnectedAccountThreads( - data.workspaceId, - data.connectedAccountId, - ); - } - } -} diff --git a/packages/twenty-server/src/modules/messaging/jobs/gmail-partial-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/jobs/gmail-partial-message-list-fetch.job.ts deleted file mode 100644 index 9954492ba5c9f..0000000000000 --- a/packages/twenty-server/src/modules/messaging/jobs/gmail-partial-message-list-fetch.job.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; - -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; - -import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; -import { GmailPartialMessageListFetchService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service'; - -export type GmailPartialMessageListFetchJobData = { - workspaceId: string; - connectedAccountId: string; -}; - -@Injectable() -export class GmailPartialMessageListFetchJob - implements MessageQueueJob -{ - private readonly logger = new Logger(GmailPartialMessageListFetchJob.name); - - constructor( - private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService, - private readonly gmailPartialSyncService: GmailPartialMessageListFetchService, - ) {} - - async handle(data: GmailPartialMessageListFetchJobData): Promise { - this.logger.log( - `gmail partial-sync for workspace ${data.workspaceId} and account ${data.connectedAccountId}`, - ); - - try { - await this.googleAPIsRefreshAccessTokenService.refreshAndSaveAccessToken( - data.workspaceId, - data.connectedAccountId, - ); - } catch (e) { - this.logger.error( - `Error refreshing access token for connected account ${data.connectedAccountId} in workspace ${data.workspaceId}`, - e, - ); - - return; - } - - await this.gmailPartialSyncService.fetchConnectedAccountThreads( - data.workspaceId, - data.connectedAccountId, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/jobs/messaging-job.module.ts b/packages/twenty-server/src/modules/messaging/jobs/messaging-job.module.ts deleted file mode 100644 index 63b78ffe3010b..0000000000000 --- a/packages/twenty-server/src/modules/messaging/jobs/messaging-job.module.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -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 { AutoCompaniesAndContactsCreationModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module'; -import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module'; -import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { BlocklistItemDeleteMessagesJob } from 'src/modules/messaging/jobs/blocklist-item-delete-messages.job'; -import { BlocklistReimportMessagesJob } from 'src/modules/messaging/jobs/blocklist-reimport-messages.job'; -import { DeleteConnectedAccountAssociatedMessagingDataJob } from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job'; -import { GmailFullMessageListFetchJob } from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; -import { GmailMessageListFetchJob } from 'src/modules/messaging/jobs/gmail-message-list-fetch.job'; -import { GmailPartialMessageListFetchJob } from 'src/modules/messaging/jobs/gmail-partial-message-list-fetch.job'; -import { MessagingCreateCompanyAndContactAfterSyncJob } from 'src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job'; -import { GmailFullMessageListFetchModule } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module'; -import { GmailPartialMessageListFetchModule } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; -import { ThreadCleanerModule } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.module'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - MessageParticipantWorkspaceEntity, - MessageChannelMessageAssociationWorkspaceEntity, - BlocklistWorkspaceEntity, - ]), - MessagingTelemetryModule, - GmailFullMessageListFetchModule, - GmailPartialMessageListFetchModule, - ThreadCleanerModule, - GoogleAPIRefreshAccessTokenModule, - AutoCompaniesAndContactsCreationModule, - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - SetMessageChannelSyncStatusModule, - ], - providers: [ - { - provide: BlocklistReimportMessagesJob.name, - useClass: BlocklistReimportMessagesJob, - }, - { - provide: BlocklistItemDeleteMessagesJob.name, - useClass: BlocklistItemDeleteMessagesJob, - }, - { - provide: GmailFullMessageListFetchJob.name, - useClass: GmailFullMessageListFetchJob, - }, - { - provide: GmailPartialMessageListFetchJob.name, - useClass: GmailPartialMessageListFetchJob, - }, - { - provide: GmailMessageListFetchJob.name, - useClass: GmailMessageListFetchJob, - }, - { - provide: DeleteConnectedAccountAssociatedMessagingDataJob.name, - useClass: DeleteConnectedAccountAssociatedMessagingDataJob, - }, - { - provide: MessagingCreateCompanyAndContactAfterSyncJob.name, - useClass: MessagingCreateCompanyAndContactAfterSyncJob, - }, - ], -}) -export class MessagingJobModule {} diff --git a/packages/twenty-server/src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts similarity index 50% rename from packages/twenty-server/src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts index eacef905ba186..5cba9355cb840 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts @@ -2,32 +2,33 @@ import { Injectable, Logger } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service'; +import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; -export type DeleteConnectedAccountAssociatedMessagingDataJobData = { +export type MessagingConnectedAccountDeletionCleanupJobData = { workspaceId: string; connectedAccountId: string; }; @Injectable() -export class DeleteConnectedAccountAssociatedMessagingDataJob - implements - MessageQueueJob +export class MessagingConnectedAccountDeletionCleanupJob + implements MessageQueueJob { private readonly logger = new Logger( - DeleteConnectedAccountAssociatedMessagingDataJob.name, + MessagingConnectedAccountDeletionCleanupJob.name, ); - constructor(private readonly threadCleanerService: ThreadCleanerService) {} + constructor( + private readonly messageCleanerService: MessagingMessageCleanerService, + ) {} async handle( - data: DeleteConnectedAccountAssociatedMessagingDataJobData, + data: MessagingConnectedAccountDeletionCleanupJobData, ): Promise { this.logger.log( `Deleting connected account ${data.connectedAccountId} associated messaging data in workspace ${data.workspaceId}`, ); - await this.threadCleanerService.cleanWorkspaceThreads(data.workspaceId); + await this.messageCleanerService.cleanWorkspaceThreads(data.workspaceId); this.logger.log( `Deleted connected account ${data.connectedAccountId} associated messaging data in workspace ${data.workspaceId}`, diff --git a/packages/twenty-server/src/modules/messaging/listeners/messaging-connected-account.listener.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts similarity index 65% rename from packages/twenty-server/src/modules/messaging/listeners/messaging-connected-account.listener.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts index 6036d3cf765de..24d5deb2974ca 100644 --- a/packages/twenty-server/src/modules/messaging/listeners/messaging-connected-account.listener.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts @@ -1,8 +1,5 @@ -import { Injectable, Inject } from '@nestjs/common'; +import { Inject } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; @@ -11,30 +8,26 @@ import { DeleteConnectedAccountAssociatedCalendarDataJobData, DeleteConnectedAccountAssociatedCalendarDataJob, } from 'src/modules/calendar/jobs/delete-connected-account-associated-calendar-data.job'; -import { - DeleteConnectedAccountAssociatedMessagingDataJobData, - DeleteConnectedAccountAssociatedMessagingDataJob, -} from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { + MessagingConnectedAccountDeletionCleanupJob, + MessagingConnectedAccountDeletionCleanupJobData, +} from 'src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job'; -@Injectable() -export class MessagingConnectedAccountListener { +export class MessagingMessageCleanerConnectedAccountListener { constructor( @Inject(MessageQueue.messagingQueue) private readonly messageQueueService: MessageQueueService, @Inject(MessageQueue.calendarQueue) private readonly calendarQueueService: MessageQueueService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, ) {} @OnEvent('connectedAccount.deleted') async handleDeletedEvent( payload: ObjectRecordDeleteEvent, ) { - await this.messageQueueService.add( - DeleteConnectedAccountAssociatedMessagingDataJob.name, + await this.messageQueueService.add( + MessagingConnectedAccountDeletionCleanupJob.name, { workspaceId: payload.workspaceId, connectedAccountId: payload.recordId, diff --git a/packages/twenty-server/src/modules/messaging/message-cleaner/messaging-message-cleaner.module.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/messaging-message-cleaner.module.ts new file mode 100644 index 0000000000000..4562bd75bad6a --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/messaging-message-cleaner.module.ts @@ -0,0 +1,27 @@ +import { Module } from '@nestjs/common'; + +import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; +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'; +import { MessagingConnectedAccountDeletionCleanupJob } from 'src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job'; +import { MessagingMessageCleanerConnectedAccountListener } from 'src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener'; +import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; + +@Module({ + imports: [ + ObjectMetadataRepositoryModule.forFeature([ + MessageWorkspaceEntity, + MessageThreadWorkspaceEntity, + ]), + ], + providers: [ + MessagingMessageCleanerService, + { + provide: MessagingConnectedAccountDeletionCleanupJob.name, + useClass: MessagingConnectedAccountDeletionCleanupJob, + }, + MessagingMessageCleanerConnectedAccountListener, + ], + exports: [MessagingMessageCleanerService], +}) +export class MessagingMessageCleanerModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.service.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts similarity index 67% rename from packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.service.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts index 40ddf77bae9f8..19a9d6b2d185e 100644 --- a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts @@ -1,14 +1,14 @@ import { Injectable } from '@nestjs/common'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; +import { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository'; +import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository'; +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'; +import { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; @Injectable() -export class ThreadCleanerService { +export class MessagingMessageCleanerService { constructor( @InjectObjectMetadataRepository(MessageWorkspaceEntity) private readonly messageRepository: MessageRepository, diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.spec.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/utils/__tests__/delete-using-pagination.util.spec.ts similarity index 88% rename from packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.spec.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/utils/__tests__/delete-using-pagination.util.spec.ts index cca39a8d6ed9a..272553278050f 100644 --- a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/utils/__tests__/delete-using-pagination.util.spec.ts @@ -1,4 +1,4 @@ -import { deleteUsingPagination } from './delete-using-pagination.util'; +import { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; describe('deleteUsingPagination', () => { it('should delete items using pagination', async () => { @@ -29,7 +29,7 @@ describe('deleteUsingPagination', () => { expect(getterPaginated).toHaveBeenNthCalledWith( 2, batchSize, - batchSize, + 0, workspaceId, transactionManager, ); diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/utils/delete-using-pagination.util.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/utils/delete-using-pagination.util.ts diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/constants/messaging-import-ongoing-sync-timeout.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/constants/messaging-import-ongoing-sync-timeout.constant.ts new file mode 100644 index 0000000000000..2f59ec93fcd3a --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/constants/messaging-import-ongoing-sync-timeout.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_IMPORT_ONGOING_SYNC_TIMEOUT = 1000 * 60 * 60; // 1 hour diff --git a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts similarity index 61% rename from packages/twenty-server/src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts index 4091eedee2a56..585762d2cb98b 100644 --- a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts @@ -4,16 +4,16 @@ import { Command, CommandRunner } from 'nest-commander'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { GmailMessageListFetchCronJob } from 'src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job'; +import { MessagingMessageListFetchCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job'; -const GMAIL_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *'; +const MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *'; @Command({ - name: 'cron:messaging:gmail-message-list-fetch', + name: 'cron:messaging:message-list-fetch', description: 'Starts a cron job to sync existing connected account messages and store them in the cache', }) -export class GmailMessageListFetchCronCommand extends CommandRunner { +export class MessagingMessageListFetchCronCommand extends CommandRunner { constructor( @Inject(MessageQueue.cronQueue) private readonly messageQueueService: MessageQueueService, @@ -23,10 +23,10 @@ export class GmailMessageListFetchCronCommand extends CommandRunner { async run(): Promise { await this.messageQueueService.addCron( - GmailMessageListFetchCronJob.name, + MessagingMessageListFetchCronJob.name, undefined, { - repeat: { pattern: GMAIL_MESSAGE_LIST_FETCH_CRON_PATTERN }, + repeat: { pattern: MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN }, }, ); } diff --git a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-messages-import.cron.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts similarity index 70% rename from packages/twenty-server/src/modules/messaging/crons/commands/gmail-messages-import.cron.command.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts index ec2986f6aa467..aae9df3723b29 100644 --- a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-messages-import.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts @@ -4,13 +4,13 @@ import { Command, CommandRunner } from 'nest-commander'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { GmailMessagesImportCronJob } from 'src/modules/messaging/crons/jobs/gmail-messages-import.cron.job'; +import { MessagingMessagesImportCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job'; @Command({ - name: 'cron:messaging:gmail-messages-import', + name: 'cron:messaging:messages-import', description: 'Starts a cron job to fetch all messages from cache', }) -export class GmailMessagesImportCronCommand extends CommandRunner { +export class MessagingMessagesImportCronCommand extends CommandRunner { constructor( @Inject(MessageQueue.cronQueue) private readonly messageQueueService: MessageQueueService, @@ -20,7 +20,7 @@ export class GmailMessagesImportCronCommand extends CommandRunner { async run(): Promise { await this.messageQueueService.addCron( - GmailMessagesImportCronJob.name, + MessagingMessagesImportCronJob.name, undefined, { repeat: { diff --git a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts similarity index 63% rename from packages/twenty-server/src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts index c8266987d2623..206990a728091 100644 --- a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts @@ -7,30 +7,22 @@ import { MessageQueueJob } from 'src/engine/integrations/message-queue/interface import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; -import { - GmailPartialMessageListFetchJobData, - GmailPartialMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-partial-message-list-fetch.job'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; 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 { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +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 { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { - GmailMessageListFetchJobData, - GmailMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-message-list-fetch.job'; + MessagingMessageListFetchJobData, + MessagingMessageListFetchJob, +} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; @Injectable() -export class GmailMessageListFetchCronJob +export class MessagingMessageListFetchCronJob implements MessageQueueJob { - private readonly logger = new Logger(GmailMessageListFetchCronJob.name); + private readonly logger = new Logger(MessagingMessageListFetchCronJob.name); constructor( @InjectRepository(Workspace, 'core') @@ -42,8 +34,6 @@ export class GmailMessageListFetchCronJob @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, private readonly environmentService: EnvironmentService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, ) {} async handle(): Promise { @@ -74,15 +64,6 @@ export class GmailMessageListFetchCronJob } private async enqueueSyncs(workspaceId: string): Promise { - const isGmailSyncV2EnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - value: true, - }); - - const isGmailSyncV2Enabled = isGmailSyncV2EnabledFeatureFlag?.value; - try { const messageChannels = await this.messageChannelRepository.getAll(workspaceId); @@ -92,23 +73,13 @@ export class GmailMessageListFetchCronJob continue; } - if (isGmailSyncV2Enabled) { - await this.messageQueueService.add( - GmailMessageListFetchJob.name, - { - workspaceId, - connectedAccountId: messageChannel.connectedAccountId, - }, - ); - } else { - await this.messageQueueService.add( - GmailPartialMessageListFetchJob.name, - { - workspaceId, - connectedAccountId: messageChannel.connectedAccountId, - }, - ); - } + await this.messageQueueService.add( + MessagingMessageListFetchJob.name, + { + workspaceId, + connectedAccountId: messageChannel.connectedAccountId, + }, + ); } } catch (error) { this.logger.error( diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts new file mode 100644 index 0000000000000..6780059bd4646 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts @@ -0,0 +1,65 @@ +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository, In } from 'typeorm'; + +import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; + +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; +import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { + MessagingMessagesImportJobData, + MessagingMessagesImportJob, +} from 'src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job'; + +@Injectable() +export class MessagingMessagesImportCronJob + implements MessageQueueJob +{ + private readonly logger = new Logger(MessagingMessagesImportCronJob.name); + + constructor( + @InjectRepository(Workspace, 'core') + private readonly workspaceRepository: Repository, + @InjectRepository(DataSourceEntity, 'metadata') + private readonly dataSourceRepository: Repository, + private readonly environmentService: EnvironmentService, + @Inject(MessageQueue.messagingQueue) + private readonly messageQueueService: MessageQueueService, + ) {} + + async handle(): Promise { + const workspaceIds = ( + await this.workspaceRepository.find({ + where: this.environmentService.get('IS_BILLING_ENABLED') + ? { + subscriptionStatus: In(['active', 'trialing', 'past_due']), + } + : {}, + select: ['id'], + }) + ).map((workspace) => workspace.id); + + const dataSources = await this.dataSourceRepository.find({ + where: { + workspaceId: In(workspaceIds), + }, + }); + + const workspaceIdsWithDataSources = new Set( + dataSources.map((dataSource) => dataSource.workspaceId), + ); + + for (const workspaceId of workspaceIdsWithDataSources) { + await this.messageQueueService.add( + MessagingMessagesImportJob.name, + { + workspaceId, + }, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories.ts new file mode 100644 index 0000000000000..1b6cd01526766 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories.ts @@ -0,0 +1,5 @@ +export const MESSAGING_GMAIL_EXCLUDED_CATEGORIES = [ + 'promotions', + 'social', + 'forums', +]; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant.ts new file mode 100644 index 0000000000000..86dd74054491a --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_GMAIL_USERS_HISTORY_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant.ts new file mode 100644 index 0000000000000..81255f3837426 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE = 20; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant.ts new file mode 100644 index 0000000000000..ece0d18e43a57 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_GMAIL_USERS_MESSAGES_LIST_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts new file mode 100644 index 0000000000000..380e4534efb1a --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts @@ -0,0 +1,53 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; +import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; +import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module'; +import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.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 { 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 { MessagingGmailFetchMessagesByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service'; +import { MessagingGmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service'; +import { MessagingGmailFullMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service'; +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'; + +@Module({ + imports: [ + GoogleAPIRefreshAccessTokenModule, + EnvironmentModule, + ObjectMetadataRepositoryModule.forFeature([ + ConnectedAccountWorkspaceEntity, + MessageChannelWorkspaceEntity, + MessageChannelMessageAssociationWorkspaceEntity, + BlocklistWorkspaceEntity, + ]), + MessagingCommonModule, + TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), + ], + providers: [ + MessagingGmailClientProvider, + MessagingGmailHistoryService, + MessagingGmailFetchMessagesByBatchesService, + MessagingGmailPartialMessageListFetchService, + MessagingGmailFullMessageListFetchService, + MessagingGmailMessagesImportService, + MessagingGmailFetchMessageIdsToExcludeService, + ], + exports: [ + MessagingGmailClientProvider, + MessagingGmailHistoryService, + MessagingGmailFetchMessagesByBatchesService, + MessagingGmailPartialMessageListFetchService, + MessagingGmailFullMessageListFetchService, + MessagingGmailMessagesImportService, + MessagingGmailFetchMessageIdsToExcludeService, + ], +}) +export class MessagingGmailDriverModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/providers/gmail/gmail-client.provider.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider.ts similarity index 96% rename from packages/twenty-server/src/modules/messaging/services/providers/gmail/gmail-client.provider.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider.ts index 3b5e591ac546d..130e335621a1f 100644 --- a/packages/twenty-server/src/modules/messaging/services/providers/gmail/gmail-client.provider.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider.ts @@ -6,7 +6,7 @@ import { gmail_v1, google } from 'googleapis'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; @Injectable() -export class GmailClientProvider { +export class MessagingGmailClientProvider { constructor(private readonly environmentService: EnvironmentService) {} public async getGmailClient(refreshToken: string): Promise { diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service.ts similarity index 90% rename from packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service.ts index 6bfda7d21ae9a..cc63ce2488995 100644 --- a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service.ts @@ -5,17 +5,21 @@ import planer from 'planer'; import addressparser from 'addressparser'; import { gmail_v1 } from 'googleapis'; -import { GmailMessage } from 'src/modules/messaging/types/gmail-message'; -import { MessageQuery } from 'src/modules/messaging/types/message-or-thread-query'; -import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service'; -import { formatAddressObjectAsParticipants } from 'src/modules/messaging/services/utils/format-address-object-as-participants.util'; import { assert, assertNotNull } from 'src/utils/assert'; +import { GmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; +import { MessageQuery } from 'src/modules/messaging/message-import-manager/types/message-or-thread-query'; +import { formatAddressObjectAsParticipants } from 'src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util'; +import { MessagingFetchByBatchesService } from 'src/modules/messaging/common/services/messaging-fetch-by-batch.service'; @Injectable() -export class FetchMessagesByBatchesService { - private readonly logger = new Logger(FetchMessagesByBatchesService.name); - - constructor(private readonly fetchByBatchesService: FetchByBatchesService) {} +export class MessagingGmailFetchMessagesByBatchesService { + private readonly logger = new Logger( + MessagingGmailFetchMessagesByBatchesService.name, + ); + + constructor( + private readonly fetchByBatchesService: MessagingFetchByBatchesService, + ) {} async fetchAllMessages( queries: MessageQuery[], diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service.ts similarity index 62% rename from packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service.ts index b0df2f31caf01..266553695f36f 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service.ts @@ -2,15 +2,15 @@ import { Injectable } from '@nestjs/common'; import { gmail_v1 } from 'googleapis'; -import { GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/constants/gmail-excluded-categories'; -import { GmailGetHistoryService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service'; -import { computeGmailCategoryLabelId } from 'src/modules/messaging/utils/compute-gmail-category-label-id'; +import { MESSAGING_GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories'; +import { MessagingGmailHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service'; +import { computeGmailCategoryLabelId } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id'; import { assertNotNull } from 'src/utils/assert'; @Injectable() -export class GmailFetchMessageIdsToExcludeService { +export class MessagingGmailFetchMessageIdsToExcludeService { constructor( - private readonly gmailGetHistoryService: GmailGetHistoryService, + private readonly gmailGetHistoryService: MessagingGmailHistoryService, ) {} public async fetchEmailIdsToExcludeOrThrow( @@ -19,7 +19,7 @@ export class GmailFetchMessageIdsToExcludeService { ): Promise { const emailIds: string[] = []; - for (const category of GMAIL_EXCLUDED_CATEGORIES) { + for (const category of MESSAGING_GMAIL_EXCLUDED_CATEGORIES) { const { history, error } = await this.gmailGetHistoryService.getHistory( gmailClient, lastSyncHistoryId, diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts similarity index 77% rename from packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts index d776ffd835d27..1fb1c4b95bd58 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts @@ -9,27 +9,29 @@ import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decora 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 { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GMAIL_USERS_MESSAGES_LIST_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-messages-list-max-result.constant'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +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 { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { GmailError, - GmailErrorHandlingService, -} from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/utils/compute-gmail-category-excude-search-filter'; -import { GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/constants/gmail-excluded-categories'; + MessagingErrorHandlingService, +} from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; +import { MessagingGmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider'; +import { MESSAGING_GMAIL_USERS_MESSAGES_LIST_MAX_RESULT } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant'; +import { MESSAGING_GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories'; @Injectable() -export class GmailFullMessageListFetchV2Service { - private readonly logger = new Logger(GmailFullMessageListFetchV2Service.name); +export class MessagingGmailFullMessageListFetchService { + private readonly logger = new Logger( + MessagingGmailFullMessageListFetchService.name, + ); constructor( - private readonly gmailClientProvider: GmailClientProvider, + private readonly gmailClientProvider: MessagingGmailClientProvider, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, @InjectCacheStorage(CacheStorageNamespace.Messaging) @@ -38,8 +40,8 @@ export class GmailFullMessageListFetchV2Service { MessageChannelMessageAssociationWorkspaceEntity, ) private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, + private readonly gmailErrorHandlingService: MessagingErrorHandlingService, ) {} public async processMessageListFetch( @@ -47,7 +49,7 @@ export class GmailFullMessageListFetchV2Service { connectedAccount: ObjectRecord, workspaceId: string, ) { - await this.messageChannelSyncStatusService.markAsMessagesListFetchOngoing( + await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing( messageChannel.id, workspaceId, ); @@ -75,7 +77,7 @@ export class GmailFullMessageListFetchV2Service { return; } - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); @@ -97,9 +99,11 @@ export class GmailFullMessageListFetchV2Service { try { response = await gmailClient.users.messages.list({ userId: 'me', - maxResults: GMAIL_USERS_MESSAGES_LIST_MAX_RESULT, + maxResults: MESSAGING_GMAIL_USERS_MESSAGES_LIST_MAX_RESULT, pageToken, - q: computeGmailCategoryExcludeSearchFilter(GMAIL_EXCLUDED_CATEGORIES), + q: computeGmailCategoryExcludeSearchFilter( + MESSAGING_GMAIL_EXCLUDED_CATEGORIES, + ), }); } catch (error) { return { diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service.ts similarity index 87% rename from packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service.ts index ebb68e2d0f95e..ab18122948e67 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service.ts @@ -3,11 +3,11 @@ import { Injectable } from '@nestjs/common'; import { gmail_v1 } from 'googleapis'; import { GaxiosResponse } from 'gaxios'; -import { GMAIL_USERS_HISTORY_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-history-max-result.constant'; -import { GmailError } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; +import { GmailError } from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { MESSAGING_GMAIL_USERS_HISTORY_MAX_RESULT } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant'; @Injectable() -export class GmailGetHistoryService { +export class MessagingGmailHistoryService { constructor() {} public async getHistory( @@ -30,7 +30,7 @@ export class GmailGetHistoryService { try { response = await gmailClient.users.history.list({ userId: 'me', - maxResults: GMAIL_USERS_HISTORY_MAX_RESULT, + maxResults: MESSAGING_GMAIL_USERS_HISTORY_MAX_RESULT, pageToken, startHistoryId: lastSyncHistoryId, historyTypes: historyTypes || ['messageAdded', 'messageDeleted'], diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts similarity index 71% rename from packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts index 64c5bac161bea..259e6de68193d 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts @@ -1,39 +1,40 @@ import { Injectable, Logger } from '@nestjs/common'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncSubStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util'; 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 { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { SaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service'; -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; -import { GmailMessagesImportService } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository'; -import { filterEmails } from 'src/modules/messaging/services/utils/filter-emails.util'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { + MessageChannelWorkspaceEntity, + MessageChannelSyncSubStatus, +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { createQueriesFromMessageIds } from 'src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util'; +import { filterEmails } from 'src/modules/messaging/message-import-manager/utils/filter-emails.util'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; +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 { 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'; @Injectable() -export class GmailMessagesImportV2Service { - private readonly logger = new Logger(GmailMessagesImportService.name); +export class MessagingGmailMessagesImportService { + private readonly logger = new Logger( + MessagingGmailMessagesImportService.name, + ); constructor( - private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService, + private readonly fetchMessagesByBatchesService: MessagingGmailFetchMessagesByBatchesService, @InjectCacheStorage(CacheStorageNamespace.Messaging) private readonly cacheStorage: CacheStorageService, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, - private readonly saveMessagesAndEnqueueContactCreationService: SaveMessagesAndEnqueueContactCreationService, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, + private readonly saveMessagesAndEnqueueContactCreationService: MessagingSaveMessagesAndEnqueueContactCreationService, + private readonly gmailErrorHandlingService: MessagingErrorHandlingService, private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService, private readonly messagingTelemetryService: MessagingTelemetryService, @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) @@ -63,7 +64,7 @@ export class GmailMessagesImportV2Service { `Messaging import for workspace ${workspaceId} and account ${connectedAccount.id} starting...`, ); - await this.messageChannelSyncStatusService.markAsMessagesImportOngoing( + await this.messagingChannelSyncStatusService.markAsMessagesImportOngoing( messageChannel.id, workspaceId, ); @@ -76,11 +77,11 @@ export class GmailMessagesImportV2Service { const messageIdsToFetch = (await this.cacheStorage.setPop( `messages-to-import:${workspaceId}:gmail:${messageChannel.id}`, - GMAIL_USERS_MESSAGES_GET_BATCH_SIZE, + MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE, )) ?? []; if (!messageIdsToFetch?.length) { - await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( + await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( messageChannel.id, workspaceId, ); @@ -119,13 +120,15 @@ export class GmailMessagesImportV2Service { workspaceId, ); - if (messageIdsToFetch.length < GMAIL_USERS_MESSAGES_GET_BATCH_SIZE) { - await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( + if ( + messageIdsToFetch.length < MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE + ) { + await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( messageChannel.id, workspaceId, ); } else { - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts similarity index 70% rename from packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts index 91270d78f0440..f45c5be5297c4 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts @@ -2,30 +2,30 @@ import { Injectable, Logger } from '@nestjs/common'; import { gmail_v1 } from 'googleapis'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; 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 { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { GmailGetHistoryService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { GmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service'; +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 { 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 { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; +import { MessagingGmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service'; +import { MessagingErrorHandlingService } from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { MessagingGmailHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service'; @Injectable() -export class GmailPartialMessageListFetchV2Service { +export class MessagingGmailPartialMessageListFetchService { private readonly logger = new Logger( - GmailPartialMessageListFetchV2Service.name, + MessagingGmailPartialMessageListFetchService.name, ); constructor( - private readonly gmailClientProvider: GmailClientProvider, + private readonly gmailClientProvider: MessagingGmailClientProvider, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, @InjectCacheStorage(CacheStorageNamespace.Messaging) @@ -34,10 +34,10 @@ export class GmailPartialMessageListFetchV2Service { MessageChannelMessageAssociationWorkspaceEntity, ) private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, - private readonly gmailGetHistoryService: GmailGetHistoryService, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, - private readonly gmailFetchMessageIdsToExcludeService: GmailFetchMessageIdsToExcludeService, + private readonly gmailErrorHandlingService: MessagingErrorHandlingService, + private readonly gmailGetHistoryService: MessagingGmailHistoryService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, + private readonly gmailFetchMessageIdsToExcludeService: MessagingGmailFetchMessageIdsToExcludeService, ) {} public async processMessageListFetch( @@ -45,7 +45,7 @@ export class GmailPartialMessageListFetchV2Service { connectedAccount: ObjectRecord, workspaceId: string, ): Promise { - await this.messageChannelSyncStatusService.markAsMessagesListFetchOngoing( + await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing( messageChannel.id, workspaceId, ); @@ -85,7 +85,7 @@ export class GmailPartialMessageListFetchV2Service { `Partial message list import done with history ${historyId} and nothing to update for workspace ${workspaceId} and account ${connectedAccount.id}`, ); - await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( + await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( messageChannel.id, workspaceId, ); @@ -144,7 +144,7 @@ export class GmailPartialMessageListFetchV2Service { workspaceId, ); - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); diff --git a/packages/twenty-server/src/modules/messaging/types/gmail-message-parsed-response.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message-parsed-response.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/gmail-message-parsed-response.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message-parsed-response.ts diff --git a/packages/twenty-server/src/modules/messaging/types/gmail-message.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/gmail-message.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message.ts diff --git a/packages/twenty-server/src/modules/messaging/types/gmail-thread.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-thread.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/gmail-thread.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-thread.ts diff --git a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts similarity index 89% rename from packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts index d77f177f07ff5..776ab33569966 100644 --- a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts @@ -1,4 +1,4 @@ -import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/utils/compute-gmail-category-excude-search-filter'; +import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter'; describe('computeGmailCategoryExcludeSearchFilter', () => { it('should return correct exclude search filter with empty category array', () => { diff --git a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-label-id.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-label-id.spec.ts similarity index 78% rename from packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-label-id.spec.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-label-id.spec.ts index 2373669efe13b..5cacd83c901b7 100644 --- a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-label-id.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-label-id.spec.ts @@ -1,4 +1,4 @@ -import { computeGmailCategoryLabelId } from 'src/modules/messaging/utils/compute-gmail-category-label-id'; +import { computeGmailCategoryLabelId } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id'; describe('computeGmailCategoryLabelId', () => { it('should return correct category label id', () => { diff --git a/packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-excude-search-filter.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-excude-search-filter.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter.ts diff --git a/packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-label-id.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-label-id.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id.ts diff --git a/packages/twenty-server/src/modules/messaging/jobs/gmail-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts similarity index 77% rename from packages/twenty-server/src/modules/messaging/jobs/gmail-message-list-fetch.job.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts index 36c86faedfc29..f180a91a92c50 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/gmail-message-list-fetch.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts @@ -2,32 +2,32 @@ import { Injectable, Logger } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { GmailPartialMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service'; -import { - MessageChannelSyncSubStatus, - MessageChannelWorkspaceEntity, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { GmailFullMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; 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 { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { + MessageChannelSyncSubStatus, + MessageChannelWorkspaceEntity, +} 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'; -export type GmailMessageListFetchJobData = { +export type MessagingMessageListFetchJobData = { workspaceId: string; connectedAccountId: string; }; @Injectable() -export class GmailMessageListFetchJob - implements MessageQueueJob +export class MessagingMessageListFetchJob + implements MessageQueueJob { - private readonly logger = new Logger(GmailMessageListFetchJob.name); + private readonly logger = new Logger(MessagingMessageListFetchJob.name); constructor( - private readonly gmailFullMessageListFetchV2Service: GmailFullMessageListFetchV2Service, - private readonly gmailPartialMessageListFetchV2Service: GmailPartialMessageListFetchV2Service, + private readonly gmailFullMessageListFetchService: MessagingGmailFullMessageListFetchService, + private readonly gmailPartialMessageListFetchV2Service: MessagingGmailPartialMessageListFetchService, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) @@ -35,7 +35,7 @@ export class GmailMessageListFetchJob private readonly messagingTelemetryService: MessagingTelemetryService, ) {} - async handle(data: GmailMessageListFetchJobData): Promise { + async handle(data: MessagingMessageListFetchJobData): Promise { const { workspaceId, connectedAccountId } = data; await this.messagingTelemetryService.track({ @@ -113,7 +113,7 @@ export class GmailMessageListFetchJob connectedAccountId, }); - await this.gmailFullMessageListFetchV2Service.processMessageListFetch( + await this.gmailFullMessageListFetchService.processMessageListFetch( messageChannel, connectedAccount, workspaceId, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts new file mode 100644 index 0000000000000..4529e81059b46 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts @@ -0,0 +1,61 @@ +import { Injectable } from '@nestjs/common'; + +import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; + +import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +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 { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +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'; + +export type MessagingMessagesImportJobData = { + workspaceId: string; +}; + +@Injectable() +export class MessagingMessagesImportJob + implements MessageQueueJob +{ + constructor( + @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) + private readonly connectedAccountRepository: ConnectedAccountRepository, + private readonly gmailFetchMessageContentFromCacheService: MessagingGmailMessagesImportService, + @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) + private readonly messageChannelRepository: MessageChannelRepository, + private readonly messagingTelemetryService: MessagingTelemetryService, + ) {} + + async handle(data: MessagingMessagesImportJobData): Promise { + const { workspaceId } = data; + + const messageChannels = + await this.messageChannelRepository.getAll(workspaceId); + + for (const messageChannel of messageChannels) { + if (!messageChannel?.isSyncEnabled) { + continue; + } + + await this.messagingTelemetryService.track({ + eventName: 'messages_import.triggered', + workspaceId, + connectedAccountId: messageChannel.connectedAccountId, + messageChannelId: messageChannel.id, + }); + + const connectedAccount = + await this.connectedAccountRepository.getConnectedAccountOrThrow( + workspaceId, + messageChannel.connectedAccountId, + ); + + await this.gmailFetchMessageContentFromCacheService.processMessageBatchImport( + messageChannel, + connectedAccount, + workspaceId, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts new file mode 100644 index 0000000000000..b0b6362c0f35c --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts @@ -0,0 +1,44 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; +import { MessagingMessageListFetchCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command'; +import { MessagingMessagesImportCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command'; +import { MessagingMessageListFetchCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job'; +import { MessagingMessagesImportCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job'; +import { MessagingGmailDriverModule } from 'src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module'; +import { MessagingMessageListFetchJob } from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; +import { MessagingMessagesImportJob } from 'src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job'; + +@Module({ + imports: [ + MessagingGmailDriverModule, + MessagingCommonModule, + TypeOrmModule.forFeature([Workspace], 'core'), + TypeOrmModule.forFeature([DataSourceEntity], 'metadata'), + ], + providers: [ + MessagingMessageListFetchCronCommand, + MessagingMessagesImportCronCommand, + { + provide: MessagingMessageListFetchJob.name, + useClass: MessagingMessageListFetchJob, + }, + { + provide: MessagingMessagesImportJob.name, + useClass: MessagingMessagesImportJob, + }, + { + provide: MessagingMessageListFetchCronJob.name, + useClass: MessagingMessageListFetchCronJob, + }, + { + provide: MessagingMessagesImportCronJob.name, + useClass: MessagingMessagesImportCronJob, + }, + ], + exports: [], +}) +export class MessagingImportManagerModule {} diff --git a/packages/twenty-server/src/modules/messaging/types/batch-queries.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/types/batch-queries.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/batch-queries.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/types/batch-queries.ts diff --git a/packages/twenty-server/src/modules/messaging/types/message-or-thread-query.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/types/message-or-thread-query.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/message-or-thread-query.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/types/message-or-thread-query.ts diff --git a/packages/twenty-server/src/modules/messaging/services/utils/__tests__/format-address-object-as-participants.util.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/format-address-object-as-participants.util.spec.ts similarity index 91% rename from packages/twenty-server/src/modules/messaging/services/utils/__tests__/format-address-object-as-participants.util.spec.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/format-address-object-as-participants.util.spec.ts index 16a87ea39623e..84193a5ec9e0f 100644 --- a/packages/twenty-server/src/modules/messaging/services/utils/__tests__/format-address-object-as-participants.util.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/format-address-object-as-participants.util.spec.ts @@ -1,4 +1,4 @@ -import { formatAddressObjectAsParticipants } from 'src/modules/messaging/services/utils/format-address-object-as-participants.util'; +import { formatAddressObjectAsParticipants } from 'src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util'; describe('formatAddressObjectAsParticipants', () => { it('should format address object as participants', () => { diff --git a/packages/twenty-server/src/modules/messaging/utils/create-queries-from-message-ids.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util.ts similarity index 68% rename from packages/twenty-server/src/modules/messaging/utils/create-queries-from-message-ids.util.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util.ts index fbf654934a36d..3da664c123268 100644 --- a/packages/twenty-server/src/modules/messaging/utils/create-queries-from-message-ids.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util.ts @@ -1,4 +1,4 @@ -import { MessageQuery } from 'src/modules/messaging/types/message-or-thread-query'; +import { MessageQuery } from 'src/modules/messaging/message-import-manager/types/message-or-thread-query'; export const createQueriesFromMessageIds = ( messageExternalIds: string[], diff --git a/packages/twenty-server/src/modules/messaging/services/utils/filter-emails.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/services/utils/filter-emails.util.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts index 2a95c0f5fab47..01140a00fc6e2 100644 --- a/packages/twenty-server/src/modules/messaging/services/utils/filter-emails.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts @@ -1,5 +1,5 @@ -import { GmailMessage } from 'src/modules/messaging/types/gmail-message'; import { isEmailBlocklisted } from 'src/modules/calendar-messaging-participant/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 export const filterEmails = (messages: GmailMessage[], blocklist: string[]) => { diff --git a/packages/twenty-server/src/modules/messaging/services/utils/format-address-object-as-participants.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util.ts similarity index 90% rename from packages/twenty-server/src/modules/messaging/services/utils/format-address-object-as-participants.util.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util.ts index 113a9c1d2b3b3..a6b9e9d2646fb 100644 --- a/packages/twenty-server/src/modules/messaging/services/utils/format-address-object-as-participants.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util.ts @@ -1,6 +1,6 @@ import addressparser from 'addressparser'; -import { Participant } from 'src/modules/messaging/types/gmail-message'; +import { Participant } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; const formatAddressObjectAsArray = ( addressObject: addressparser.EmailAddress | addressparser.EmailAddress[], diff --git a/packages/twenty-server/src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job.ts b/packages/twenty-server/src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job.ts rename to packages/twenty-server/src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts index a51ad8c0f59b1..1f2b3a7e6198c 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts @@ -11,10 +11,10 @@ import { } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; export type MessagingCreateCompanyAndContactAfterSyncJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/modules/messaging/message-participants-manager/messaging-participants-manager.module.ts b/packages/twenty-server/src/modules/messaging/message-participants-manager/messaging-participants-manager.module.ts new file mode 100644 index 0000000000000..f7744916fb4a6 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-participants-manager/messaging-participants-manager.module.ts @@ -0,0 +1,24 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module'; +import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.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 { MessagingCreateCompanyAndContactAfterSyncJob } from 'src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), + AnalyticsModule, + MessagingGmailDriverModule, + AutoCompaniesAndContactsCreationModule, + ], + providers: [ + { + provide: MessagingCreateCompanyAndContactAfterSyncJob.name, + useClass: MessagingCreateCompanyAndContactAfterSyncJob, + }, + ], +}) +export class MessaginParticipantsManagerModule {} diff --git a/packages/twenty-server/src/modules/messaging/messaging.module.ts b/packages/twenty-server/src/modules/messaging/messaging.module.ts index 907c5bcb018b8..0797e3853b643 100644 --- a/packages/twenty-server/src/modules/messaging/messaging.module.ts +++ b/packages/twenty-server/src/modules/messaging/messaging.module.ts @@ -1,22 +1,18 @@ import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { MessagingMessageChannelListener } from 'src/modules/messaging/listeners/messaging-message-channel.listener'; -import { MessagingConnectedAccountListener } from 'src/modules/messaging/listeners/messaging-connected-account.listener'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ParticipantPersonListener } from 'src/modules/calendar-messaging-participant/listeners/participant-person.listener'; -import { ParticipantWorkspaceMemberListener } from 'src/modules/calendar-messaging-participant/listeners/participant-workspace-member.listener'; -import { MessagingBlocklistListener } from 'src/modules/messaging/listeners/messaging-blocklist.listener'; +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'; @Module({ - imports: [TypeOrmModule.forFeature([FeatureFlagEntity], 'core')], - providers: [ - ParticipantPersonListener, - ParticipantWorkspaceMemberListener, - MessagingMessageChannelListener, - MessagingConnectedAccountListener, - MessagingBlocklistListener, + imports: [ + MessagingImportManagerModule, + MessagingMessageCleanerModule, + MessaginParticipantsManagerModule, + MessagingBlocklistManagerModule, ], + providers: [], exports: [], }) export class MessagingModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module.ts b/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module.ts deleted file mode 100644 index 0535c95caf875..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { HttpModule } from '@nestjs/axios'; -import { Module } from '@nestjs/common'; - -import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service'; - -@Module({ - imports: [ - HttpModule.register({ - baseURL: 'https://www.googleapis.com/batch/gmail/v1', - }), - ], - providers: [FetchByBatchesService], - exports: [FetchByBatchesService], -}) -export class FetchByBatchModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module.ts b/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module.ts deleted file mode 100644 index 9bcb913718b69..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { FetchByBatchModule } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module'; -import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service'; - -@Module({ - imports: [FetchByBatchModule], - providers: [FetchMessagesByBatchesService], - exports: [FetchMessagesByBatchesService], -}) -export class FetchMessagesByBatchesModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module.ts deleted file mode 100644 index 915fac67fdc88..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; - -@Module({ - imports: [SetMessageChannelSyncStatusModule, MessagingTelemetryModule], - providers: [GmailErrorHandlingService], - exports: [GmailErrorHandlingService], -}) -export class GmailErrorHandlingModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module.ts deleted file mode 100644 index e5733ffc44d7d..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -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 { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; -import { GmailFullMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service'; -import { GmailFullMessageListFetchService } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessagingProvidersModule } from 'src/modules/messaging/services/providers/messaging-providers.module'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - MessagingProvidersModule, - FetchMessagesByBatchesModule, - GmailErrorHandlingModule, - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - MessageChannelMessageAssociationWorkspaceEntity, - BlocklistWorkspaceEntity, - ]), - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - WorkspaceDataSourceModule, - SetMessageChannelSyncStatusModule, - ], - providers: [ - GmailFullMessageListFetchService, - GmailFullMessageListFetchV2Service, - ], - exports: [ - GmailFullMessageListFetchService, - GmailFullMessageListFetchV2Service, - ], -}) -export class GmailFullMessageListFetchModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service.ts deleted file mode 100644 index e2ab6e0f5bfd4..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service.ts +++ /dev/null @@ -1,306 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { EntityManager, Repository } from 'typeorm'; -import { gmail_v1 } from 'googleapis'; - -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -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 { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GMAIL_USERS_MESSAGES_LIST_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-messages-list-max-result.constant'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/utils/compute-gmail-category-excude-search-filter'; -import { GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/constants/gmail-excluded-categories'; - -@Injectable() -export class GmailFullMessageListFetchService { - private readonly logger = new Logger(GmailFullMessageListFetchService.name); - - constructor( - private readonly gmailClientProvider: GmailClientProvider, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) - private readonly blocklistRepository: BlocklistRepository, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - @InjectCacheStorage(CacheStorageNamespace.Messaging) - private readonly cacheStorage: CacheStorageService, - @InjectObjectMetadataRepository( - MessageChannelMessageAssociationWorkspaceEntity, - ) - private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - ) {} - - public async fetchConnectedAccountThreads( - workspaceId: string, - connectedAccountId: string, - includedEmails?: string[], - ) { - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - this.logger.error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - - return; - } - - const refreshToken = connectedAccount.refreshToken; - - if (!refreshToken) { - throw new Error( - `No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - const gmailMessageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!gmailMessageChannel) { - this.logger.error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - - return; - } - - if (gmailMessageChannel.syncStatus === MessageChannelSyncStatus.ONGOING) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} is locked, import will be retried later.`, - ); - - return; - } - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.ONGOING, - workspaceId, - ); - - const workspaceDataSource = - await this.workspaceDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); - - const gmailClient: gmail_v1.Gmail = - await this.gmailClientProvider.getGmailClient(refreshToken); - - const blocklistedEmails = await this.fetchBlocklistEmails( - connectedAccount.accountOwnerId, - workspaceId, - ); - - await workspaceDataSource - ?.transaction(async (transactionManager) => { - await this.fetchAllMessageIdsFromGmailAndStoreInCache( - gmailClient, - gmailMessageChannel.id, - includedEmails || [], - blocklistedEmails, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - }) - .catch(async (error) => { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - }); - } - - public async fetchAllMessageIdsFromGmailAndStoreInCache( - gmailClient: gmail_v1.Gmail, - messageChannelId: string, - includedEmails: string[], - blocklistedEmails: string[], - workspaceId: string, - transactionManager?: EntityManager, - ) { - let pageToken: string | undefined; - let hasMoreMessages = true; - let messageIdsToFetch = 0; - let firstMessageExternalId; - - while (hasMoreMessages) { - const response = await gmailClient.users.messages.list({ - userId: 'me', - maxResults: GMAIL_USERS_MESSAGES_LIST_MAX_RESULT, - pageToken, - q: computeGmailCategoryExcludeSearchFilter(GMAIL_EXCLUDED_CATEGORIES), - }); - - if (response.data?.messages) { - const messageExternalIds = response.data.messages - .filter((message): message is { id: string } => message.id != null) - .map((message) => message.id); - - if (!firstMessageExternalId) { - firstMessageExternalId = messageExternalIds[0]; - } - - const existingMessageChannelMessageAssociations = - await this.messageChannelMessageAssociationRepository.getByMessageExternalIdsAndMessageChannelId( - messageExternalIds, - messageChannelId, - workspaceId, - transactionManager, - ); - - const existingMessageChannelMessageAssociationsExternalIds = - existingMessageChannelMessageAssociations.map( - (messageChannelMessageAssociation) => - messageChannelMessageAssociation.messageExternalId, - ); - - const messageIdsToImport = messageExternalIds.filter( - (messageExternalId) => - !existingMessageChannelMessageAssociationsExternalIds.includes( - messageExternalId, - ), - ); - - if (messageIdsToImport && messageIdsToImport.length) { - await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${messageChannelId}`, - messageIdsToImport, - ); - - messageIdsToFetch += messageIdsToImport.length; - } - } - - pageToken = response.data.nextPageToken ?? undefined; - hasMoreMessages = !!pageToken; - } - - if (!messageIdsToFetch) { - this.logger.log( - `No messages found in Gmail for messageChannel ${messageChannelId} in workspace ${workspaceId}`, - ); - - return; - } - - this.logger.log( - `Fetched all ${messageIdsToFetch} message ids from Gmail for messageChannel ${messageChannelId} in workspace ${workspaceId} and added to cache for import`, - ); - - await this.updateLastSyncCursor( - gmailClient, - messageChannelId, - firstMessageExternalId, - workspaceId, - transactionManager, - ); - } - - public async fetchBlocklistEmails( - workspaceMemberId: string, - workspaceId: string, - ) { - const isBlocklistEnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId, - key: FeatureFlagKeys.IsBlocklistEnabled, - value: true, - }); - - const isBlocklistEnabled = - isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value; - - const blocklist = isBlocklistEnabled - ? await this.blocklistRepository.getByWorkspaceMemberId( - workspaceMemberId, - workspaceId, - ) - : []; - - return blocklist.map((blocklist) => blocklist.handle); - } - - private async updateLastSyncCursor( - gmailClient: gmail_v1.Gmail, - messageChannelId: string, - firstMessageExternalId: string, - workspaceId: string, - transactionManager?: EntityManager, - ) { - if (!firstMessageExternalId) { - throw new Error( - `No first message found for workspace ${workspaceId} and account ${messageChannelId}, can't update sync external id`, - ); - } - - const firstMessageContent = await gmailClient.users.messages.get({ - userId: 'me', - id: firstMessageExternalId, - }); - - if (!firstMessageContent?.data) { - throw new Error( - `No first message content found for message ${firstMessageExternalId} in workspace ${workspaceId}`, - ); - } - - const historyId = firstMessageContent?.data?.historyId; - - if (!historyId) { - throw new Error( - `No historyId found for message ${firstMessageExternalId} in workspace ${workspaceId}`, - ); - } - - this.logger.log( - `Updating last external id: ${historyId} for workspace ${workspaceId} and account ${messageChannelId} succeeded.`, - ); - - await this.messageChannelRepository.updateLastSyncCursorIfHigher( - messageChannelId, - historyId, - workspaceId, - transactionManager, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module.ts deleted file mode 100644 index 6aef6fcd29336..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -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 { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; -import { GmailMessagesImportV2Service } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service'; -import { GmailMessagesImportService } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service'; -import { SaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module'; -import { MessageModule } from 'src/modules/messaging/services/message/message.module'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - FetchMessagesByBatchesModule, - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - ]), - MessageModule, - WorkspaceDataSourceModule, - MessageModule, - MessageParticipantModule, - SetMessageChannelSyncStatusModule, - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - GmailErrorHandlingModule, - GoogleAPIRefreshAccessTokenModule, - MessagingTelemetryModule, - ], - providers: [ - GmailMessagesImportService, - GmailMessagesImportV2Service, - SaveMessagesAndEnqueueContactCreationService, - ], - exports: [GmailMessagesImportService, GmailMessagesImportV2Service], -}) -export class GmailMessagesImportModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service.ts b/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service.ts deleted file mode 100644 index 788d653913750..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service.ts +++ /dev/null @@ -1,320 +0,0 @@ -import { Inject, Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { EntityManager, Repository } from 'typeorm'; - -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -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 { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util'; -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 { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant'; -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { - GmailFullMessageListFetchJobData, - GmailFullMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { GMAIL_ONGOING_SYNC_TIMEOUT } from 'src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; -import { MessageService } from 'src/modules/messaging/services/message/message.service'; -import { ParticipantWithMessageId } from 'src/modules/messaging/types/gmail-message'; -import { - CreateCompanyAndContactJobData, - CreateCompanyAndContactJob, -} from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/create-company-and-contact.job'; -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; - -@Injectable() -export class GmailMessagesImportService { - private readonly logger = new Logger(GmailMessagesImportService.name); - - constructor( - private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - @InjectCacheStorage(CacheStorageNamespace.Messaging) - private readonly cacheStorage: CacheStorageService, - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - @Inject(MessageQueue.messagingQueue) - private readonly messageQueueService: MessageQueueService, - private readonly messageService: MessageService, - private readonly messageParticipantService: MessageParticipantService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - ) {} - - async fetchMessageContentFromCache( - workspaceId: string, - connectedAccountId: string, - ) { - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - this.logger.error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - - return; - } - - const { accessToken, refreshToken, authFailedAt } = connectedAccount; - - if (authFailedAt) { - this.logger.error( - `Connected account ${connectedAccountId} in workspace ${workspaceId} is in a failed state. Skipping...`, - ); - - return; - } - - if (!refreshToken) { - throw new Error( - `No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - const gmailMessageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!gmailMessageChannel) { - this.logger.error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - - return; - } - - if (gmailMessageChannel.syncStatus !== MessageChannelSyncStatus.PENDING) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} is not pending.`, - ); - - if (gmailMessageChannel.syncStatus !== MessageChannelSyncStatus.ONGOING) { - return; - } - - const ongoingSyncStartedAt = new Date( - gmailMessageChannel.ongoingSyncStartedAt, - ); - - if ( - ongoingSyncStartedAt < new Date(Date.now() - GMAIL_ONGOING_SYNC_TIMEOUT) - ) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} failed due to ongoing sync timeout. Restarting full-sync...`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - await this.fallbackToFullSync(workspaceId, connectedAccountId); - - return; - } - - return; - } - - const gmailMessageChannelId = gmailMessageChannel.id; - - const messageIdsToFetch = - (await this.cacheStorage.setPop( - `messages-to-import:${workspaceId}:gmail:${gmailMessageChannelId}`, - GMAIL_USERS_MESSAGES_GET_BATCH_SIZE, - )) ?? []; - - if (!messageIdsToFetch?.length) { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.SUCCEEDED, - workspaceId, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} done with nothing to import or delete.`, - ); - - return; - } - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.ONGOING, - workspaceId, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} starting...`, - ); - - const workspaceDataSource = - await this.workspaceDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); - - const messageQueries = createQueriesFromMessageIds(messageIdsToFetch); - - const isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled, - value: true, - }); - - const isContactCreationForSentAndReceivedEmailsEnabled = - isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag?.value; - - try { - const messagesToSave = - await this.fetchMessagesByBatchesService.fetchAllMessages( - messageQueries, - accessToken, - workspaceId, - connectedAccountId, - ); - - const participantsWithMessageId = await workspaceDataSource?.transaction( - async (transactionManager: EntityManager) => { - if (!messagesToSave.length) { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.PENDING, - workspaceId, - ); - - return []; - } - - const messageExternalIdsAndIdsMap = - await this.messageService.saveMessagesWithinTransaction( - messagesToSave, - connectedAccount, - gmailMessageChannel.id, - workspaceId, - transactionManager, - ); - - const participantsWithMessageId: (ParticipantWithMessageId & { - shouldCreateContact: boolean; - })[] = messagesToSave.flatMap((message) => { - const messageId = messageExternalIdsAndIdsMap.get( - message.externalId, - ); - - return messageId - ? message.participants.map((participant) => ({ - ...participant, - messageId, - shouldCreateContact: - gmailMessageChannel.isContactAutoCreationEnabled && - (isContactCreationForSentAndReceivedEmailsEnabled || - message.participants.find((p) => p.role === 'from') - ?.handle === connectedAccount.handle), - })) - : []; - }); - - await this.messageParticipantService.saveMessageParticipants( - participantsWithMessageId, - workspaceId, - transactionManager, - ); - - if (messageIdsToFetch.length < GMAIL_USERS_MESSAGES_GET_BATCH_SIZE) { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.SUCCEEDED, - workspaceId, - transactionManager, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} done with no more messages to import.`, - ); - } else { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} done with more messages to import.`, - ); - } - - return participantsWithMessageId; - }, - ); - - if (gmailMessageChannel.isContactAutoCreationEnabled) { - const contactsToCreate = participantsWithMessageId.filter( - (participant) => participant.shouldCreateContact, - ); - - await this.messageQueueService.add( - CreateCompanyAndContactJob.name, - { - workspaceId, - connectedAccountHandle: connectedAccount.handle, - contactsToCreate, - }, - ); - } - } catch (error) { - await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${gmailMessageChannelId}`, - messageIdsToFetch, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - this.logger.error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: locking for ${GMAIL_ONGOING_SYNC_TIMEOUT}ms...`, - ); - - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - } - } - - private async fallbackToFullSync( - workspaceId: string, - connectedAccountId: string, - ) { - await this.messageQueueService.add( - GmailFullMessageListFetchJob.name, - { workspaceId, connectedAccountId }, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module.ts deleted file mode 100644 index cd0a0c31f9ca7..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -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 { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; -import { GmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service'; -import { GmailGetHistoryService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service'; -import { GmailPartialMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service'; -import { GmailPartialMessageListFetchService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessageModule } from 'src/modules/messaging/services/message/message.module'; -import { MessagingProvidersModule } from 'src/modules/messaging/services/providers/messaging-providers.module'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - MessagingProvidersModule, - FetchMessagesByBatchesModule, - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - BlocklistWorkspaceEntity, - ]), - MessageModule, - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - WorkspaceDataSourceModule, - SetMessageChannelSyncStatusModule, - GmailErrorHandlingModule, - ], - providers: [ - GmailPartialMessageListFetchService, - GmailPartialMessageListFetchV2Service, - GmailGetHistoryService, - GmailFetchMessageIdsToExcludeService, - ], - exports: [ - GmailPartialMessageListFetchService, - GmailPartialMessageListFetchV2Service, - ], -}) -export class GmailPartialMessageListFetchModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service.ts deleted file mode 100644 index 779c6d6f3670e..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service.ts +++ /dev/null @@ -1,347 +0,0 @@ -import { Inject, Injectable, Logger } from '@nestjs/common'; - -import { gmail_v1 } from 'googleapis'; -import { EntityManager } from 'typeorm'; - -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { GMAIL_USERS_HISTORY_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-history-max-result.constant'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -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 { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { - GmailFullMessageListFetchJob, - GmailFullMessageListFetchJobData, -} from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; - -@Injectable() -export class GmailPartialMessageListFetchService { - private readonly logger = new Logger( - GmailPartialMessageListFetchService.name, - ); - - constructor( - private readonly gmailClientProvider: GmailClientProvider, - @Inject(MessageQueue.messagingQueue) - private readonly messageQueueService: MessageQueueService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - @InjectCacheStorage(CacheStorageNamespace.Messaging) - private readonly cacheStorage: CacheStorageService, - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - @InjectObjectMetadataRepository( - MessageChannelMessageAssociationWorkspaceEntity, - ) - private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - ) {} - - public async fetchConnectedAccountThreads( - workspaceId: string, - connectedAccountId: string, - ): Promise { - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - this.logger.error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - - return; - } - - const refreshToken = connectedAccount.refreshToken; - - if (!refreshToken) { - throw new Error( - `No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - const gmailMessageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!gmailMessageChannel) { - this.logger.error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - - return; - } - - if (gmailMessageChannel.syncStatus !== MessageChannelSyncStatus.SUCCEEDED) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} is locked, import will be retried later.`, - ); - - return; - } - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.ONGOING, - workspaceId, - ); - - const workspaceDataSource = - await this.workspaceDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); - - await workspaceDataSource - ?.transaction(async (transactionManager: EntityManager) => { - const lastSyncHistoryId = gmailMessageChannel.syncCursor; - - if (!lastSyncHistoryId) { - this.logger.log( - `No lastSyncHistoryId for workspace ${workspaceId} and account ${connectedAccountId}, falling back to full sync.`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - await this.fallbackToFullSync(workspaceId, connectedAccountId); - - return; - } - - const gmailClient: gmail_v1.Gmail = - await this.gmailClientProvider.getGmailClient(refreshToken); - - const { history, historyId, error } = await this.getHistoryFromGmail( - gmailClient, - lastSyncHistoryId, - ); - - if (error?.code === 404) { - this.logger.log( - `404: Invalid lastSyncHistoryId: ${lastSyncHistoryId} for workspace ${workspaceId} and account ${connectedAccountId}, falling back to full sync.`, - ); - - await this.messageChannelRepository.resetSyncCursor( - gmailMessageChannel.id, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - await this.fallbackToFullSync(workspaceId, connectedAccountId); - - return; - } - - if (error?.code === 429) { - this.logger.log( - `429: rate limit reached for workspace ${workspaceId} and account ${connectedAccountId}: ${error.message}, import will be retried later.`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - return; - } - - if (error) { - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - } - - if (!historyId) { - throw new Error( - `No historyId found for ${connectedAccountId} in workspace ${workspaceId} in gmail history response.`, - ); - } - - if (historyId === lastSyncHistoryId || !history?.length) { - this.logger.log( - `Messaging import done with history ${historyId} and nothing to update for workspace ${workspaceId} and account ${connectedAccountId}`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - ); - - return; - } - - const { messagesAdded, messagesDeleted } = - await this.getMessageIdsFromHistory(history); - - await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${gmailMessageChannel.id}`, - messagesAdded, - ); - - await this.messageChannelMessageAssociationRepository.deleteByMessageExternalIdsAndMessageChannelId( - messagesDeleted, - gmailMessageChannel.id, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateLastSyncCursorIfHigher( - gmailMessageChannel.id, - historyId, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - }) - .catch(async (error) => { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - }); - } - - private async getMessageIdsFromHistory( - history: gmail_v1.Schema$History[], - ): Promise<{ - messagesAdded: string[]; - messagesDeleted: string[]; - }> { - const { messagesAdded, messagesDeleted } = history.reduce( - ( - acc: { - messagesAdded: string[]; - messagesDeleted: string[]; - }, - history, - ) => { - const messagesAdded = history.messagesAdded?.map( - (messageAdded) => messageAdded.message?.id || '', - ); - - const messagesDeleted = history.messagesDeleted?.map( - (messageDeleted) => messageDeleted.message?.id || '', - ); - - if (messagesAdded) acc.messagesAdded.push(...messagesAdded); - if (messagesDeleted) acc.messagesDeleted.push(...messagesDeleted); - - return acc; - }, - { messagesAdded: [], messagesDeleted: [] }, - ); - - const uniqueMessagesAdded = messagesAdded.filter( - (messageId) => !messagesDeleted.includes(messageId), - ); - - const uniqueMessagesDeleted = messagesDeleted.filter( - (messageId) => !messagesAdded.includes(messageId), - ); - - return { - messagesAdded: uniqueMessagesAdded, - messagesDeleted: uniqueMessagesDeleted, - }; - } - - private async getHistoryFromGmail( - gmailClient: gmail_v1.Gmail, - lastSyncHistoryId: string, - ): Promise<{ - history: gmail_v1.Schema$History[]; - historyId?: string | null; - error?: any; - }> { - const fullHistory: gmail_v1.Schema$History[] = []; - let pageToken: string | undefined; - let hasMoreMessages = true; - let nextHistoryId: string | undefined; - - while (hasMoreMessages) { - try { - const response = await gmailClient.users.history.list({ - userId: 'me', - maxResults: GMAIL_USERS_HISTORY_MAX_RESULT, - pageToken, - startHistoryId: lastSyncHistoryId, - historyTypes: ['messageAdded', 'messageDeleted'], - }); - - nextHistoryId = response?.data?.historyId ?? undefined; - - if (response?.data?.history) { - fullHistory.push(...response.data.history); - } - - pageToken = response?.data?.nextPageToken ?? undefined; - hasMoreMessages = !!pageToken; - } catch (error) { - const errorData = error?.response?.data?.error; - - if (errorData) { - return { - history: [], - error: errorData, - historyId: lastSyncHistoryId, - }; - } - - throw error; - } - } - - return { history: fullHistory, historyId: nextHistoryId }; - } - - private async fallbackToFullSync( - workspaceId: string, - connectedAccountId: string, - ) { - await this.messageQueueService.add( - GmailFullMessageListFetchJob.name, - { workspaceId, connectedAccountId }, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module.ts b/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module.ts deleted file mode 100644 index 42e350d074c9b..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([MessageChannelWorkspaceEntity]), - ], - providers: [MessageChannelSyncStatusService], - exports: [MessageChannelSyncStatusService], -}) -export class SetMessageChannelSyncStatusModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.module.ts b/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.module.ts deleted file mode 100644 index 907ae76ec16de..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Module } from '@nestjs/common'; - -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 { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; -import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; - -@Module({ - imports: [ - WorkspaceDataSourceModule, - ObjectMetadataRepositoryModule.forFeature([ - PersonWorkspaceEntity, - MessageParticipantWorkspaceEntity, - ]), - AddPersonIdAndWorkspaceMemberIdModule, - ], - providers: [MessageParticipantService], - exports: [MessageParticipantService], -}) -export class MessageParticipantModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.module.ts b/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.module.ts deleted file mode 100644 index eb7cbd7489613..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { MessageThreadService } from 'src/modules/messaging/services/message-thread/message-thread.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - MessageChannelMessageAssociationWorkspaceEntity, - MessageWorkspaceEntity, - MessageThreadWorkspaceEntity, - ]), - ], - providers: [MessageThreadService], - exports: [MessageThreadService], -}) -export class MessageThreadModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/message/message.module.ts b/packages/twenty-server/src/modules/messaging/services/message/message.module.ts deleted file mode 100644 index 8bfa2b6d58842..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/message/message.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; -import { MessageThreadModule } from 'src/modules/messaging/services/message-thread/message-thread.module'; -import { MessageService } from 'src/modules/messaging/services/message/message.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; - -@Module({ - imports: [ - WorkspaceDataSourceModule, - ObjectMetadataRepositoryModule.forFeature([ - MessageChannelMessageAssociationWorkspaceEntity, - MessageWorkspaceEntity, - MessageChannelWorkspaceEntity, - MessageThreadWorkspaceEntity, - ]), - MessageThreadModule, - ], - providers: [MessageService], - exports: [MessageService], -}) -export class MessageModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/providers/messaging-providers.module.ts b/packages/twenty-server/src/modules/messaging/services/providers/messaging-providers.module.ts deleted file mode 100644 index fc0cb1c178d9a..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/providers/messaging-providers.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; - -@Module({ - imports: [EnvironmentModule], - providers: [GmailClientProvider], - exports: [GmailClientProvider], -}) -export class MessagingProvidersModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.module.ts b/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.module.ts deleted file mode 100644 index f5bd69370a5e3..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; - -@Module({ - imports: [AnalyticsModule], - providers: [MessagingTelemetryService], - exports: [MessagingTelemetryService], -}) -export class MessagingTelemetryModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.module.ts b/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.module.ts deleted file mode 100644 index 6305b55a3a44f..0000000000000 --- a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - MessageWorkspaceEntity, - MessageThreadWorkspaceEntity, - ]), - ], - providers: [ThreadCleanerService], - exports: [ThreadCleanerService], -}) -export class ThreadCleanerModule {} diff --git a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts index 23b5c33adf119..83353993dfb14 100644 --- a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts +++ b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts @@ -14,7 +14,6 @@ import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objec import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; @@ -23,6 +22,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, diff --git a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts index 1a5f77e4bb9ea..17378a598f60a 100644 --- a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts @@ -16,7 +16,6 @@ import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/co import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; import { AuditLogWorkspaceEntity } from 'src/modules/timeline/standard-objects/audit-log.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; @@ -26,6 +25,7 @@ import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/work import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.workspaceMember,