4710 implement google calendar incremental sync (#4822)

Closes #4710
This commit is contained in:
bosiraphael
2024-04-10 15:53:14 +02:00
committed by GitHub
parent f1cc1c60e0
commit e7d146363c
20 changed files with 333 additions and 152 deletions

View File

@ -0,0 +1,82 @@
import { Injectable } 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 {
FeatureFlagEntity,
FeatureFlagKeys,
} 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 { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository';
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata';
import { GoogleCalendarSyncService } from 'src/modules/calendar/services/google-calendar-sync.service';
@Injectable()
export class GoogleCalendarSyncCronJob implements MessageQueueJob<undefined> {
constructor(
@InjectRepository(Workspace, 'core')
private readonly workspaceRepository: Repository<Workspace>,
@InjectRepository(DataSourceEntity, 'metadata')
private readonly dataSourceRepository: Repository<DataSourceEntity>,
@InjectObjectMetadataRepository(CalendarChannelObjectMetadata)
private readonly calendarChannelRepository: CalendarChannelRepository,
@InjectRepository(FeatureFlagEntity, 'core')
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
private readonly googleCalendarSyncService: GoogleCalendarSyncService,
) {}
async handle(): Promise<void> {
const workspaceIds = (
await this.workspaceRepository.find({
where: {
subscriptionStatus: 'active',
},
select: ['id'],
})
).map((workspace) => workspace.id);
const workspacesWithFeatureFlagActive =
await this.featureFlagRepository.find({
where: {
workspaceId: In(workspaceIds),
key: FeatureFlagKeys.IsCalendarEnabled,
value: true,
},
});
const dataSources = await this.dataSourceRepository.find({
where: {
workspaceId: In(
workspacesWithFeatureFlagActive.map((w) => w.workspaceId),
),
},
});
const workspaceIdsWithDataSources = new Set(
dataSources.map((dataSource) => dataSource.workspaceId),
);
for (const workspaceId of workspaceIdsWithDataSources) {
await this.startWorkspaceGoogleCalendarSync(workspaceId);
}
}
private async startWorkspaceGoogleCalendarSync(
workspaceId: string,
): Promise<void> {
const calendarChannels =
await this.calendarChannelRepository.getAll(workspaceId);
for (const calendarChannel of calendarChannels) {
await this.googleCalendarSyncService.startGoogleCalendarSync(
workspaceId,
calendarChannel.connectedAccountId,
);
}
}
}

View File

@ -0,0 +1 @@
export const googleCalendarSyncCronPattern = '*/5 * * * *';

View File

@ -3,32 +3,27 @@ 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 { GoogleCalendarFullSyncService } from 'src/modules/calendar/services/google-calendar-full-sync.service';
import { GoogleCalendarSyncService } from 'src/modules/calendar/services/google-calendar-sync.service';
export type GoogleCalendarFullSyncJobData = {
export type GoogleCalendarSyncJobData = {
workspaceId: string;
connectedAccountId: string;
nextPageToken?: string;
};
@Injectable()
export class GoogleCalendarFullSyncJob
implements MessageQueueJob<GoogleCalendarFullSyncJobData>
export class GoogleCalendarSyncJob
implements MessageQueueJob<GoogleCalendarSyncJobData>
{
private readonly logger = new Logger(GoogleCalendarFullSyncJob.name);
private readonly logger = new Logger(GoogleCalendarSyncJob.name);
constructor(
private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService,
private readonly googleCalendarFullSyncService: GoogleCalendarFullSyncService,
private readonly googleCalendarSyncService: GoogleCalendarSyncService,
) {}
async handle(data: GoogleCalendarFullSyncJobData): Promise<void> {
async handle(data: GoogleCalendarSyncJobData): Promise<void> {
this.logger.log(
`google calendar full-sync for workspace ${
data.workspaceId
} and account ${data.connectedAccountId} ${
data.nextPageToken ? `and ${data.nextPageToken} pageToken` : ''
}`,
`google calendar sync for workspace ${data.workspaceId} and account ${data.connectedAccountId}`,
);
try {
await this.googleAPIsRefreshAccessTokenService.refreshAndSaveAccessToken(
@ -44,10 +39,9 @@ export class GoogleCalendarFullSyncJob
return;
}
await this.googleCalendarFullSyncService.startGoogleCalendarFullSync(
await this.googleCalendarSyncService.startGoogleCalendarSync(
data.workspaceId,
data.connectedAccountId,
data.nextPageToken,
);
}
}