From 6006ba00dd99697ab8f7499f9fb90a41c96dc648 Mon Sep 17 00:00:00 2001 From: nicktrn <55853254+nicktrn@users.noreply.github.com> Date: Wed, 6 Dec 2023 07:48:54 +0000 Subject: [PATCH] Batched payload types --- packages/core/src/schemas/triggers.ts | 2 + packages/trigger-sdk/src/job.ts | 24 +++++++- .../trigger-sdk/src/triggers/eventTrigger.ts | 55 ++++++++++++++----- packages/trigger-sdk/src/triggers/webhook.ts | 31 ++++++++++- packages/trigger-sdk/src/types.ts | 4 +- 5 files changed, 94 insertions(+), 22 deletions(-) diff --git a/packages/core/src/schemas/triggers.ts b/packages/core/src/schemas/triggers.ts index a5114b488..f6f492eef 100644 --- a/packages/core/src/schemas/triggers.ts +++ b/packages/core/src/schemas/triggers.ts @@ -44,6 +44,8 @@ export const BatcherOptionsSchema = z.object({ export type BatcherOptions = z.infer; +export type OptionalBatcherOptions = BatcherOptions | undefined; + export const StaticTriggerMetadataSchema = z.object({ type: z.literal("static"), title: z.union([z.string(), z.array(z.string())]), diff --git a/packages/trigger-sdk/src/job.ts b/packages/trigger-sdk/src/job.ts index da5f7423b..a1400fde4 100644 --- a/packages/trigger-sdk/src/job.ts +++ b/packages/trigger-sdk/src/job.ts @@ -1,4 +1,5 @@ import { + BatcherOptions, FailedRunNotification, IntegrationConfig, InvokeOptions, @@ -21,6 +22,8 @@ import { slugifyId } from "./utils"; import { runLocalStorage } from "./runLocalStorage"; import { Prettify } from "@trigger.dev/core"; import { ConcurrencyLimit } from "./concurrencyLimit"; +import { EventTrigger } from "./triggers/eventTrigger"; +import { WebhookTrigger } from "./triggers/webhook"; export type JobOptions< TTrigger extends Trigger>, @@ -80,21 +83,36 @@ export type JobOptions< * @param context An object that contains information about the Organization, Job, Run and more. */ run: ( - payload: TriggerEventType, + payload: ArrayIfBatched>, io: IOWithIntegrations, context: TriggerContext ) => Promise; onSuccess?: ( - notification: SuccessfulRunNotification> + notification: SuccessfulRunNotification< + TOutput, + ArrayIfBatched> + > ) => void; - onFailure?: (notification: FailedRunNotification>) => void; + onFailure?: ( + notification: FailedRunNotification>> + ) => void; // @internal __internal?: boolean; }; +type HasBatchingEnabled = TBatcherOptions extends BatcherOptions ? true : false; + +type ArrayIfTrue = TBool extends true ? T[] : T; + +type ArrayIfBatched, T> = TTrigger extends EventTrigger + ? ArrayIfTrue, T> + : TTrigger extends WebhookTrigger + ? ArrayIfTrue, T> + : T; + export type JobPayload = TJob extends Job>, any> ? TEvent : never; diff --git a/packages/trigger-sdk/src/triggers/eventTrigger.ts b/packages/trigger-sdk/src/triggers/eventTrigger.ts index 81635f783..16aadd03e 100644 --- a/packages/trigger-sdk/src/triggers/eventTrigger.ts +++ b/packages/trigger-sdk/src/triggers/eventTrigger.ts @@ -1,4 +1,10 @@ -import { BatcherOptions, EventFilter, TriggerMetadata, deepMergeFilters } from "@trigger.dev/core"; +import { + BatcherOptions, + EventFilter, + OptionalBatcherOptions, + TriggerMetadata, + deepMergeFilters, +} from "@trigger.dev/core"; import { Job } from "../job"; import { TriggerClient } from "../triggerClient"; import { @@ -12,21 +18,26 @@ import { formatSchemaErrors } from "../utils/formatSchemaErrors"; import { ParsedPayloadSchemaError } from "../errors"; import { VerifyCallback } from "../httpEndpoint"; -type EventTriggerOptions> = { +type EventTriggerOptions< + TEventSpecification extends EventSpecification, + TBatcherOptions extends OptionalBatcherOptions = undefined, +> = { event: TEventSpecification; name?: string | string[]; source?: string; filter?: EventFilter; verify?: EventTypeFromSpecification extends Request ? VerifyCallback : never; - batch?: BatcherOptions; + batch?: TBatcherOptions; }; -export class EventTrigger> - implements Trigger +export class EventTrigger< + TEventSpecification extends EventSpecification, + TBatcherOptions extends OptionalBatcherOptions = undefined, +> implements Trigger { - #options: EventTriggerOptions; + #options: EventTriggerOptions; - constructor(options: EventTriggerOptions) { + constructor(options: EventTriggerOptions) { this.#options = options; } @@ -49,7 +60,14 @@ export class EventTrigger> attachToJob(triggerClient: TriggerClient, job: Job, any>): void {} - batch(options?: BatcherOptions): EventTrigger { + /** + * Used to configure batching options. An empty object will enable batching with server defaults. + * + * @param options - Is an object containing the following properties: + * @param {number} options.maxPayloads - The `maxPayloads` property defines how many event payloads you will receive at most per batch. This is affected by server limits, but you should never receive more than this. + * @param {number} options.maxInterval - The `maxInterval` property defines how many seconds to wait before sending out batches that aren't full yet. This is affected by server limits, but you should never receive more than this. + */ + batch(options?: BatcherOptions): EventTrigger { const { batch, ...rest } = this.#options; return new EventTrigger({ @@ -75,7 +93,7 @@ export class EventTrigger> } /** Configuration options for an EventTrigger */ -type TriggerOptions = { +type TriggerOptions = { /** 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. @@ -104,8 +122,14 @@ type TriggerOptions = { * ``` */ filter?: EventFilter; - /** Used to set batching options. */ - batch?: BatcherOptions; + + /** + * Used to configure batching options. An empty object will enable batching with server defaults. + * + * @param {number} maxPayloads - The `maxPayloads` property defines how many event payloads you will receive at most per batch. This is affected by server limits, but you should never receive more than this. + * @param {number} maxInterval - The `maxInterval` property defines how many seconds to wait before sending out batches that aren't full yet. This is affected by server limits, but you should never receive more than this. + */ + batch?: TBatcherOptions; examples?: EventSpecificationExample[]; }; @@ -113,9 +137,12 @@ type TriggerOptions = { /** `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) * @param options options for the EventTrigger */ -export function eventTrigger( - options: TriggerOptions -): EventTrigger> { +export function eventTrigger< + TEvent extends any = any, + TBatcherOptions extends OptionalBatcherOptions = undefined, +>( + options: TriggerOptions +): EventTrigger, TBatcherOptions> { return new EventTrigger({ name: options.name, filter: options.filter, diff --git a/packages/trigger-sdk/src/triggers/webhook.ts b/packages/trigger-sdk/src/triggers/webhook.ts index ab9eb1344..2f09cff12 100644 --- a/packages/trigger-sdk/src/triggers/webhook.ts +++ b/packages/trigger-sdk/src/triggers/webhook.ts @@ -3,6 +3,7 @@ import { DisplayProperty, EventFilter, HandleTriggerSource, + OptionalBatcherOptions, RegisterWebhookSource, TriggerMetadata, deepMergeFilters, @@ -262,20 +263,37 @@ export type WebhookTriggerOptions< TEventSpecification extends EventSpecification, TEventSource extends WebhookSource, TConfig extends Record = Record, + TBatcherOptions extends OptionalBatcherOptions = undefined, > = { event: TEventSpecification; source: TEventSource; params: GetWebhookParams; config: TConfig; - batch?: BatcherOptions; + + /** + * Used to configure batching options. An empty object will enable batching with server defaults. + * + * @param {number} maxPayloads - The `maxPayloads` property defines how many event payloads you will receive at most per batch. This is affected by server limits, but you should never receive more than this. + * @param {number} maxInterval - The `maxInterval` property defines how many seconds to wait before sending out batches that aren't full yet. This is affected by server limits, but you should never receive more than this. + */ + batch?: TBatcherOptions; }; export class WebhookTrigger< TEventSpecification extends EventSpecification, TEventSource extends WebhookSource, + TConfig extends Record = Record, + TBatcherOptions extends OptionalBatcherOptions = undefined, > implements Trigger { - constructor(private options: WebhookTriggerOptions) {} + constructor( + private options: WebhookTriggerOptions< + TEventSpecification, + TEventSource, + TConfig, + TBatcherOptions + > + ) {} get event() { return this.options.event; @@ -307,7 +325,14 @@ export class WebhookTrigger< }; } - batch(options?: BatcherOptions): WebhookTrigger { + /** + * Used to configure batching options. An empty object will enable batching with server defaults. + * + * @param options - Is an object containing the following properties: + * @param {number} options.maxPayloads - The `maxPayloads` property defines how many event payloads you will receive at most per batch. This is affected by server limits, but you should never receive more than this. + * @param {number} options.maxInterval - The `maxInterval` property defines how many seconds to wait before sending out batches that aren't full yet. This is affected by server limits, but you should never receive more than this. + */ + batch(options?: BatcherOptions): WebhookTrigger { const { batch, ...rest } = this.options; return new WebhookTrigger({ diff --git a/packages/trigger-sdk/src/types.ts b/packages/trigger-sdk/src/types.ts index 63adad147..2b38f5a97 100644 --- a/packages/trigger-sdk/src/types.ts +++ b/packages/trigger-sdk/src/types.ts @@ -124,8 +124,8 @@ export type TypedEventSpecificationExample = { id: string; name: string; icon?: string; - payload: TEvent -} + payload: TEvent; +}; export interface EventSpecification { name: string | string[];