Skip to content

Commit 5881a47

Browse files
committed
fix(sdk,react-hooks): forward debounce on the remaining trigger paths
Adds a satisfies check to every batch item builder so a missing or misspelled option key fails to compile instead of being stripped by the server, and asserts a distinct debounce key per item so the tests catch a wrong item-to-option pairing, not just a wholesale drop. useTaskTrigger had the same silent drop as the batch array branches.
1 parent 7f6ef07 commit 5881a47

4 files changed

Lines changed: 57 additions & 47 deletions

File tree

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
---
22
"@trigger.dev/sdk": patch
3+
"@trigger.dev/react-hooks": patch
34
---
45

5-
`debounce` now works when you pass an array of items to `batchTrigger` or `batchTriggerAndWait`. Previously the option was accepted by the types and dropped before the request was sent, so every item created its own run instead of collapsing onto the debounce key.
6+
`debounce` now works when you pass an array of items to `batchTrigger` or `batchTriggerAndWait`, and when you trigger from `useTaskTrigger`. Previously the option was accepted by the types and dropped before the request was sent, so every trigger created its own run instead of collapsing onto the debounce key.
67

78
```ts
89
await myTask.batchTrigger([
@@ -11,4 +12,4 @@ await myTask.batchTrigger([
1112
]);
1213
```
1314

14-
The streaming (async iterable) forms of these calls were already forwarding `debounce` correctly.
15+
The streaming (async iterable) forms of the batch calls were already forwarding `debounce` correctly.

packages/react-hooks/src/hooks/useTaskTrigger.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export function useTaskTrigger<TTask extends AnyTask>(
8787
metadata: options?.metadata,
8888
maxDuration: options?.maxDuration,
8989
lockToVersion: options?.version,
90+
debounce: options?.debounce,
9091
},
9192
});
9293

packages/trigger-sdk/src/v3/batchDebounce.test.ts

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ import { batch } from "./batch.js";
55
import { createTask } from "./shared.js";
66
import { tasks } from "./tasks.js";
77

8-
const DEBOUNCE = { key: "warm-conn-notify", delay: "12h", mode: "trailing" as const };
8+
const debounceFor = (i: number) => ({
9+
key: `warm-conn-notify:${i}`,
10+
delay: "12h",
11+
maxDelay: "24h",
12+
mode: "trailing" as const,
13+
});
14+
15+
const EXPECTED = [debounceFor(0), debounceFor(1)];
916

1017
type Payload = { i: number };
1118

@@ -55,11 +62,12 @@ function installBatchCapture() {
5562
});
5663
}
5764

58-
return Response.json({});
65+
throw new Error(`Unexpected request during batch trigger: ${url}`);
5966
}) as typeof fetch;
6067

6168
return {
62-
debounceOptions: () => sent.sort((a, b) => a.index - b.index).map((i) => i.options?.debounce),
69+
debounceOptions: () =>
70+
[...sent].sort((a, b) => a.index - b.index).map((item) => item.options?.debounce),
6371
restore: () => {
6472
globalThis.fetch = originalFetch;
6573
},
@@ -93,61 +101,61 @@ describe("batch trigger debounce forwarding", () => {
93101
name: "task.batchTrigger(array)",
94102
call: () =>
95103
taskA.batchTrigger([
96-
{ payload: { i: 0 }, options: { debounce: DEBOUNCE } },
97-
{ payload: { i: 1 }, options: { debounce: DEBOUNCE } },
104+
{ payload: { i: 0 }, options: { debounce: debounceFor(0) } },
105+
{ payload: { i: 1 }, options: { debounce: debounceFor(1) } },
98106
]),
99107
},
100108
{
101109
name: "task.batchTrigger(asyncIterable)",
102110
call: () =>
103111
taskA.batchTrigger(
104112
asAsyncIterable([
105-
{ payload: { i: 0 }, options: { debounce: DEBOUNCE } },
106-
{ payload: { i: 1 }, options: { debounce: DEBOUNCE } },
113+
{ payload: { i: 0 }, options: { debounce: debounceFor(0) } },
114+
{ payload: { i: 1 }, options: { debounce: debounceFor(1) } },
107115
])
108116
),
109117
},
110118
{
111119
name: "tasks.batchTrigger(array)",
112120
call: () =>
113121
tasks.batchTrigger<typeof taskA>("task-a", [
114-
{ payload: { i: 0 }, options: { debounce: DEBOUNCE } },
115-
{ payload: { i: 1 }, options: { debounce: DEBOUNCE } },
122+
{ payload: { i: 0 }, options: { debounce: debounceFor(0) } },
123+
{ payload: { i: 1 }, options: { debounce: debounceFor(1) } },
116124
]),
117125
},
118126
{
119127
name: "batch.trigger(array)",
120128
call: () =>
121129
batch.trigger<typeof taskA | typeof taskB>([
122-
{ id: "task-a", payload: { i: 0 }, options: { debounce: DEBOUNCE } },
123-
{ id: "task-b", payload: { i: 1 }, options: { debounce: DEBOUNCE } },
130+
{ id: "task-a", payload: { i: 0 }, options: { debounce: debounceFor(0) } },
131+
{ id: "task-b", payload: { i: 1 }, options: { debounce: debounceFor(1) } },
124132
]),
125133
},
126134
{
127135
name: "batch.trigger(asyncIterable)",
128136
call: () =>
129137
batch.trigger<typeof taskA | typeof taskB>(
130138
asAsyncIterable([
131-
{ id: "task-a" as const, payload: { i: 0 }, options: { debounce: DEBOUNCE } },
132-
{ id: "task-b" as const, payload: { i: 1 }, options: { debounce: DEBOUNCE } },
139+
{ id: "task-a" as const, payload: { i: 0 }, options: { debounce: debounceFor(0) } },
140+
{ id: "task-b" as const, payload: { i: 1 }, options: { debounce: debounceFor(1) } },
133141
])
134142
),
135143
},
136144
{
137145
name: "batch.triggerByTask(array)",
138146
call: () =>
139147
batch.triggerByTask([
140-
{ task: taskA, payload: { i: 0 }, options: { debounce: DEBOUNCE } },
141-
{ task: taskB, payload: { i: 1 }, options: { debounce: DEBOUNCE } },
148+
{ task: taskA, payload: { i: 0 }, options: { debounce: debounceFor(0) } },
149+
{ task: taskB, payload: { i: 1 }, options: { debounce: debounceFor(1) } },
142150
]),
143151
},
144152
{
145153
name: "batch.triggerByTask(asyncIterable)",
146154
call: () =>
147155
batch.triggerByTask(
148156
asAsyncIterable([
149-
{ task: taskA, payload: { i: 0 }, options: { debounce: DEBOUNCE } },
150-
{ task: taskB, payload: { i: 1 }, options: { debounce: DEBOUNCE } },
157+
{ task: taskA, payload: { i: 0 }, options: { debounce: debounceFor(0) } },
158+
{ task: taskB, payload: { i: 1 }, options: { debounce: debounceFor(1) } },
151159
])
152160
),
153161
},
@@ -156,69 +164,69 @@ describe("batch trigger debounce forwarding", () => {
156164
it.each(surfaces)("$name forwards debounce for every item", async ({ call }) => {
157165
await call();
158166

159-
expect(capture.debounceOptions()).toEqual([DEBOUNCE, DEBOUNCE]);
167+
expect(capture.debounceOptions()).toEqual(EXPECTED);
160168
});
161169

162170
const waitSurfaces: Array<{ name: string; call: () => Promise<unknown> }> = [
163171
{
164172
name: "task.batchTriggerAndWait(array)",
165173
call: () =>
166174
taskA.batchTriggerAndWait([
167-
{ payload: { i: 0 }, options: { debounce: DEBOUNCE } },
168-
{ payload: { i: 1 }, options: { debounce: DEBOUNCE } },
175+
{ payload: { i: 0 }, options: { debounce: debounceFor(0) } },
176+
{ payload: { i: 1 }, options: { debounce: debounceFor(1) } },
169177
]),
170178
},
171179
{
172180
name: "task.batchTriggerAndWait(asyncIterable)",
173181
call: () =>
174182
taskA.batchTriggerAndWait(
175183
asAsyncIterable([
176-
{ payload: { i: 0 }, options: { debounce: DEBOUNCE } },
177-
{ payload: { i: 1 }, options: { debounce: DEBOUNCE } },
184+
{ payload: { i: 0 }, options: { debounce: debounceFor(0) } },
185+
{ payload: { i: 1 }, options: { debounce: debounceFor(1) } },
178186
])
179187
),
180188
},
181189
{
182190
name: "tasks.batchTriggerAndWait(array)",
183191
call: () =>
184192
tasks.batchTriggerAndWait<typeof taskA>("task-a", [
185-
{ payload: { i: 0 }, options: { debounce: DEBOUNCE } },
186-
{ payload: { i: 1 }, options: { debounce: DEBOUNCE } },
193+
{ payload: { i: 0 }, options: { debounce: debounceFor(0) } },
194+
{ payload: { i: 1 }, options: { debounce: debounceFor(1) } },
187195
]),
188196
},
189197
{
190198
name: "batch.triggerAndWait(array)",
191199
call: () =>
192200
batch.triggerAndWait<typeof taskA | typeof taskB>([
193-
{ id: "task-a", payload: { i: 0 }, options: { debounce: DEBOUNCE } },
194-
{ id: "task-b", payload: { i: 1 }, options: { debounce: DEBOUNCE } },
201+
{ id: "task-a", payload: { i: 0 }, options: { debounce: debounceFor(0) } },
202+
{ id: "task-b", payload: { i: 1 }, options: { debounce: debounceFor(1) } },
195203
]),
196204
},
197205
{
198206
name: "batch.triggerAndWait(asyncIterable)",
199207
call: () =>
200208
batch.triggerAndWait<typeof taskA | typeof taskB>(
201209
asAsyncIterable([
202-
{ id: "task-a" as const, payload: { i: 0 }, options: { debounce: DEBOUNCE } },
203-
{ id: "task-b" as const, payload: { i: 1 }, options: { debounce: DEBOUNCE } },
210+
{ id: "task-a" as const, payload: { i: 0 }, options: { debounce: debounceFor(0) } },
211+
{ id: "task-b" as const, payload: { i: 1 }, options: { debounce: debounceFor(1) } },
204212
])
205213
),
206214
},
207215
{
208216
name: "batch.triggerByTaskAndWait(array)",
209217
call: () =>
210218
batch.triggerByTaskAndWait([
211-
{ task: taskA, payload: { i: 0 }, options: { debounce: DEBOUNCE } },
212-
{ task: taskB, payload: { i: 1 }, options: { debounce: DEBOUNCE } },
219+
{ task: taskA, payload: { i: 0 }, options: { debounce: debounceFor(0) } },
220+
{ task: taskB, payload: { i: 1 }, options: { debounce: debounceFor(1) } },
213221
]),
214222
},
215223
{
216224
name: "batch.triggerByTaskAndWait(asyncIterable)",
217225
call: () =>
218226
batch.triggerByTaskAndWait(
219227
asAsyncIterable([
220-
{ task: taskA, payload: { i: 0 }, options: { debounce: DEBOUNCE } },
221-
{ task: taskB, payload: { i: 1 }, options: { debounce: DEBOUNCE } },
228+
{ task: taskA, payload: { i: 0 }, options: { debounce: debounceFor(0) } },
229+
{ task: taskB, payload: { i: 1 }, options: { debounce: debounceFor(1) } },
222230
])
223231
),
224232
},
@@ -229,6 +237,6 @@ describe("batch trigger debounce forwarding", () => {
229237
await call();
230238
});
231239

232-
expect(capture.debounceOptions()).toEqual([DEBOUNCE, DEBOUNCE]);
240+
expect(capture.debounceOptions()).toEqual(EXPECTED);
233241
});
234242
});

packages/trigger-sdk/src/v3/shared.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ export async function batchTriggerById<TTask extends AnyTask>(
749749
lockToVersion: item.options?.version ?? scopedEnvVar("TRIGGER_VERSION"),
750750
debounce: item.options?.debounce,
751751
},
752-
};
752+
} satisfies BatchItemNDJSON;
753753
})
754754
);
755755

@@ -1005,7 +1005,7 @@ export async function batchTriggerByIdAndWait<TTask extends AnyTask>(
10051005
region: item.options?.region,
10061006
debounce: item.options?.debounce,
10071007
},
1008-
};
1008+
} satisfies BatchItemNDJSON;
10091009
})
10101010
);
10111011

@@ -1271,7 +1271,7 @@ export async function batchTriggerTasks<TTasks extends readonly AnyTask[]>(
12711271
lockToVersion: item.options?.version ?? scopedEnvVar("TRIGGER_VERSION"),
12721272
debounce: item.options?.debounce,
12731273
},
1274-
};
1274+
} satisfies BatchItemNDJSON;
12751275
})
12761276
);
12771277

@@ -1532,7 +1532,7 @@ export async function batchTriggerAndWaitTasks<TTasks extends readonly AnyTask[]
15321532
region: item.options?.region,
15331533
debounce: item.options?.debounce,
15341534
},
1535-
};
1535+
} satisfies BatchItemNDJSON;
15361536
})
15371537
);
15381538

@@ -2019,7 +2019,7 @@ async function* transformBatchItemsStream<TTask extends AnyTask>(
20192019
lockToVersion: item.options?.version ?? scopedEnvVar("TRIGGER_VERSION"),
20202020
debounce: item.options?.debounce,
20212021
},
2022-
};
2022+
} satisfies BatchItemNDJSON;
20232023
}
20242024
}
20252025

@@ -2071,7 +2071,7 @@ async function* transformBatchItemsStreamForWait<TTask extends AnyTask>(
20712071
region: item.options?.region,
20722072
debounce: item.options?.debounce,
20732073
},
2074-
};
2074+
} satisfies BatchItemNDJSON;
20752075
}
20762076
}
20772077

@@ -2122,7 +2122,7 @@ async function* transformBatchByTaskItemsStream<TTasks extends readonly AnyTask[
21222122
lockToVersion: item.options?.version ?? scopedEnvVar("TRIGGER_VERSION"),
21232123
debounce: item.options?.debounce,
21242124
},
2125-
};
2125+
} satisfies BatchItemNDJSON;
21262126
}
21272127
}
21282128

@@ -2173,7 +2173,7 @@ async function* transformBatchByTaskItemsStreamForWait<TTasks extends readonly A
21732173
region: item.options?.region,
21742174
debounce: item.options?.debounce,
21752175
},
2176-
};
2176+
} satisfies BatchItemNDJSON;
21772177
}
21782178
}
21792179

@@ -2226,7 +2226,7 @@ async function* transformSingleTaskBatchItemsStream<TPayload>(
22262226
lockToVersion: item.options?.version ?? scopedEnvVar("TRIGGER_VERSION"),
22272227
debounce: item.options?.debounce,
22282228
},
2229-
};
2229+
} satisfies BatchItemNDJSON;
22302230
}
22312231
}
22322232

@@ -2286,7 +2286,7 @@ async function* transformSingleTaskBatchItemsStreamForWait<TPayload>(
22862286
region: item.options?.region,
22872287
debounce: item.options?.debounce,
22882288
},
2289-
};
2289+
} satisfies BatchItemNDJSON;
22902290
}
22912291
}
22922292

@@ -2425,7 +2425,7 @@ async function batchTrigger_internal<TRunTypes extends AnyRunTypes>(
24252425
lockToVersion: item.options?.version ?? scopedEnvVar("TRIGGER_VERSION"),
24262426
debounce: item.options?.debounce,
24272427
},
2428-
};
2428+
} satisfies BatchItemNDJSON;
24292429
})
24302430
);
24312431

@@ -2857,7 +2857,7 @@ async function batchTriggerAndWait_internal<TIdentifier extends string, TPayload
28572857
region: item.options?.region,
28582858
debounce: item.options?.debounce,
28592859
},
2860-
};
2860+
} satisfies BatchItemNDJSON;
28612861
})
28622862
);
28632863

0 commit comments

Comments
 (0)