From 8ac83f1d59ed643d88ecebbb628182489353ebdc Mon Sep 17 00:00:00 2001 From: Chigala <92148630+Chigala@users.noreply.github.com> Date: Wed, 26 Jul 2023 21:18:03 +0100 Subject: [PATCH 1/4] added multiple event name support to the eventDispatcher --- apps/webapp/app/services/events/deliverEvent.server.ts | 4 +++- .../migrations/20230724074140_changed/migration.sql | 9 +++++++++ packages/database/prisma/schema.prisma | 6 +++--- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 packages/database/prisma/migrations/20230724074140_changed/migration.sql diff --git a/apps/webapp/app/services/events/deliverEvent.server.ts b/apps/webapp/app/services/events/deliverEvent.server.ts index f3745a49b04..04df77fe5a2 100644 --- a/apps/webapp/app/services/events/deliverEvent.server.ts +++ b/apps/webapp/app/services/events/deliverEvent.server.ts @@ -33,7 +33,9 @@ export class DeliverEventService { const possibleEventDispatchers = await tx.eventDispatcher.findMany({ where: { environmentId: eventRecord.environmentId, - event: eventRecord.name, + event: { + has: eventRecord.name, + }, source: eventRecord.source, enabled: true, manual: false, diff --git a/packages/database/prisma/migrations/20230724074140_changed/migration.sql b/packages/database/prisma/migrations/20230724074140_changed/migration.sql new file mode 100644 index 00000000000..6fce4a15f54 --- /dev/null +++ b/packages/database/prisma/migrations/20230724074140_changed/migration.sql @@ -0,0 +1,9 @@ +/* + Warnings: + + - The `event` column on the `EventDispatcher` table would be dropped and recreated. This will lead to data loss if there is data in the column. + +*/ +-- AlterTable +ALTER TABLE "EventDispatcher" DROP COLUMN "event", +ADD COLUMN "event" TEXT[]; diff --git a/packages/database/prisma/schema.prisma b/packages/database/prisma/schema.prisma index 5d62807e342..d586ee4296b 100644 --- a/packages/database/prisma/schema.prisma +++ b/packages/database/prisma/schema.prisma @@ -582,12 +582,12 @@ enum DynamicTriggerType { } model EventDispatcher { - id String @id @default(cuid()) - event String + id String @id @default(cuid()) + event String[] source String payloadFilter Json? contextFilter Json? - manual Boolean @default(false) + manual Boolean @default(false) dispatchableId String dispatchable Json From e0a2cec978ed982d349f81bfd063be69241663d0 Mon Sep 17 00:00:00 2001 From: Chigala <92148630+Chigala@users.noreply.github.com> Date: Thu, 27 Jul 2023 00:09:03 +0100 Subject: [PATCH 2/4] Chore: Modified eventTrigger to accept a string and an array of strings. --- packages/internal/src/schemas/eventFilter.ts | 2 +- packages/internal/src/schemas/triggers.ts | 2 +- packages/trigger-sdk/src/triggers/eventTrigger.ts | 4 ++-- packages/trigger-sdk/src/types.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/internal/src/schemas/eventFilter.ts b/packages/internal/src/schemas/eventFilter.ts index b0499f19b0b..bbe28eba529 100644 --- a/packages/internal/src/schemas/eventFilter.ts +++ b/packages/internal/src/schemas/eventFilter.ts @@ -19,7 +19,7 @@ export const EventFilterSchema: z.ZodType = z.lazy(() => ); export const EventRuleSchema = z.object({ - event: z.string(), + event: z.union([z.string(), z.array(z.string())]), source: z.string(), payload: EventFilterSchema.optional(), context: EventFilterSchema.optional(), diff --git a/packages/internal/src/schemas/triggers.ts b/packages/internal/src/schemas/triggers.ts index 2ef8402bcd1..a40e9b5b46a 100644 --- a/packages/internal/src/schemas/triggers.ts +++ b/packages/internal/src/schemas/triggers.ts @@ -30,7 +30,7 @@ export const DynamicTriggerMetadataSchema = z.object({ export const StaticTriggerMetadataSchema = z.object({ type: z.literal("static"), - title: z.string(), + title: z.union([z.string(), z.array(z.string())]), properties: z.array(DisplayPropertySchema).optional(), rule: EventRuleSchema, }); diff --git a/packages/trigger-sdk/src/triggers/eventTrigger.ts b/packages/trigger-sdk/src/triggers/eventTrigger.ts index 3951271a05e..86f518b7f0d 100644 --- a/packages/trigger-sdk/src/triggers/eventTrigger.ts +++ b/packages/trigger-sdk/src/triggers/eventTrigger.ts @@ -11,7 +11,7 @@ import { EventSpecification, Trigger } from "../types"; type EventTriggerOptions> = { event: TEventSpecification; - name?: string; + name?: string | string[]; source?: string; filter?: EventFilter; }; @@ -57,7 +57,7 @@ export class EventTrigger> /** Configuration options for an EventTrigger */ type TriggerOptions = { /** The name of the event you are subscribing to. Must be an exact match (case sensitive). */ - name: string; + name: string | string[]; /** A [Zod](https://trigger.dev/docs/documentation/guides/zod) schema that defines the shape of the event payload. * The default is `z.any()` which is `any`. * */ diff --git a/packages/trigger-sdk/src/types.ts b/packages/trigger-sdk/src/types.ts index 5222a3839ea..312b93a4517 100644 --- a/packages/trigger-sdk/src/types.ts +++ b/packages/trigger-sdk/src/types.ts @@ -69,13 +69,13 @@ export interface Trigger> { export type EventSpecificationExample = { id: string; - name: string; + name: string | string[]; icon?: string; payload: any; }; export interface EventSpecification { - name: string; + name: string | string[]; title: string; source: string; icon: string; From 7e4d72f95949a9d5336b2ef70d88e906a713ee27 Mon Sep 17 00:00:00 2001 From: Eric Allam Date: Fri, 28 Jul 2023 11:48:23 +0100 Subject: [PATCH 3/4] Made the migration non-destructive and fixed other typechecking issues --- .../app/services/jobs/registerJob.server.ts | 10 +- .../app/services/jobs/testJob.server.ts | 109 ++++++++++-------- examples/nextjs-example/src/jobs/events.ts | 14 +++ .../20230724074140_changed/migration.sql | 18 ++- packages/internal/src/schemas/eventFilter.ts | 2 +- packages/internal/src/schemas/triggers.ts | 2 +- packages/trigger-sdk/src/triggerClient.ts | 7 +- packages/trigger-sdk/src/triggers/dynamic.ts | 5 +- .../trigger-sdk/src/triggers/eventTrigger.ts | 11 +- packages/trigger-sdk/src/types.ts | 2 +- 10 files changed, 119 insertions(+), 61 deletions(-) diff --git a/apps/webapp/app/services/jobs/registerJob.server.ts b/apps/webapp/app/services/jobs/registerJob.server.ts index 2e6d2df3ce8..36d3c207f37 100644 --- a/apps/webapp/app/services/jobs/registerJob.server.ts +++ b/apps/webapp/app/services/jobs/registerJob.server.ts @@ -404,7 +404,10 @@ export class RegisterJobService { }, }, create: { - event: trigger.rule.event, + event: + typeof trigger.rule.event === "string" + ? [trigger.rule.event] + : trigger.rule.event, source: trigger.rule.source, payloadFilter: trigger.rule.payload, contextFilter: trigger.rule.context, @@ -417,7 +420,10 @@ export class RegisterJobService { dispatchableId: job.id, }, update: { - event: trigger.rule.event, + event: + typeof trigger.rule.event === "string" + ? [trigger.rule.event] + : trigger.rule.event, source: trigger.rule.source, payloadFilter: trigger.rule.payload, contextFilter: trigger.rule.context, diff --git a/apps/webapp/app/services/jobs/testJob.server.ts b/apps/webapp/app/services/jobs/testJob.server.ts index 183f04e2893..501ab8ccf54 100644 --- a/apps/webapp/app/services/jobs/testJob.server.ts +++ b/apps/webapp/app/services/jobs/testJob.server.ts @@ -18,64 +18,73 @@ export class TestJobService { versionId: string; payload: any; }) { - return await $transaction(this.#prismaClient, async (tx) => { - //get the environment with orgId and projectId - const environment = await tx.runtimeEnvironment.findUniqueOrThrow({ - include: { - organization: true, - project: true, - }, - where: { - id: environmentId, - }, - }); + return await $transaction( + this.#prismaClient, + async (tx) => { + //get the environment with orgId and projectId + const environment = await tx.runtimeEnvironment.findUniqueOrThrow({ + include: { + organization: true, + project: true, + }, + where: { + id: environmentId, + }, + }); - const version = await tx.jobVersion.findUniqueOrThrow({ - include: { - job: true, - }, - where: { - id: versionId, - }, - }); + const version = await tx.jobVersion.findUniqueOrThrow({ + include: { + job: true, + }, + where: { + id: versionId, + }, + }); - const event = EventSpecificationSchema.parse(version.eventSpecification); + const event = EventSpecificationSchema.parse( + version.eventSpecification + ); + const eventName = Array.isArray(event.name) + ? event.name[0] + : event.name; - const eventLog = await this.#prismaClient.eventRecord.create({ - data: { - organization: { - connect: { - id: environment.organizationId, + const eventLog = await this.#prismaClient.eventRecord.create({ + data: { + organization: { + connect: { + id: environment.organizationId, + }, }, - }, - project: { - connect: { - id: environment.projectId, + project: { + connect: { + id: environment.projectId, + }, }, - }, - environment: { - connect: { - id: environment.id, + environment: { + connect: { + id: environment.id, + }, }, + eventId: `test:${eventName}:${new Date().getTime()}`, + name: eventName, + timestamp: new Date(), + payload: payload ?? {}, + context: {}, + source: event.source ?? "trigger.dev", + isTest: true, }, - eventId: `test:${event.name}:${new Date().getTime()}`, - name: event.name, - timestamp: new Date(), - payload: payload ?? {}, - context: {}, - source: event.source ?? "trigger.dev", - isTest: true, - }, - }); + }); - const createRunService = new CreateRunService(tx); + const createRunService = new CreateRunService(tx); - return await createRunService.call({ - environment, - eventId: eventLog.id, - job: version.job, - version, - }); - }, { timeout: 10000 }); + return await createRunService.call({ + environment, + eventId: eventLog.id, + job: version.job, + version, + }); + }, + { timeout: 10000 } + ); } } diff --git a/examples/nextjs-example/src/jobs/events.ts b/examples/nextjs-example/src/jobs/events.ts index 136409ee0ca..4ef4071864e 100644 --- a/examples/nextjs-example/src/jobs/events.ts +++ b/examples/nextjs-example/src/jobs/events.ts @@ -44,3 +44,17 @@ client.defineJob({ } }, }); + +client.defineJob({ + id: "test-multiple-events", + name: "Test Multiple Events", + version: "0.0.1", + logLevel: "debug", + trigger: eventTrigger({ + name: ["test.event.1", "test.event.2"], + examples: [{ id: "test", name: "Test", payload: { name: "test" } }], + }), + run: async (payload, io, ctx) => { + await io.logger.log(`Triggered by the ${ctx.event.name} event`, { ctx }); + }, +}); diff --git a/packages/database/prisma/migrations/20230724074140_changed/migration.sql b/packages/database/prisma/migrations/20230724074140_changed/migration.sql index 6fce4a15f54..9b1129cae16 100644 --- a/packages/database/prisma/migrations/20230724074140_changed/migration.sql +++ b/packages/database/prisma/migrations/20230724074140_changed/migration.sql @@ -5,5 +5,19 @@ */ -- AlterTable -ALTER TABLE "EventDispatcher" DROP COLUMN "event", -ADD COLUMN "event" TEXT[]; +-- Step 1: Create temporary column +ALTER TABLE "EventDispatcher" +ADD COLUMN temp_event TEXT[]; + +-- Step 2: Update temporary column +UPDATE "EventDispatcher" +SET temp_event = ARRAY[event]; + +-- Step 3: Drop original column +ALTER TABLE "EventDispatcher" +DROP COLUMN "event"; + +-- Step 4: Rename temporary column +ALTER TABLE "EventDispatcher" +RENAME COLUMN temp_event TO "event"; + diff --git a/packages/internal/src/schemas/eventFilter.ts b/packages/internal/src/schemas/eventFilter.ts index bbe28eba529..4ef40a7dfa3 100644 --- a/packages/internal/src/schemas/eventFilter.ts +++ b/packages/internal/src/schemas/eventFilter.ts @@ -19,7 +19,7 @@ export const EventFilterSchema: z.ZodType = z.lazy(() => ); export const EventRuleSchema = z.object({ - event: z.union([z.string(), z.array(z.string())]), + event: z.string().or(z.array(z.string())), source: z.string(), payload: EventFilterSchema.optional(), context: EventFilterSchema.optional(), diff --git a/packages/internal/src/schemas/triggers.ts b/packages/internal/src/schemas/triggers.ts index a40e9b5b46a..edc5256bc6e 100644 --- a/packages/internal/src/schemas/triggers.ts +++ b/packages/internal/src/schemas/triggers.ts @@ -13,7 +13,7 @@ export const EventExampleSchema = z.object({ export type EventExample = z.infer; export const EventSpecificationSchema = z.object({ - name: z.string(), + name: z.string().or(z.array(z.string())), title: z.string(), source: z.string(), icon: z.string(), diff --git a/packages/trigger-sdk/src/triggerClient.ts b/packages/trigger-sdk/src/triggerClient.ts index e5f9e54bd9e..3bd46e640af 100644 --- a/packages/trigger-sdk/src/triggerClient.ts +++ b/packages/trigger-sdk/src/triggerClient.ts @@ -513,7 +513,12 @@ export class TriggerClient { } registeredSource.events = Array.from( - new Set([...registeredSource.events, options.event.name]) + new Set([ + ...registeredSource.events, + ...(typeof options.event.name === "string" + ? [options.event.name] + : options.event.name), + ]) ); this.#registeredSources[options.key] = registeredSource; diff --git a/packages/trigger-sdk/src/triggers/dynamic.ts b/packages/trigger-sdk/src/triggers/dynamic.ts index 1f6245f6431..f98a138d4e1 100644 --- a/packages/trigger-sdk/src/triggers/dynamic.ts +++ b/packages/trigger-sdk/src/triggers/dynamic.ts @@ -92,7 +92,10 @@ export class DynamicTrigger< key, channel: this.source.channel, params, - events: [this.event.name], + events: + typeof this.event.name === "string" + ? [this.event.name] + : this.event.name, integration: { id: this.source.integration.id, metadata: this.source.integration.metadata, diff --git a/packages/trigger-sdk/src/triggers/eventTrigger.ts b/packages/trigger-sdk/src/triggers/eventTrigger.ts index 86f518b7f0d..8942fa1f38d 100644 --- a/packages/trigger-sdk/src/triggers/eventTrigger.ts +++ b/packages/trigger-sdk/src/triggers/eventTrigger.ts @@ -6,7 +6,11 @@ import { import { z } from "zod"; import { Job } from "../job"; import { TriggerClient } from "../triggerClient"; -import { EventSpecification, Trigger } from "../types"; +import { + EventSpecification, + EventSpecificationExample, + Trigger, +} from "../types"; type EventTriggerOptions> = { @@ -56,7 +60,7 @@ export class EventTrigger> /** Configuration options for an EventTrigger */ type TriggerOptions = { - /** The name of the event you are subscribing to. Must be an exact match (case sensitive). */ + /** The name of the event you are subscribing to. Must be an exact match (case sensitive). To trigger on multiple possible events, pass in an array of event names */ name: string | string[]; /** A [Zod](https://trigger.dev/docs/documentation/guides/zod) schema that defines the shape of the event payload. * The default is `z.any()` which is `any`. @@ -84,6 +88,8 @@ type TriggerOptions = { * ``` */ filter?: EventFilter; + + examples?: EventSpecificationExample[]; }; /** `eventTrigger()` is set as a [Job's trigger](https://trigger.dev/docs/sdk/job) to subscribe to an event a Job from [a sent event](https://trigger.dev/docs/sdk/triggerclient/instancemethods/sendevent) @@ -100,6 +106,7 @@ export function eventTrigger( title: "Event", source: options.source ?? "trigger.dev", icon: "custom-event", + examples: options.examples, parsePayload: (rawPayload: any) => { if (options.schema) { return options.schema.parse(rawPayload); diff --git a/packages/trigger-sdk/src/types.ts b/packages/trigger-sdk/src/types.ts index 9a1545a09c5..eb291f543a3 100644 --- a/packages/trigger-sdk/src/types.ts +++ b/packages/trigger-sdk/src/types.ts @@ -75,7 +75,7 @@ export type TriggerPayload = TTrigger extends Trigger< export type EventSpecificationExample = { id: string; - name: string | string[]; + name: string; icon?: string; payload: any; }; From 9138976dad093920f1418dd6b84cc52d1aca1219 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Mon, 31 Jul 2023 16:13:35 +0100 Subject: [PATCH 4/4] Changeset: Multiple eventname support in eventDispatcher --- .changeset/brave-parents-roll.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/brave-parents-roll.md diff --git a/.changeset/brave-parents-roll.md b/.changeset/brave-parents-roll.md new file mode 100644 index 00000000000..b89668ce1ff --- /dev/null +++ b/.changeset/brave-parents-roll.md @@ -0,0 +1,5 @@ +--- +"@trigger.dev/sdk": patch +--- + +Multiple eventname support in eventDispatcher