diff --git a/.changeset/fix-batch-trigger-and-wait-debounce.md b/.changeset/fix-batch-trigger-and-wait-debounce.md new file mode 100644 index 00000000000..4261d2bb2a4 --- /dev/null +++ b/.changeset/fix-batch-trigger-and-wait-debounce.md @@ -0,0 +1,5 @@ +--- +"@trigger.dev/sdk": patch +--- + +Forward per-item debounce options in array batchTriggerAndWait calls. diff --git a/packages/trigger-sdk/src/v3/shared.test.ts b/packages/trigger-sdk/src/v3/shared.test.ts index 4a0509b6b3b..842788e97fd 100644 --- a/packages/trigger-sdk/src/v3/shared.test.ts +++ b/packages/trigger-sdk/src/v3/shared.test.ts @@ -1,6 +1,8 @@ -import { describe, it, expect } from "vitest"; +import { describe, it, expect, afterEach, vi } from "vitest"; import { readableStreamToAsyncIterable } from "./shared.js"; +let taskIdCounter = 0; + describe("readableStreamToAsyncIterable", () => { it("yields all values from the stream", async () => { const values = [1, 2, 3, 4, 5]; @@ -217,3 +219,114 @@ describe("readableStreamToAsyncIterable", () => { }); }); +describe("batchTriggerAndWait debounce forwarding", () => { + afterEach(() => { + vi.doUnmock("@trigger.dev/core/v3"); + vi.resetModules(); + vi.restoreAllMocks(); + }); + + async function setupBatchTriggerAndWaitHarness() { + vi.resetModules(); + + const capturedItems: any[] = []; + + const createBatch = vi.fn(async ({ runCount }: { runCount: number }) => ({ + id: "batch_test123", + runCount, + publicAccessToken: "access_token", + isCached: false, + })); + + const streamBatchItems = vi.fn(async (_batchId: string, items: any[]) => { + capturedItems.push(...items); + + return { + id: "batch_test123", + itemsAccepted: items.length, + itemsDeduplicated: 0, + sealed: true, + }; + }); + + const waitForBatch = vi.fn(async ({ id }: { id: string }) => ({ + id, + items: [], + })); + + vi.doMock("@trigger.dev/core/v3", async (importOriginal) => { + const original = await importOriginal(); + + return { + ...original, + apiClientManager: { + clientOrThrow: vi.fn(() => ({ + createBatch, + streamBatchItems, + })), + } as any, + runtime: { + ...original.runtime, + waitForBatch, + } as any, + taskContext: { + ctx: { + run: { + id: "run_123", + isTest: false, + }, + }, + worker: { + version: "worker_123", + }, + } as any, + }; + }); + + const tasksModule = await import("./tasks.js"); + + return { + ...tasksModule, + capturedItems, + createBatch, + streamBatchItems, + waitForBatch, + }; + } + + it("forwards per-item debounce for task.batchTriggerAndWait array items", async () => { + const { task, capturedItems, streamBatchItems, waitForBatch } = + await setupBatchTriggerAndWaitHarness(); + const debounce = { key: "same-key", delay: "30s", mode: "trailing" as const }; + const taskId = `batch-debounce-task-${++taskIdCounter}`; + + const myTask = task({ + id: taskId, + run: async (payload: { id: string }) => payload, + }); + + await myTask.batchTriggerAndWait([{ payload: { id: "a" }, options: { debounce } }]); + + expect(streamBatchItems).toHaveBeenCalledTimes(1); + expect(waitForBatch).toHaveBeenCalledTimes(1); + expect(capturedItems).toHaveLength(1); + expect(capturedItems[0]?.task).toBe(taskId); + expect(capturedItems[0]?.options?.debounce).toEqual(debounce); + }); + + it("forwards per-item debounce for tasks.batchTriggerAndWait array items", async () => { + const { tasks, capturedItems, streamBatchItems, waitForBatch } = + await setupBatchTriggerAndWaitHarness(); + const debounce = { key: "same-key", delay: "30s", mode: "trailing" as const }; + + await tasks.batchTriggerAndWait("batch-debounce-by-id-task", [ + { payload: { id: "a" }, options: { debounce } }, + ]); + + expect(streamBatchItems).toHaveBeenCalledTimes(1); + expect(waitForBatch).toHaveBeenCalledTimes(1); + expect(capturedItems).toHaveLength(1); + expect(capturedItems[0]?.task).toBe("batch-debounce-by-id-task"); + expect(capturedItems[0]?.options?.debounce).toEqual(debounce); + }); +}); diff --git a/packages/trigger-sdk/src/v3/shared.ts b/packages/trigger-sdk/src/v3/shared.ts index c69bceeb535..be37827a725 100644 --- a/packages/trigger-sdk/src/v3/shared.ts +++ b/packages/trigger-sdk/src/v3/shared.ts @@ -2507,6 +2507,7 @@ async function batchTriggerAndWait_internal