Fix cron module structure (#4933)
This PR introduces a new folder structure for business modules. Cron commands and jobs are now stored within the same module/folder at the root of the business module e.g: /modules/messaging/crons/commands instead of /modules/messaging/commands/crons Patterns are now inside their own cron-command files since they don't need to be exported Ideally cronJobs and cronCommands should have their logic within the same class but it's a bit harder than expected due to how commanderjs and our worker need both some class heritage check, hence the first approach is to move them in the same folder Also Messaging fullsync/partialsync V2 has been dropped since this is the only used version => Breaking change for ongoing jobs and crons. Jobs can be dropped but we will need to re-run our crons (only cron:messaging:gmail-fetch-messages-from-cache)
This commit is contained in:
@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { GoogleCalendarSyncCommand } from 'src/modules/calendar/commands/google-calendar-sync.command';
|
||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata';
|
||||
import { GoogleCalendarSyncCronCommand } from 'src/modules/calendar/crons/commands/google-calendar-sync.cron.command';
|
||||
|
||||
@Module({
|
||||
providers: [GoogleCalendarSyncCronCommand],
|
||||
})
|
||||
export class CalendarCronCommandsModule {}
|
||||
@ -0,0 +1,32 @@
|
||||
import { Inject } from '@nestjs/common';
|
||||
|
||||
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 { GoogleCalendarSyncCronJob } from 'src/modules/calendar/crons/jobs/google-calendar-sync.cron.job';
|
||||
|
||||
const GOOGLE_CALENDAR_SYNC_CRON_PATTERN = '*/5 * * * *';
|
||||
|
||||
@Command({
|
||||
name: 'cron:calendar:google-calendar-sync',
|
||||
description: 'Starts a cron job to sync google calendar for all workspaces.',
|
||||
})
|
||||
export class GoogleCalendarSyncCronCommand extends CommandRunner {
|
||||
constructor(
|
||||
@Inject(MessageQueue.cronQueue)
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
await this.messageQueueService.addCron<undefined>(
|
||||
GoogleCalendarSyncCronJob.name,
|
||||
undefined,
|
||||
{
|
||||
repeat: { pattern: GOOGLE_CALENDAR_SYNC_CRON_PATTERN },
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user