Add cron trigger table (#14110)
This Pr begins the extensibility journey - adds a `core.cronTrigger` table - add a oneToMany relation between core.serverlessFunction and `core.cronTrigger` (one serverlessFunction can be triggered by multiple cronTriggers) - add a job to trigger a serverless function - adds a cron to trigger serverlessFunction (via the trigger job) based on the core.cronTrigger.setting.pattern - adds a command to register the cron - add the command in `cron-register-all.command.ts`
This commit is contained in:
@@ -14,6 +14,7 @@ import { WorkflowCleanWorkflowRunsCommand } from 'src/modules/workflow/workflow-
|
||||
import { WorkflowHandleStaledRunsCronCommand } from 'src/modules/workflow/workflow-runner/workflow-run-queue/cron/command/workflow-handle-staled-runs.cron.command';
|
||||
import { WorkflowRunEnqueueCronCommand } from 'src/modules/workflow/workflow-runner/workflow-run-queue/cron/command/workflow-run-enqueue.cron.command';
|
||||
import { WorkflowCronTriggerCronCommand } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/commands/workflow-cron-trigger.cron.command';
|
||||
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command';
|
||||
|
||||
@Command({
|
||||
name: 'cron:register:all',
|
||||
@@ -35,6 +36,7 @@ export class CronRegisterAllCommand extends CommandRunner {
|
||||
private readonly workflowRunEnqueueCronCommand: WorkflowRunEnqueueCronCommand,
|
||||
private readonly workflowHandleStaledRunsCronCommand: WorkflowHandleStaledRunsCronCommand,
|
||||
private readonly workflowCleanWorkflowRunsCronCommand: WorkflowCleanWorkflowRunsCommand,
|
||||
private readonly cronTriggerCronCommand: CronTriggerCronCommand,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -91,6 +93,10 @@ export class CronRegisterAllCommand extends CommandRunner {
|
||||
name: 'WorkflowCleanWorkflowRuns',
|
||||
command: this.workflowCleanWorkflowRunsCronCommand,
|
||||
},
|
||||
{
|
||||
name: 'CronTrigger',
|
||||
command: this.cronTriggerCronCommand,
|
||||
},
|
||||
];
|
||||
|
||||
let successCount = 0;
|
||||
|
||||
@@ -21,6 +21,7 @@ import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar-
|
||||
import { MessagingImportManagerModule } from 'src/modules/messaging/message-import-manager/messaging-import-manager.module';
|
||||
import { WorkflowRunQueueModule } from 'src/modules/workflow/workflow-runner/workflow-run-queue/workflow-run-queue.module';
|
||||
import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/automated-trigger/automated-trigger.module';
|
||||
import { TriggerModule } from 'src/engine/metadata-modules/trigger/trigger.module';
|
||||
|
||||
import { DataSeedWorkspaceCommand } from './data-seed-dev-workspace.command';
|
||||
|
||||
@@ -45,6 +46,7 @@ import { DataSeedWorkspaceCommand } from './data-seed-dev-workspace.command';
|
||||
WorkspaceCacheStorageModule,
|
||||
ApiKeyModule,
|
||||
FeatureFlagModule,
|
||||
TriggerModule,
|
||||
],
|
||||
providers: [
|
||||
DataSeedWorkspaceCommand,
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { type MigrationInterface, type QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddCronTriggerEntity1756373902817 implements MigrationInterface {
|
||||
name = 'AddCronTriggerEntity1756373902817';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "core"."cronTrigger" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "settings" jsonb NOT NULL, "workspaceId" uuid NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "serverlessFunctionId" uuid, CONSTRAINT "PK_153e054abdb2663942d4661e3bb" PRIMARY KEY ("id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_CRON_TRIGGER_WORKSPACE_ID" ON "core"."cronTrigger" ("workspaceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."cronTrigger" ADD CONSTRAINT "FK_f70831ec336e0cb42d6a33b80ba" FOREIGN KEY ("serverlessFunctionId") REFERENCES "core"."serverlessFunction"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."cronTrigger" DROP CONSTRAINT "FK_f70831ec336e0cb42d6a33b80ba"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "core"."IDX_CRON_TRIGGER_WORKSPACE_ID"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "core"."cronTrigger"`);
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module
|
||||
import { TimelineActivityModule } from 'src/modules/timeline/timeline-activity.module';
|
||||
import { WebhookJobModule } from 'src/engine/core-modules/webhook/jobs/webhook-job.module';
|
||||
import { WorkflowModule } from 'src/modules/workflow/workflow.module';
|
||||
import { TriggerModule } from 'src/engine/metadata-modules/trigger/trigger.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -60,6 +62,8 @@ import { WorkflowModule } from 'src/modules/workflow/workflow.module';
|
||||
WorkspaceCleanerModule,
|
||||
SubscriptionsModule,
|
||||
AuditJobModule,
|
||||
TriggerModule,
|
||||
ServerlessFunctionModule,
|
||||
],
|
||||
providers: [
|
||||
CleanSuspendedWorkspacesJob,
|
||||
|
||||
+1
@@ -16,4 +16,5 @@ export enum MessageQueue {
|
||||
workflowQueue = 'workflow-queue',
|
||||
deleteCascadeQueue = 'delete-cascade-queue',
|
||||
subscriptionsQueue = 'subscriptions-queue',
|
||||
serverlessFunctionQueue = 'serverless-function-queue',
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { Scope } from '@nestjs/common';
|
||||
|
||||
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
||||
import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service';
|
||||
|
||||
export type ServerlessFunctionTriggerJobData = {
|
||||
serverlessFunctionId: string;
|
||||
workspaceId: string;
|
||||
payload?: object;
|
||||
};
|
||||
|
||||
@Processor({
|
||||
queueName: MessageQueue.serverlessFunctionQueue,
|
||||
scope: Scope.REQUEST,
|
||||
})
|
||||
export class ServerlessFunctionTriggerJob {
|
||||
constructor(
|
||||
private readonly serverlessFunctionService: ServerlessFunctionService,
|
||||
) {}
|
||||
|
||||
@Process(ServerlessFunctionTriggerJob.name)
|
||||
async handle(data: ServerlessFunctionTriggerJobData) {
|
||||
await this.serverlessFunctionService.executeOneServerlessFunction(
|
||||
data.serverlessFunctionId,
|
||||
data.workspaceId,
|
||||
data.payload || {},
|
||||
'draft',
|
||||
);
|
||||
}
|
||||
}
|
||||
+11
@@ -7,9 +7,11 @@ import {
|
||||
Index,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
OneToMany,
|
||||
} from 'typeorm';
|
||||
|
||||
import { InputSchema } from 'src/modules/workflow/workflow-builder/workflow-schema/types/input-schema.type';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity';
|
||||
|
||||
const DEFAULT_SERVERLESS_TIMEOUT_SECONDS = 300; // 5 minutes
|
||||
|
||||
@@ -52,6 +54,15 @@ export class ServerlessFunctionEntity {
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
@OneToMany(
|
||||
() => CronTrigger,
|
||||
(cronTrigger) => cronTrigger.serverlessFunction,
|
||||
{
|
||||
cascade: true,
|
||||
},
|
||||
)
|
||||
cronTriggers: CronTrigger[];
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
|
||||
+6
-1
@@ -12,6 +12,7 @@ import { ThrottlerModule } from 'src/engine/core-modules/throttler/throttler.mod
|
||||
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
import { ServerlessFunctionResolver } from 'src/engine/metadata-modules/serverless-function/serverless-function.resolver';
|
||||
import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverless-function/serverless-function.service';
|
||||
import { ServerlessFunctionTriggerJob } from 'src/engine/metadata-modules/serverless-function/jobs/serverless-function-trigger.job';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -23,7 +24,11 @@ import { ServerlessFunctionService } from 'src/engine/metadata-modules/serverles
|
||||
AuditModule,
|
||||
FeatureFlagModule,
|
||||
],
|
||||
providers: [ServerlessFunctionService, ServerlessFunctionResolver],
|
||||
providers: [
|
||||
ServerlessFunctionService,
|
||||
ServerlessFunctionTriggerJob,
|
||||
ServerlessFunctionResolver,
|
||||
],
|
||||
exports: [ServerlessFunctionService],
|
||||
})
|
||||
export class ServerlessFunctionModule {}
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { Command, CommandRunner } from 'nest-commander';
|
||||
|
||||
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 {
|
||||
CRON_TRIGGER_CRON_PATTERN,
|
||||
CronTriggerCronJob,
|
||||
} from 'src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job';
|
||||
@Command({
|
||||
name: 'cron:trigger:start-cron-trigger',
|
||||
description:
|
||||
'Starts a cron job to trigger cron triggered serverless functions',
|
||||
})
|
||||
export class CronTriggerCronCommand extends CommandRunner {
|
||||
constructor(
|
||||
@InjectMessageQueue(MessageQueue.cronQueue)
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
await this.messageQueueService.addCron<undefined>({
|
||||
jobName: CronTriggerCronJob.name,
|
||||
data: undefined,
|
||||
options: {
|
||||
repeat: {
|
||||
pattern: CRON_TRIGGER_CRON_PATTERN,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { SentryCronMonitor } from 'src/engine/core-modules/cron/sentry-cron-monitor.decorator';
|
||||
import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator';
|
||||
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.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 { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import {
|
||||
ServerlessFunctionTriggerJob,
|
||||
ServerlessFunctionTriggerJobData,
|
||||
} from 'src/engine/metadata-modules/serverless-function/jobs/serverless-function-trigger.job';
|
||||
import { shouldRunNow } from 'src/utils/should-run-now.utils';
|
||||
|
||||
export const CRON_TRIGGER_CRON_PATTERN = '* * * * *';
|
||||
|
||||
@Processor(MessageQueue.cronQueue)
|
||||
export class CronTriggerCronJob {
|
||||
constructor(
|
||||
@InjectMessageQueue(MessageQueue.serverlessFunctionQueue)
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
@InjectRepository(Workspace)
|
||||
private readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(CronTrigger)
|
||||
private readonly cronTriggerRepository: Repository<CronTrigger>,
|
||||
) {}
|
||||
|
||||
@Process(CronTriggerCronJob.name)
|
||||
@SentryCronMonitor(CronTriggerCronJob.name, CRON_TRIGGER_CRON_PATTERN)
|
||||
async handle() {
|
||||
const activeWorkspaces = await this.workspaceRepository.find({
|
||||
where: {
|
||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||
},
|
||||
select: ['id'],
|
||||
});
|
||||
|
||||
const now = new Date();
|
||||
|
||||
for (const activeWorkspace of activeWorkspaces) {
|
||||
const cronTriggers = await this.cronTriggerRepository.find({
|
||||
where: {
|
||||
workspaceId: activeWorkspace.id,
|
||||
},
|
||||
select: ['settings'],
|
||||
relations: ['serverlessFunction'],
|
||||
});
|
||||
|
||||
for (const cronTrigger of cronTriggers) {
|
||||
const settings = cronTrigger.settings;
|
||||
|
||||
if (!isDefined(settings.pattern)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!shouldRunNow(settings.pattern, now)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.messageQueueService.add<ServerlessFunctionTriggerJobData>(
|
||||
ServerlessFunctionTriggerJob.name,
|
||||
{
|
||||
serverlessFunctionId: cronTrigger.serverlessFunction.id,
|
||||
workspaceId: activeWorkspace.id,
|
||||
payload: {},
|
||||
},
|
||||
{ retryLimit: 3 },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
DeleteDateColumn,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
Relation,
|
||||
Index,
|
||||
} from 'typeorm';
|
||||
|
||||
import { ServerlessFunctionEntity } from 'src/engine/metadata-modules/serverless-function/serverless-function.entity';
|
||||
|
||||
export type CronTriggerSettings = {
|
||||
pattern: string;
|
||||
};
|
||||
|
||||
@Entity({ name: 'cronTrigger', schema: 'core' })
|
||||
@Index('IDX_CRON_TRIGGER_WORKSPACE_ID', ['workspaceId'])
|
||||
export class CronTrigger {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ nullable: false, type: 'jsonb' })
|
||||
settings: CronTriggerSettings;
|
||||
|
||||
@ManyToOne(
|
||||
() => ServerlessFunctionEntity,
|
||||
(serverlessFunction) => serverlessFunction.cronTriggers,
|
||||
{ onDelete: 'CASCADE' },
|
||||
)
|
||||
@JoinColumn({ name: 'serverlessFunctionId' })
|
||||
serverlessFunction: Relation<ServerlessFunctionEntity>;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date;
|
||||
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt?: Date;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/trigger/crons/commands/cron-trigger.cron.command';
|
||||
import { CronTriggerCronJob } from 'src/engine/metadata-modules/trigger/crons/jobs/cron-trigger.cron.job';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { CronTrigger } from 'src/engine/metadata-modules/trigger/entities/cron-trigger.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Workspace, CronTrigger])],
|
||||
providers: [CronTriggerCronJob, CronTriggerCronCommand],
|
||||
exports: [CronTriggerCronCommand],
|
||||
})
|
||||
export class TriggerModule {}
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/works
|
||||
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
|
||||
import { AutomatedTriggerWorkspaceService } from 'src/modules/workflow/workflow-trigger/automated-trigger/automated-trigger.workspace-service';
|
||||
import { WorkflowCronTriggerCronCommand } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/commands/workflow-cron-trigger.cron.command';
|
||||
import { CronTriggerCronJob } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/jobs/cron-trigger.cron.job';
|
||||
import { WorkflowCronTriggerCronJob } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/jobs/workflow-cron-trigger-cron.job';
|
||||
import { DatabaseEventTriggerListener } from 'src/modules/workflow/workflow-trigger/automated-trigger/listeners/database-event-trigger.listener';
|
||||
|
||||
@Module({
|
||||
@@ -18,7 +18,7 @@ import { DatabaseEventTriggerListener } from 'src/modules/workflow/workflow-trig
|
||||
providers: [
|
||||
AutomatedTriggerWorkspaceService,
|
||||
DatabaseEventTriggerListener,
|
||||
CronTriggerCronJob,
|
||||
WorkflowCronTriggerCronJob,
|
||||
WorkflowCronTriggerCronCommand,
|
||||
],
|
||||
exports: [AutomatedTriggerWorkspaceService, WorkflowCronTriggerCronCommand],
|
||||
|
||||
+5
-5
@@ -4,9 +4,9 @@ import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decora
|
||||
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 {
|
||||
CRON_TRIGGER_CRON_PATTERN,
|
||||
CronTriggerCronJob,
|
||||
} from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/jobs/cron-trigger.cron.job';
|
||||
WORKFLOW_CRON_TRIGGER_CRON_PATTERN,
|
||||
WorkflowCronTriggerCronJob,
|
||||
} from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/jobs/workflow-cron-trigger-cron.job';
|
||||
|
||||
@Command({
|
||||
name: 'cron:workflow:automated-cron-trigger',
|
||||
@@ -22,11 +22,11 @@ export class WorkflowCronTriggerCronCommand extends CommandRunner {
|
||||
|
||||
async run(): Promise<void> {
|
||||
await this.messageQueueService.addCron<undefined>({
|
||||
jobName: CronTriggerCronJob.name,
|
||||
jobName: WorkflowCronTriggerCronJob.name,
|
||||
data: undefined,
|
||||
options: {
|
||||
repeat: {
|
||||
pattern: CRON_TRIGGER_CRON_PATTERN,
|
||||
pattern: WORKFLOW_CRON_TRIGGER_CRON_PATTERN,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
+8
-5
@@ -15,16 +15,16 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
|
||||
import { AutomatedTriggerType } from 'src/modules/workflow/common/standard-objects/workflow-automated-trigger.workspace-entity';
|
||||
import { type CronTriggerSettings } from 'src/modules/workflow/workflow-trigger/automated-trigger/constants/automated-trigger-settings';
|
||||
import { shouldRunNow } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/utils/should-run-now.utils';
|
||||
import {
|
||||
WorkflowTriggerJob,
|
||||
type WorkflowTriggerJobData,
|
||||
} from 'src/modules/workflow/workflow-trigger/jobs/workflow-trigger.job';
|
||||
import { shouldRunNow } from 'src/utils/should-run-now.utils';
|
||||
|
||||
export const CRON_TRIGGER_CRON_PATTERN = '* * * * *';
|
||||
export const WORKFLOW_CRON_TRIGGER_CRON_PATTERN = '* * * * *';
|
||||
|
||||
@Processor(MessageQueue.cronQueue)
|
||||
export class CronTriggerCronJob {
|
||||
export class WorkflowCronTriggerCronJob {
|
||||
constructor(
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
@@ -35,8 +35,11 @@ export class CronTriggerCronJob {
|
||||
private readonly exceptionHandlerService: ExceptionHandlerService,
|
||||
) {}
|
||||
|
||||
@Process(CronTriggerCronJob.name)
|
||||
@SentryCronMonitor(CronTriggerCronJob.name, CRON_TRIGGER_CRON_PATTERN)
|
||||
@Process(WorkflowCronTriggerCronJob.name)
|
||||
@SentryCronMonitor(
|
||||
WorkflowCronTriggerCronJob.name,
|
||||
WORKFLOW_CRON_TRIGGER_CRON_PATTERN,
|
||||
)
|
||||
async handle() {
|
||||
const activeWorkspaces = await this.workspaceRepository.find({
|
||||
where: {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { shouldRunNow } from 'src/modules/workflow/workflow-trigger/automated-trigger/crons/utils/should-run-now.utils';
|
||||
import { shouldRunNow } from 'src/utils/should-run-now.utils';
|
||||
|
||||
const getNowDate = (hour: string) => {
|
||||
return new Date(`2025-01-01T${hour}.100Z`);
|
||||
Reference in New Issue
Block a user