Reorganise calendar module (#6089)

Refactor Calendar into functional sub modules
<img width="437" alt="image"
src="https://github.com/twentyhq/twenty/assets/12035771/d9de3285-a226-4fe8-b3ef-2d8a21def2a5">

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
This commit is contained in:
Charles Bochet
2024-07-02 13:55:11 +02:00
committed by GitHub
parent ea7d52fba8
commit f8dd2cc733
66 changed files with 267 additions and 401 deletions

View File

@ -0,0 +1,18 @@
import { Module } from '@nestjs/common';
import { BlocklistItemDeleteCalendarEventsJob } from 'src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job';
import { BlocklistReimportCalendarEventsJob } from 'src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job';
import { CalendarBlocklistListener } from 'src/modules/calendar/blocklist-manager/listeners/calendar-blocklist.listener';
import { CalendarEventCleanerModule } from 'src/modules/calendar/calendar-event-cleaner/calendar-event-cleaner.module';
import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module';
@Module({
imports: [CalendarEventCleanerModule, CalendarEventImportManagerModule],
providers: [
CalendarBlocklistListener,
BlocklistItemDeleteCalendarEventsJob,
BlocklistReimportCalendarEventsJob,
],
exports: [],
})
export class CalendarBlocklistManagerModule {}

View File

@ -0,0 +1,101 @@
import { Logger, Scope } from '@nestjs/common';
import { Any, ILike } from 'typeorm';
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { 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 { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
import { CalendarEventCleanerService } from 'src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service';
import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
export type BlocklistItemDeleteCalendarEventsJobData = {
workspaceId: string;
blocklistItemId: string;
};
@Processor({
queueName: MessageQueue.calendarQueue,
scope: Scope.REQUEST,
})
export class BlocklistItemDeleteCalendarEventsJob {
private readonly logger = new Logger(
BlocklistItemDeleteCalendarEventsJob.name,
);
constructor(
@InjectWorkspaceRepository(CalendarChannelWorkspaceEntity)
private readonly calendarChannelRepository: WorkspaceRepository<CalendarChannelWorkspaceEntity>,
@InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity)
private readonly calendarChannelEventAssociationRepository: WorkspaceRepository<CalendarChannelEventAssociationWorkspaceEntity>,
@InjectObjectMetadataRepository(BlocklistWorkspaceEntity)
private readonly blocklistRepository: BlocklistRepository,
private readonly calendarEventCleanerService: CalendarEventCleanerService,
) {}
@Process(BlocklistItemDeleteCalendarEventsJob.name)
async handle(data: BlocklistItemDeleteCalendarEventsJobData): Promise<void> {
const { workspaceId, blocklistItemId } = data;
const blocklistItem = await this.blocklistRepository.getById(
blocklistItemId,
workspaceId,
);
if (!blocklistItem) {
this.logger.log(
`Blocklist item with id ${blocklistItemId} not found in workspace ${workspaceId}`,
);
return;
}
const { handle, workspaceMemberId } = blocklistItem;
this.logger.log(
`Deleting calendar events from ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`,
);
if (!workspaceMemberId) {
throw new Error(
`Workspace member ID is undefined for blocklist item ${blocklistItemId} in workspace ${workspaceId}`,
);
}
const calendarChannels = await this.calendarChannelRepository.find({
where: {
connectedAccount: {
accountOwnerId: workspaceMemberId,
},
},
});
const calendarChannelIds = calendarChannels.map(({ id }) => id);
const isHandleDomain = handle.startsWith('@');
await this.calendarChannelEventAssociationRepository.delete({
calendarEvent: {
calendarEventParticipants: {
handle: isHandleDomain ? ILike(`%${handle}`) : handle,
},
calendarChannelEventAssociations: {
calendarChannelId: Any(calendarChannelIds),
},
},
});
await this.calendarEventCleanerService.cleanWorkspaceCalendarEvents(
workspaceId,
);
this.logger.log(
`Deleted calendar events from handle ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`,
);
}
}

View File

@ -0,0 +1,62 @@
import { Logger, Scope } from '@nestjs/common';
import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { 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 { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator';
import { CalendarEventsImportService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service';
export type BlocklistReimportCalendarEventsJobData = {
workspaceId: string;
workspaceMemberId: string;
handle: string;
};
@Processor({
queueName: MessageQueue.calendarQueue,
scope: Scope.REQUEST,
})
export class BlocklistReimportCalendarEventsJob {
private readonly logger = new Logger(BlocklistReimportCalendarEventsJob.name);
constructor(
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
private readonly connectedAccountRepository: ConnectedAccountRepository,
private readonly googleCalendarSyncService: CalendarEventsImportService,
) {}
@Process(BlocklistReimportCalendarEventsJob.name)
async handle(data: BlocklistReimportCalendarEventsJobData): Promise<void> {
const { workspaceId, workspaceMemberId, handle } = data;
this.logger.log(
`Reimporting calendar events from handle ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId}`,
);
const connectedAccount =
await this.connectedAccountRepository.getAllByWorkspaceMemberId(
workspaceMemberId,
workspaceId,
);
if (!connectedAccount || connectedAccount.length === 0) {
this.logger.error(
`No connected account found for workspace member ${workspaceMemberId} in workspace ${workspaceId}`,
);
return;
}
await this.googleCalendarSyncService.processCalendarEventsImport(
workspaceId,
connectedAccount[0].id,
handle,
);
this.logger.log(
`Reimporting calendar events from ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId} done`,
);
}
}

View File

@ -0,0 +1,75 @@
import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event';
import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event';
import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event';
import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
import {
BlocklistItemDeleteCalendarEventsJobData,
BlocklistItemDeleteCalendarEventsJob,
} from 'src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job';
import {
BlocklistReimportCalendarEventsJobData,
BlocklistReimportCalendarEventsJob,
} from 'src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job';
import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity';
@Injectable()
export class CalendarBlocklistListener {
constructor(
@InjectMessageQueue(MessageQueue.calendarQueue)
private readonly messageQueueService: MessageQueueService,
) {}
@OnEvent('blocklist.created')
async handleCreatedEvent(
payload: ObjectRecordCreateEvent<BlocklistWorkspaceEntity>,
) {
await this.messageQueueService.add<BlocklistItemDeleteCalendarEventsJobData>(
BlocklistItemDeleteCalendarEventsJob.name,
{
workspaceId: payload.workspaceId,
blocklistItemId: payload.recordId,
},
);
}
@OnEvent('blocklist.deleted')
async handleDeletedEvent(
payload: ObjectRecordDeleteEvent<BlocklistWorkspaceEntity>,
) {
await this.messageQueueService.add<BlocklistReimportCalendarEventsJobData>(
BlocklistReimportCalendarEventsJob.name,
{
workspaceId: payload.workspaceId,
workspaceMemberId: payload.properties.before.workspaceMember.id,
handle: payload.properties.before.handle,
},
);
}
@OnEvent('blocklist.updated')
async handleUpdatedEvent(
payload: ObjectRecordUpdateEvent<BlocklistWorkspaceEntity>,
) {
await this.messageQueueService.add<BlocklistItemDeleteCalendarEventsJobData>(
BlocklistItemDeleteCalendarEventsJob.name,
{
workspaceId: payload.workspaceId,
blocklistItemId: payload.recordId,
},
);
await this.messageQueueService.add<BlocklistReimportCalendarEventsJobData>(
BlocklistReimportCalendarEventsJob.name,
{
workspaceId: payload.workspaceId,
workspaceMemberId: payload.properties.after.workspaceMember.id,
handle: payload.properties.before.handle,
},
);
}
}