feat: add cron job trigger for background jobs

Extends the job to support both event-based and cron-scheduled triggers
This commit is contained in:
Ephraim Atta-Duncan
2024-11-20 15:00:45 +00:00
parent 2e2bc8382f
commit 8b771d36d2
10 changed files with 94 additions and 35 deletions

View File

@ -26,16 +26,26 @@ export type TriggerJobOptions<Definitions extends ReadonlyArray<JobDefinition> =
}; };
}[number]; }[number];
export type CronTrigger = {
type: 'cron';
schedule: string;
name?: string;
};
export type EventTrigger<N extends string = string> = {
type: 'event';
name: N;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export type JobDefinition<Name extends string = string, Schema = any> = { export type JobDefinition<Name extends string = string, Schema = any> = {
id: string; id: string;
name: string; name: string;
version: string; version: string;
enabled?: boolean; enabled?: boolean;
trigger: { trigger:
name: Name; | (EventTrigger<Name> & { schema?: z.ZodType<Schema> })
schema?: z.ZodType<Schema>; | (CronTrigger & { schema?: z.ZodType<Schema> });
};
handler: (options: { payload: Schema; io: JobRunIO }) => Promise<Json | void>; handler: (options: { payload: Schema; io: JobRunIO }) => Promise<Json | void>;
}; };

View File

@ -38,6 +38,33 @@ export class InngestJobProvider extends BaseJobProvider {
public defineJob<N extends string, T>(job: JobDefinition<N, T>): void { public defineJob<N extends string, T>(job: JobDefinition<N, T>): void {
console.log('defining job', job.id); console.log('defining job', job.id);
if (job.trigger.type === 'cron') {
const fn = this._client.createFunction(
{
id: job.id,
name: job.name,
},
{
cron: job.trigger.schedule,
},
async (ctx) => {
const io = this.convertInngestIoToJobRunIo(ctx);
// We need to cast to any so we can deal with parsing later.
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
let payload = ctx.event.data as any;
if (job.trigger.schema) {
payload = job.trigger.schema.parse(payload);
}
await job.handler({ payload, io });
},
);
this._functions.push(fn);
} else {
const fn = this._client.createFunction( const fn = this._client.createFunction(
{ {
id: job.id, id: job.id,
@ -63,6 +90,7 @@ export class InngestJobProvider extends BaseJobProvider {
this._functions.push(fn); this._functions.push(fn);
} }
}
public async triggerJob(options: SimpleTriggerJobOptions): Promise<void> { public async triggerJob(options: SimpleTriggerJobOptions): Promise<void> {
await this._client.send({ await this._client.send({

View File

@ -1,6 +1,6 @@
import { createPagesRoute } from '@trigger.dev/nextjs'; import { createPagesRoute } from '@trigger.dev/nextjs';
import type { IO } from '@trigger.dev/sdk'; import type { IO } from '@trigger.dev/sdk';
import { TriggerClient, eventTrigger } from '@trigger.dev/sdk'; import { TriggerClient, cronTrigger, eventTrigger } from '@trigger.dev/sdk';
import type { JobDefinition, JobRunIO, SimpleTriggerJobOptions } from './_internal/job'; import type { JobDefinition, JobRunIO, SimpleTriggerJobOptions } from './_internal/job';
import { BaseJobProvider } from './base'; import { BaseJobProvider } from './base';
@ -31,6 +31,18 @@ export class TriggerJobProvider extends BaseJobProvider {
} }
public defineJob<N extends string, T>(job: JobDefinition<N, T>): void { public defineJob<N extends string, T>(job: JobDefinition<N, T>): void {
if (job.trigger.type === 'cron') {
this._client.defineJob({
id: job.id,
name: job.name,
version: job.version,
trigger: cronTrigger({
cron: job.trigger.schedule,
}),
run: async (payload, io) =>
job.handler({ payload: payload as T, io: this.convertTriggerIoToJobRunIo(io) }),
});
} else {
this._client.defineJob({ this._client.defineJob({
id: job.id, id: job.id,
name: job.name, name: job.name,
@ -39,9 +51,11 @@ export class TriggerJobProvider extends BaseJobProvider {
name: job.trigger.name, name: job.trigger.name,
schema: job.trigger.schema, schema: job.trigger.schema,
}), }),
run: async (payload, io) => job.handler({ payload, io: this.convertTriggerIoToJobRunIo(io) }), run: async (payload, io) =>
job.handler({ payload, io: this.convertTriggerIoToJobRunIo(io) }),
}); });
} }
}
public async triggerJob(options: SimpleTriggerJobOptions): Promise<void> { public async triggerJob(options: SimpleTriggerJobOptions): Promise<void> {
await this._client.sendEvent({ await this._client.sendEvent({

View File

@ -15,6 +15,7 @@ export const SEND_CONFIRMATION_EMAIL_JOB_DEFINITION = {
name: 'Send Confirmation Email', name: 'Send Confirmation Email',
version: '1.0.0', version: '1.0.0',
trigger: { trigger: {
type: 'event',
name: SEND_CONFIRMATION_EMAIL_JOB_DEFINITION_ID, name: SEND_CONFIRMATION_EMAIL_JOB_DEFINITION_ID,
schema: SEND_CONFIRMATION_EMAIL_JOB_DEFINITION_SCHEMA, schema: SEND_CONFIRMATION_EMAIL_JOB_DEFINITION_SCHEMA,
}, },

View File

@ -30,6 +30,7 @@ export const SEND_SIGNING_REJECTION_EMAILS_JOB_DEFINITION = {
name: 'Send Rejection Emails', name: 'Send Rejection Emails',
version: '1.0.0', version: '1.0.0',
trigger: { trigger: {
type: 'event',
name: SEND_SIGNING_REJECTION_EMAILS_JOB_DEFINITION_ID, name: SEND_SIGNING_REJECTION_EMAILS_JOB_DEFINITION_ID,
schema: SEND_SIGNING_REJECTION_EMAILS_JOB_DEFINITION_SCHEMA, schema: SEND_SIGNING_REJECTION_EMAILS_JOB_DEFINITION_SCHEMA,
}, },

View File

@ -43,6 +43,7 @@ export const SEND_SIGNING_EMAIL_JOB_DEFINITION = {
name: 'Send Signing Email', name: 'Send Signing Email',
version: '1.0.0', version: '1.0.0',
trigger: { trigger: {
type: 'event',
name: SEND_SIGNING_EMAIL_JOB_DEFINITION_ID, name: SEND_SIGNING_EMAIL_JOB_DEFINITION_ID,
schema: SEND_SIGNING_EMAIL_JOB_DEFINITION_SCHEMA, schema: SEND_SIGNING_EMAIL_JOB_DEFINITION_SCHEMA,
}, },

View File

@ -40,6 +40,7 @@ export const SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION = {
name: 'Send Team Deleted Email', name: 'Send Team Deleted Email',
version: '1.0.0', version: '1.0.0',
trigger: { trigger: {
type: 'event',
name: SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION_ID, name: SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION_ID,
schema: SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION_SCHEMA, schema: SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION_SCHEMA,
}, },

View File

@ -27,6 +27,7 @@ export const SEND_TEAM_MEMBER_JOINED_EMAIL_JOB_DEFINITION = {
name: 'Send Team Member Joined Email', name: 'Send Team Member Joined Email',
version: '1.0.0', version: '1.0.0',
trigger: { trigger: {
type: 'event',
name: SEND_TEAM_MEMBER_JOINED_EMAIL_JOB_DEFINITION_ID, name: SEND_TEAM_MEMBER_JOINED_EMAIL_JOB_DEFINITION_ID,
schema: SEND_TEAM_MEMBER_JOINED_EMAIL_JOB_DEFINITION_SCHEMA, schema: SEND_TEAM_MEMBER_JOINED_EMAIL_JOB_DEFINITION_SCHEMA,
}, },

View File

@ -27,6 +27,7 @@ export const SEND_TEAM_MEMBER_LEFT_EMAIL_JOB_DEFINITION = {
name: 'Send Team Member Left Email', name: 'Send Team Member Left Email',
version: '1.0.0', version: '1.0.0',
trigger: { trigger: {
type: 'event',
name: SEND_TEAM_MEMBER_LEFT_EMAIL_JOB_DEFINITION_ID, name: SEND_TEAM_MEMBER_LEFT_EMAIL_JOB_DEFINITION_ID,
schema: SEND_TEAM_MEMBER_LEFT_EMAIL_JOB_DEFINITION_SCHEMA, schema: SEND_TEAM_MEMBER_LEFT_EMAIL_JOB_DEFINITION_SCHEMA,
}, },

View File

@ -41,6 +41,7 @@ export const SEAL_DOCUMENT_JOB_DEFINITION = {
name: 'Seal Document', name: 'Seal Document',
version: '1.0.0', version: '1.0.0',
trigger: { trigger: {
type: 'event',
name: SEAL_DOCUMENT_JOB_DEFINITION_ID, name: SEAL_DOCUMENT_JOB_DEFINITION_ID,
schema: SEAL_DOCUMENT_JOB_DEFINITION_SCHEMA, schema: SEAL_DOCUMENT_JOB_DEFINITION_SCHEMA,
}, },