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];
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
export type JobDefinition<Name extends string = string, Schema = any> = {
id: string;
name: string;
version: string;
enabled?: boolean;
trigger: {
name: Name;
schema?: z.ZodType<Schema>;
};
trigger:
| (EventTrigger<Name> & { schema?: z.ZodType<Schema> })
| (CronTrigger & { schema?: z.ZodType<Schema> });
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 {
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.
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
let payload = ctx.event.data as any;
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);
if (job.trigger.schema) {
payload = job.trigger.schema.parse(payload);
}
// 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;
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> {

View File

@ -1,6 +1,6 @@
import { createPagesRoute } from '@trigger.dev/nextjs';
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 { BaseJobProvider } from './base';
@ -31,16 +31,30 @@ export class TriggerJobProvider extends BaseJobProvider {
}
public defineJob<N extends string, T>(job: JobDefinition<N, T>): void {
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) }),
});
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({
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> {

View File

@ -15,6 +15,7 @@ export const SEND_CONFIRMATION_EMAIL_JOB_DEFINITION = {
name: 'Send Confirmation Email',
version: '1.0.0',
trigger: {
type: 'event',
name: SEND_CONFIRMATION_EMAIL_JOB_DEFINITION_ID,
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',
version: '1.0.0',
trigger: {
type: 'event',
name: SEND_SIGNING_REJECTION_EMAILS_JOB_DEFINITION_ID,
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',
version: '1.0.0',
trigger: {
type: 'event',
name: SEND_SIGNING_EMAIL_JOB_DEFINITION_ID,
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',
version: '1.0.0',
trigger: {
type: 'event',
name: SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION_ID,
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',
version: '1.0.0',
trigger: {
type: 'event',
name: SEND_TEAM_MEMBER_JOINED_EMAIL_JOB_DEFINITION_ID,
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',
version: '1.0.0',
trigger: {
type: 'event',
name: SEND_TEAM_MEMBER_LEFT_EMAIL_JOB_DEFINITION_ID,
schema: SEND_TEAM_MEMBER_LEFT_EMAIL_JOB_DEFINITION_SCHEMA,
},

View File

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