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,30 +38,58 @@ 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);
const fn = this._client.createFunction(
{
id: job.id,
name: job.name,
},
{
event: job.trigger.name,
},
async (ctx) => {
const io = this.convertInngestIoToJobRunIo(ctx);
// We need to cast to any so we can deal with parsing later. if (job.trigger.type === 'cron') {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any const fn = this._client.createFunction(
let payload = ctx.event.data as any; {
id: job.id,
name: job.name,
},
{
cron: job.trigger.schedule,
},
async (ctx) => {
const io = this.convertInngestIoToJobRunIo(ctx);
if (job.trigger.schema) { // We need to cast to any so we can deal with parsing later.
payload = job.trigger.schema.parse(payload); // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
} let payload = ctx.event.data as any;
await job.handler({ payload, io }); if (job.trigger.schema) {
}, payload = job.trigger.schema.parse(payload);
); }
this._functions.push(fn); await job.handler({ payload, io });
},
);
this._functions.push(fn);
} else {
const fn = this._client.createFunction(
{
id: job.id,
name: job.name,
},
{
event: job.trigger.name,
},
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);
}
} }
public async triggerJob(options: SimpleTriggerJobOptions): Promise<void> { public async triggerJob(options: SimpleTriggerJobOptions): Promise<void> {

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,16 +31,30 @@ 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 {
this._client.defineJob({ if (job.trigger.type === 'cron') {
id: job.id, this._client.defineJob({
name: job.name, id: job.id,
version: job.version, name: job.name,
trigger: eventTrigger({ version: job.version,
name: job.trigger.name, trigger: cronTrigger({
schema: job.trigger.schema, cron: job.trigger.schedule,
}), }),
run: async (payload, io) => job.handler({ payload, io: this.convertTriggerIoToJobRunIo(io) }), run: async (payload, io) =>
}); job.handler({ payload: payload as T, io: this.convertTriggerIoToJobRunIo(io) }),
});
} else {
this._client.defineJob({
id: job.id,
name: job.name,
version: job.version,
trigger: eventTrigger({
name: job.trigger.name,
schema: job.trigger.schema,
}),
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> {

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,
}, },