Message channel change 1 (#14942)

This commit is contained in:
neo773
2025-10-11 21:48:44 +05:30
committed by GitHub
parent 560e24fa4b
commit 6f49fd1911
33 changed files with 1124 additions and 90 deletions
@@ -35,6 +35,7 @@ export enum CalendarChannelSyncStatus {
}
export enum CalendarChannelSyncStage {
PENDING_CONFIGURATION = 'PENDING_CONFIGURATION',
FULL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'FULL_CALENDAR_EVENT_LIST_FETCH_PENDING', // WILL BE DEPRECATED
PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING = 'PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING', // DEPRECATED
CALENDAR_EVENT_LIST_FETCH_PENDING = 'CALENDAR_EVENT_LIST_FETCH_PENDING',
@@ -194,8 +195,14 @@ export class CalendarChannelWorkspaceEntity extends BaseWorkspaceEntity {
position: 8,
color: 'blue',
},
{
value: CalendarChannelSyncStage.PENDING_CONFIGURATION,
label: 'Pending configuration',
position: 9,
color: 'gray',
},
],
defaultValue: `'${CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING}'`,
defaultValue: `'${CalendarChannelSyncStage.PENDING_CONFIGURATION}'`,
})
syncStage: CalendarChannelSyncStage;
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
import { ChannelSyncResolver } from 'src/modules/connected-account/channel-sync/channel-sync.resolver';
import { ChannelSyncService } from 'src/modules/connected-account/channel-sync/services/channel-sync.service';
@Module({
imports: [WorkspaceDataSourceModule],
providers: [ChannelSyncResolver, ChannelSyncService],
exports: [ChannelSyncService],
})
export class ChannelSyncModule {}
@@ -0,0 +1,33 @@
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { ChannelSyncSuccess } from 'src/modules/connected-account/channel-sync/dtos/channel-sync-success.dto';
import { ChannelSyncService } from 'src/modules/connected-account/channel-sync/services/channel-sync.service';
@Resolver()
@UsePipes(ResolverValidationPipe)
@UseFilters(AuthGraphqlApiExceptionFilter)
@UseGuards(WorkspaceAuthGuard)
export class ChannelSyncResolver {
constructor(private readonly channelSyncService: ChannelSyncService) {}
@Mutation(() => ChannelSyncSuccess)
async startChannelSync(
@Args('connectedAccountId', { type: () => UUIDScalarType })
connectedAccountId: string,
@AuthWorkspace() workspace: Workspace,
): Promise<ChannelSyncSuccess> {
await this.channelSyncService.startChannelSync({
connectedAccountId,
workspaceId: workspace.id,
});
return { success: true };
}
}
@@ -0,0 +1,7 @@
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType()
export class ChannelSyncSuccess {
@Field(() => Boolean)
success: boolean;
}
@@ -0,0 +1,113 @@
import { Injectable } from '@nestjs/common';
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import {
CalendarEventListFetchJob,
type CalendarEventListFetchJobData,
} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job';
import {
CalendarChannelSyncStage,
CalendarChannelSyncStatus,
type CalendarChannelWorkspaceEntity,
} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import {
MessageChannelSyncStage,
MessageChannelSyncStatus,
type MessageChannelWorkspaceEntity,
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import {
MessagingMessageListFetchJob,
type MessagingMessageListFetchJobData,
} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job';
export type StartChannelSyncInput = {
connectedAccountId: string;
workspaceId: string;
};
@Injectable()
export class ChannelSyncService {
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
@InjectMessageQueue(MessageQueue.messagingQueue)
private readonly messageQueueService: MessageQueueService,
@InjectMessageQueue(MessageQueue.calendarQueue)
private readonly calendarQueueService: MessageQueueService,
) {}
async startChannelSync(input: StartChannelSyncInput): Promise<void> {
const { connectedAccountId, workspaceId } = input;
await this.startMessageChannelSync(connectedAccountId, workspaceId);
await this.startCalendarChannelSync(connectedAccountId, workspaceId);
}
private async startMessageChannelSync(
connectedAccountId: string,
workspaceId: string,
): Promise<void> {
const messageChannelRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>(
workspaceId,
'messageChannel',
);
const messageChannels = await messageChannelRepository.find({
where: {
connectedAccountId,
syncStage: MessageChannelSyncStage.PENDING_CONFIGURATION,
},
});
for (const messageChannel of messageChannels) {
await this.messageQueueService.add<MessagingMessageListFetchJobData>(
MessagingMessageListFetchJob.name,
{
workspaceId,
messageChannelId: messageChannel.id,
},
);
await messageChannelRepository.update(messageChannel.id, {
syncStage: MessageChannelSyncStage.MESSAGE_LIST_FETCH_PENDING,
syncStatus: MessageChannelSyncStatus.ONGOING,
});
}
}
private async startCalendarChannelSync(
connectedAccountId: string,
workspaceId: string,
): Promise<void> {
const calendarChannelRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<CalendarChannelWorkspaceEntity>(
workspaceId,
'calendarChannel',
);
const calendarChannels = await calendarChannelRepository.find({
where: {
connectedAccountId,
syncStage: CalendarChannelSyncStage.PENDING_CONFIGURATION,
},
});
for (const calendarChannel of calendarChannels) {
await this.calendarQueueService.add<CalendarEventListFetchJobData>(
CalendarEventListFetchJob.name,
{
calendarChannelId: calendarChannel.id,
workspaceId,
},
);
await calendarChannelRepository.update(calendarChannel.id, {
syncStage: CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_SCHEDULED,
syncStatus: CalendarChannelSyncStatus.ONGOING,
});
}
}
}
@@ -46,7 +46,7 @@ export class ImapSmtpCalDavAPIService {
workspaceId: string;
connectionParameters: EmailAccountConnectionParameters;
connectedAccountId?: string;
}) {
}): Promise<string> {
const { handle, workspaceId, workspaceMemberId, connectedAccountId } =
input;
@@ -125,6 +125,8 @@ export class ImapSmtpCalDavAPIService {
messageChannel,
calendarChannel,
);
return accountId;
}
private async upsertConnectedAccount(
@@ -31,6 +31,7 @@ export enum MessageChannelSyncStatus {
}
export enum MessageChannelSyncStage {
PENDING_CONFIGURATION = 'PENDING_CONFIGURATION',
FULL_MESSAGE_LIST_FETCH_PENDING = 'FULL_MESSAGE_LIST_FETCH_PENDING', // WILL BE DEPRECATED
PARTIAL_MESSAGE_LIST_FETCH_PENDING = 'PARTIAL_MESSAGE_LIST_FETCH_PENDING', // DEPRECATED
MESSAGE_LIST_FETCH_PENDING = 'MESSAGE_LIST_FETCH_PENDING',
@@ -380,8 +381,14 @@ export class MessageChannelWorkspaceEntity extends BaseWorkspaceEntity {
position: 8,
color: 'blue',
},
{
value: MessageChannelSyncStage.PENDING_CONFIGURATION,
label: 'Pending configuration',
position: 9,
color: 'gray',
},
],
defaultValue: `'${MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING}'`,
defaultValue: `'${MessageChannelSyncStage.PENDING_CONFIGURATION}'`,
})
syncStage: MessageChannelSyncStage;