@trigger.dev/sdk 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,8 +10,11 @@ exports.triggerAndWait = triggerAndWait;
10
10
  exports.batchTriggerAndWait = batchTriggerAndWait;
11
11
  exports.triggerAndPoll = triggerAndPoll;
12
12
  exports.batchTrigger = batchTrigger;
13
+ exports.batchTriggerById = batchTriggerById;
14
+ exports.batchTriggerByIdAndWait = batchTriggerByIdAndWait;
15
+ exports.batchTriggerTasks = batchTriggerTasks;
16
+ exports.batchTriggerAndWaitTasks = batchTriggerAndWaitTasks;
13
17
  const api_1 = require("@opentelemetry/api");
14
- const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
15
18
  const v3_1 = require("@trigger.dev/core/v3");
16
19
  Object.defineProperty(exports, "SubtaskUnwrapError", { enumerable: true, get: function () { return v3_1.SubtaskUnwrapError; } });
17
20
  Object.defineProperty(exports, "TaskRunPromise", { enumerable: true, get: function () { return v3_1.TaskRunPromise; } });
@@ -39,11 +42,11 @@ function createTask(params) {
39
42
  ...options,
40
43
  });
41
44
  },
42
- batchTrigger: async (items) => {
45
+ batchTrigger: async (items, options) => {
43
46
  const taskMetadata = v3_1.taskCatalog.getTaskManifest(params.id);
44
47
  return await batchTrigger_internal(taskMetadata && taskMetadata.exportName
45
48
  ? `${taskMetadata.exportName}.batchTrigger()`
46
- : `batchTrigger()`, params.id, items, undefined, undefined, customQueue);
49
+ : `batchTrigger()`, params.id, items, options, undefined, undefined, customQueue);
47
50
  },
48
51
  triggerAndWait: (payload, options) => {
49
52
  const taskMetadata = v3_1.taskCatalog.getTaskManifest(params.id);
@@ -130,11 +133,11 @@ function createSchemaTask(params) {
130
133
  ...options,
131
134
  }, requestOptions);
132
135
  },
133
- batchTrigger: async (items, requestOptions) => {
136
+ batchTrigger: async (items, options, requestOptions) => {
134
137
  const taskMetadata = v3_1.taskCatalog.getTaskManifest(params.id);
135
138
  return await batchTrigger_internal(taskMetadata && taskMetadata.exportName
136
139
  ? `${taskMetadata.exportName}.batchTrigger()`
137
- : `batchTrigger()`, params.id, items, parsePayload, requestOptions, customQueue);
140
+ : `batchTrigger()`, params.id, items, options, parsePayload, requestOptions, customQueue);
138
141
  },
139
142
  triggerAndWait: (payload, options) => {
140
143
  const taskMetadata = v3_1.taskCatalog.getTaskManifest(params.id);
@@ -277,8 +280,540 @@ async function triggerAndPoll(id, payload, options, requestOptions) {
277
280
  const handle = await trigger(id, payload, options, requestOptions);
278
281
  return runs_js_1.runs.poll(handle, options, requestOptions);
279
282
  }
280
- async function batchTrigger(id, items, requestOptions) {
281
- return await batchTrigger_internal("tasks.batchTrigger()", id, items, undefined, requestOptions);
283
+ async function batchTrigger(id, items, options, requestOptions) {
284
+ return await batchTrigger_internal("tasks.batchTrigger()", id, items, options, undefined, requestOptions);
285
+ }
286
+ /**
287
+ * Triggers multiple runs of different tasks with specified payloads and options.
288
+ *
289
+ * @template TTask - The type of task(s) to be triggered, extends AnyTask
290
+ *
291
+ * @param {Array<BatchByIdItem<InferRunTypes<TTask>>>} items - Array of task items to trigger
292
+ * @param {BatchTriggerOptions} [options] - Optional batch-level trigger options
293
+ * @param {TriggerApiRequestOptions} [requestOptions] - Optional API request configuration
294
+ *
295
+ * @returns {Promise<BatchRunHandleFromTypes<InferRunTypes<TTask>>>} A promise that resolves with the batch run handle
296
+ * containing batch ID, cached status, idempotency info, runs, and public access token
297
+ *
298
+ * @example
299
+ * ```ts
300
+ * import { batch } from "@trigger.dev/sdk/v3";
301
+ * import type { myTask1, myTask2 } from "~/trigger/myTasks";
302
+ *
303
+ * // Trigger multiple tasks with different payloads
304
+ * const result = await batch.trigger<typeof myTask1 | typeof myTask2>([
305
+ * {
306
+ * id: "my-task-1",
307
+ * payload: { some: "data" },
308
+ * options: {
309
+ * queue: "default",
310
+ * concurrencyKey: "key",
311
+ * idempotencyKey: "unique-key",
312
+ * delay: "5m",
313
+ * tags: ["tag1", "tag2"]
314
+ * }
315
+ * },
316
+ * {
317
+ * id: "my-task-2",
318
+ * payload: { other: "data" }
319
+ * }
320
+ * ]);
321
+ * ```
322
+ *
323
+ * @description
324
+ * Each task item in the array can include:
325
+ * - `id`: The unique identifier of the task
326
+ * - `payload`: The data to pass to the task
327
+ * - `options`: Optional task-specific settings including:
328
+ * - `queue`: Specify a queue for the task
329
+ * - `concurrencyKey`: Control concurrent execution
330
+ * - `idempotencyKey`: Prevent duplicate runs
331
+ * - `idempotencyKeyTTL`: Time-to-live for idempotency key
332
+ * - `delay`: Delay before task execution
333
+ * - `ttl`: Time-to-live for the task
334
+ * - `tags`: Array of tags for the task
335
+ * - `maxAttempts`: Maximum retry attempts
336
+ * - `metadata`: Additional metadata
337
+ * - `maxDuration`: Maximum execution duration
338
+ */
339
+ async function batchTriggerById(items, options, requestOptions) {
340
+ const apiClient = v3_1.apiClientManager.clientOrThrow();
341
+ const response = await apiClient.batchTriggerV2({
342
+ items: await Promise.all(items.map(async (item) => {
343
+ const taskMetadata = v3_1.taskCatalog.getTask(item.id);
344
+ const parsedPayload = taskMetadata?.fns.parsePayload
345
+ ? await taskMetadata?.fns.parsePayload(item.payload)
346
+ : item.payload;
347
+ const payloadPacket = await (0, v3_1.stringifyIO)(parsedPayload);
348
+ return {
349
+ task: item.id,
350
+ payload: payloadPacket.data,
351
+ options: {
352
+ queue: item.options?.queue,
353
+ concurrencyKey: item.options?.concurrencyKey,
354
+ test: v3_1.taskContext.ctx?.run.isTest,
355
+ payloadType: payloadPacket.dataType,
356
+ idempotencyKey: await (0, v3_1.makeIdempotencyKey)(item.options?.idempotencyKey),
357
+ idempotencyKeyTTL: item.options?.idempotencyKeyTTL,
358
+ delay: item.options?.delay,
359
+ ttl: item.options?.ttl,
360
+ tags: item.options?.tags,
361
+ maxAttempts: item.options?.maxAttempts,
362
+ parentAttempt: v3_1.taskContext.ctx?.attempt.id,
363
+ metadata: item.options?.metadata,
364
+ maxDuration: item.options?.maxDuration,
365
+ },
366
+ };
367
+ })),
368
+ }, {
369
+ spanParentAsLink: true,
370
+ idempotencyKey: await (0, v3_1.makeIdempotencyKey)(options?.idempotencyKey),
371
+ idempotencyKeyTTL: options?.idempotencyKeyTTL,
372
+ }, {
373
+ name: "batch.trigger()",
374
+ tracer: tracer_js_1.tracer,
375
+ icon: "trigger",
376
+ onResponseBody(body, span) {
377
+ if (body && typeof body === "object" && !Array.isArray(body)) {
378
+ if ("id" in body && typeof body.id === "string") {
379
+ span.setAttribute("batchId", body.id);
380
+ }
381
+ if ("runs" in body && Array.isArray(body.runs)) {
382
+ span.setAttribute("runCount", body.runs.length);
383
+ }
384
+ if ("isCached" in body && typeof body.isCached === "boolean") {
385
+ if (body.isCached) {
386
+ console.warn(`Result is a cached response because the request was idempotent.`);
387
+ }
388
+ span.setAttribute("isCached", body.isCached);
389
+ }
390
+ if ("idempotencyKey" in body && typeof body.idempotencyKey === "string") {
391
+ span.setAttribute("idempotencyKey", body.idempotencyKey);
392
+ }
393
+ }
394
+ },
395
+ ...requestOptions,
396
+ });
397
+ const handle = {
398
+ batchId: response.id,
399
+ isCached: response.isCached,
400
+ idempotencyKey: response.idempotencyKey,
401
+ runs: response.runs,
402
+ publicAccessToken: response.publicAccessToken,
403
+ };
404
+ return handle;
405
+ }
406
+ /**
407
+ * Triggers multiple tasks and waits for all of them to complete before returning their results.
408
+ * This function must be called from within a task.run() context.
409
+ *
410
+ * @template TTask - Union type of tasks to be triggered, extends AnyTask
411
+ *
412
+ * @param {Array<BatchByIdAndWaitItem<InferRunTypes<TTask>>>} items - Array of task items to trigger
413
+ * @param {TriggerApiRequestOptions} [requestOptions] - Optional API request configuration
414
+ *
415
+ * @returns {Promise<BatchByIdResult<TTask>>} A promise that resolves with the batch results, including
416
+ * success/failure status and strongly-typed outputs for each task
417
+ *
418
+ * @throws {Error} If called outside of a task.run() context
419
+ * @throws {Error} If no API client is configured
420
+ *
421
+ * @example
422
+ * ```ts
423
+ * import { batch, task } from "@trigger.dev/sdk/v3";
424
+ *
425
+ * export const parentTask = task({
426
+ * id: "parent-task",
427
+ * run: async (payload: string) => {
428
+ * const results = await batch.triggerAndWait<typeof childTask1 | typeof childTask2>([
429
+ * {
430
+ * id: "child-task-1",
431
+ * payload: { foo: "World" },
432
+ * options: {
433
+ * queue: "default",
434
+ * delay: "5m",
435
+ * tags: ["batch", "child1"]
436
+ * }
437
+ * },
438
+ * {
439
+ * id: "child-task-2",
440
+ * payload: { bar: 42 }
441
+ * }
442
+ * ]);
443
+ *
444
+ * // Type-safe result handling
445
+ * for (const result of results) {
446
+ * if (result.ok) {
447
+ * switch (result.taskIdentifier) {
448
+ * case "child-task-1":
449
+ * console.log("Child task 1 output:", result.output); // string type
450
+ * break;
451
+ * case "child-task-2":
452
+ * console.log("Child task 2 output:", result.output); // number type
453
+ * break;
454
+ * }
455
+ * } else {
456
+ * console.error("Task failed:", result.error);
457
+ * }
458
+ * }
459
+ * }
460
+ * });
461
+ * ```
462
+ *
463
+ * @description
464
+ * Each task item in the array can include:
465
+ * - `id`: The task identifier (must match one of the tasks in the union type)
466
+ * - `payload`: Strongly-typed payload matching the task's input type
467
+ * - `options`: Optional task-specific settings including:
468
+ * - `queue`: Specify a queue for the task
469
+ * - `concurrencyKey`: Control concurrent execution
470
+ * - `delay`: Delay before task execution
471
+ * - `ttl`: Time-to-live for the task
472
+ * - `tags`: Array of tags for the task
473
+ * - `maxAttempts`: Maximum retry attempts
474
+ * - `metadata`: Additional metadata
475
+ * - `maxDuration`: Maximum execution duration
476
+ *
477
+ * The function provides full type safety for:
478
+ * - Task IDs
479
+ * - Payload types
480
+ * - Return value types
481
+ * - Error handling
482
+ */
483
+ async function batchTriggerByIdAndWait(items, requestOptions) {
484
+ const ctx = v3_1.taskContext.ctx;
485
+ if (!ctx) {
486
+ throw new Error("batchTriggerAndWait can only be used from inside a task.run()");
487
+ }
488
+ const apiClient = v3_1.apiClientManager.clientOrThrow();
489
+ return await tracer_js_1.tracer.startActiveSpan("batch.triggerAndWait()", async (span) => {
490
+ const response = await apiClient.batchTriggerV2({
491
+ items: await Promise.all(items.map(async (item) => {
492
+ const taskMetadata = v3_1.taskCatalog.getTask(item.id);
493
+ const parsedPayload = taskMetadata?.fns.parsePayload
494
+ ? await taskMetadata?.fns.parsePayload(item.payload)
495
+ : item.payload;
496
+ const payloadPacket = await (0, v3_1.stringifyIO)(parsedPayload);
497
+ return {
498
+ task: item.id,
499
+ payload: payloadPacket.data,
500
+ options: {
501
+ lockToVersion: v3_1.taskContext.worker?.version,
502
+ queue: item.options?.queue,
503
+ concurrencyKey: item.options?.concurrencyKey,
504
+ test: v3_1.taskContext.ctx?.run.isTest,
505
+ payloadType: payloadPacket.dataType,
506
+ delay: item.options?.delay,
507
+ ttl: item.options?.ttl,
508
+ tags: item.options?.tags,
509
+ maxAttempts: item.options?.maxAttempts,
510
+ metadata: item.options?.metadata,
511
+ maxDuration: item.options?.maxDuration,
512
+ },
513
+ };
514
+ })),
515
+ dependentAttempt: ctx.attempt.id,
516
+ }, {}, requestOptions);
517
+ span.setAttribute("batchId", response.id);
518
+ span.setAttribute("runCount", response.runs.length);
519
+ span.setAttribute("isCached", response.isCached);
520
+ if (response.isCached) {
521
+ console.warn(`Result is a cached response because the request was idempotent.`);
522
+ }
523
+ if (response.idempotencyKey) {
524
+ span.setAttribute("idempotencyKey", response.idempotencyKey);
525
+ }
526
+ const result = await v3_1.runtime.waitForBatch({
527
+ id: response.id,
528
+ runs: response.runs.map((run) => run.id),
529
+ ctx,
530
+ });
531
+ const runs = await handleBatchTaskRunExecutionResultV2(result.items);
532
+ return {
533
+ id: result.id,
534
+ runs,
535
+ };
536
+ }, {
537
+ kind: api_1.SpanKind.PRODUCER,
538
+ });
539
+ }
540
+ /**
541
+ * Triggers multiple tasks and waits for all of them to complete before returning their results.
542
+ * This function must be called from within a task.run() context.
543
+ *
544
+ * @template TTask - Union type of tasks to be triggered, extends AnyTask
545
+ *
546
+ * @param {Array<BatchByIdAndWaitItem<InferRunTypes<TTask>>>} items - Array of task items to trigger
547
+ * @param {TriggerApiRequestOptions} [requestOptions] - Optional API request configuration
548
+ *
549
+ * @returns {Promise<BatchByIdResult<TTask>>} A promise that resolves with the batch results, including
550
+ * success/failure status and strongly-typed outputs for each task
551
+ *
552
+ * @throws {Error} If called outside of a task.run() context
553
+ * @throws {Error} If no API client is configured
554
+ *
555
+ * @example
556
+ * ```ts
557
+ * import { batch, task } from "@trigger.dev/sdk/v3";
558
+ *
559
+ * export const parentTask = task({
560
+ * id: "parent-task",
561
+ * run: async (payload: string) => {
562
+ * const results = await batch.triggerAndWait<typeof childTask1 | typeof childTask2>([
563
+ * {
564
+ * id: "child-task-1",
565
+ * payload: { foo: "World" },
566
+ * options: {
567
+ * queue: "default",
568
+ * delay: "5m",
569
+ * tags: ["batch", "child1"]
570
+ * }
571
+ * },
572
+ * {
573
+ * id: "child-task-2",
574
+ * payload: { bar: 42 }
575
+ * }
576
+ * ]);
577
+ *
578
+ * // Type-safe result handling
579
+ * for (const result of results) {
580
+ * if (result.ok) {
581
+ * switch (result.taskIdentifier) {
582
+ * case "child-task-1":
583
+ * console.log("Child task 1 output:", result.output); // string type
584
+ * break;
585
+ * case "child-task-2":
586
+ * console.log("Child task 2 output:", result.output); // number type
587
+ * break;
588
+ * }
589
+ * } else {
590
+ * console.error("Task failed:", result.error);
591
+ * }
592
+ * }
593
+ * }
594
+ * });
595
+ * ```
596
+ *
597
+ * @description
598
+ * Each task item in the array can include:
599
+ * - `id`: The task identifier (must match one of the tasks in the union type)
600
+ * - `payload`: Strongly-typed payload matching the task's input type
601
+ * - `options`: Optional task-specific settings including:
602
+ * - `queue`: Specify a queue for the task
603
+ * - `concurrencyKey`: Control concurrent execution
604
+ * - `delay`: Delay before task execution
605
+ * - `ttl`: Time-to-live for the task
606
+ * - `tags`: Array of tags for the task
607
+ * - `maxAttempts`: Maximum retry attempts
608
+ * - `metadata`: Additional metadata
609
+ * - `maxDuration`: Maximum execution duration
610
+ *
611
+ * The function provides full type safety for:
612
+ * - Task IDs
613
+ * - Payload types
614
+ * - Return value types
615
+ * - Error handling
616
+ */
617
+ async function batchTriggerTasks(items, options, requestOptions) {
618
+ const apiClient = v3_1.apiClientManager.clientOrThrow();
619
+ const response = await apiClient.batchTriggerV2({
620
+ items: await Promise.all(items.map(async (item) => {
621
+ const taskMetadata = v3_1.taskCatalog.getTask(item.task.id);
622
+ const parsedPayload = taskMetadata?.fns.parsePayload
623
+ ? await taskMetadata?.fns.parsePayload(item.payload)
624
+ : item.payload;
625
+ const payloadPacket = await (0, v3_1.stringifyIO)(parsedPayload);
626
+ return {
627
+ task: item.task.id,
628
+ payload: payloadPacket.data,
629
+ options: {
630
+ queue: item.options?.queue,
631
+ concurrencyKey: item.options?.concurrencyKey,
632
+ test: v3_1.taskContext.ctx?.run.isTest,
633
+ payloadType: payloadPacket.dataType,
634
+ idempotencyKey: await (0, v3_1.makeIdempotencyKey)(item.options?.idempotencyKey),
635
+ idempotencyKeyTTL: item.options?.idempotencyKeyTTL,
636
+ delay: item.options?.delay,
637
+ ttl: item.options?.ttl,
638
+ tags: item.options?.tags,
639
+ maxAttempts: item.options?.maxAttempts,
640
+ parentAttempt: v3_1.taskContext.ctx?.attempt.id,
641
+ metadata: item.options?.metadata,
642
+ maxDuration: item.options?.maxDuration,
643
+ },
644
+ };
645
+ })),
646
+ }, {
647
+ spanParentAsLink: true,
648
+ idempotencyKey: await (0, v3_1.makeIdempotencyKey)(options?.idempotencyKey),
649
+ idempotencyKeyTTL: options?.idempotencyKeyTTL,
650
+ }, {
651
+ name: "batch.triggerByTask()",
652
+ tracer: tracer_js_1.tracer,
653
+ icon: "trigger",
654
+ onResponseBody(body, span) {
655
+ if (body && typeof body === "object" && !Array.isArray(body)) {
656
+ if ("id" in body && typeof body.id === "string") {
657
+ span.setAttribute("batchId", body.id);
658
+ }
659
+ if ("runs" in body && Array.isArray(body.runs)) {
660
+ span.setAttribute("runCount", body.runs.length);
661
+ }
662
+ if ("isCached" in body && typeof body.isCached === "boolean") {
663
+ if (body.isCached) {
664
+ console.warn(`Result is a cached response because the request was idempotent.`);
665
+ }
666
+ span.setAttribute("isCached", body.isCached);
667
+ }
668
+ if ("idempotencyKey" in body && typeof body.idempotencyKey === "string") {
669
+ span.setAttribute("idempotencyKey", body.idempotencyKey);
670
+ }
671
+ }
672
+ },
673
+ ...requestOptions,
674
+ });
675
+ const handle = {
676
+ batchId: response.id,
677
+ isCached: response.isCached,
678
+ idempotencyKey: response.idempotencyKey,
679
+ runs: response.runs,
680
+ publicAccessToken: response.publicAccessToken,
681
+ };
682
+ return handle;
683
+ }
684
+ /**
685
+ * Triggers multiple tasks and waits for all of them to complete before returning their results.
686
+ * This function must be called from within a task.run() context.
687
+ *
688
+ * @template TTask - Union type of tasks to be triggered, extends AnyTask
689
+ *
690
+ * @param {Array<BatchByIdAndWaitItem<InferRunTypes<TTask>>>} items - Array of task items to trigger
691
+ * @param {TriggerApiRequestOptions} [requestOptions] - Optional API request configuration
692
+ *
693
+ * @returns {Promise<BatchByIdResult<TTask>>} A promise that resolves with the batch results, including
694
+ * success/failure status and strongly-typed outputs for each task
695
+ *
696
+ * @throws {Error} If called outside of a task.run() context
697
+ * @throws {Error} If no API client is configured
698
+ *
699
+ * @example
700
+ * ```ts
701
+ * import { batch, task } from "@trigger.dev/sdk/v3";
702
+ *
703
+ * export const parentTask = task({
704
+ * id: "parent-task",
705
+ * run: async (payload: string) => {
706
+ * const results = await batch.triggerAndWait<typeof childTask1 | typeof childTask2>([
707
+ * {
708
+ * id: "child-task-1",
709
+ * payload: { foo: "World" },
710
+ * options: {
711
+ * queue: "default",
712
+ * delay: "5m",
713
+ * tags: ["batch", "child1"]
714
+ * }
715
+ * },
716
+ * {
717
+ * id: "child-task-2",
718
+ * payload: { bar: 42 }
719
+ * }
720
+ * ]);
721
+ *
722
+ * // Type-safe result handling
723
+ * for (const result of results) {
724
+ * if (result.ok) {
725
+ * switch (result.taskIdentifier) {
726
+ * case "child-task-1":
727
+ * console.log("Child task 1 output:", result.output); // string type
728
+ * break;
729
+ * case "child-task-2":
730
+ * console.log("Child task 2 output:", result.output); // number type
731
+ * break;
732
+ * }
733
+ * } else {
734
+ * console.error("Task failed:", result.error);
735
+ * }
736
+ * }
737
+ * }
738
+ * });
739
+ * ```
740
+ *
741
+ * @description
742
+ * Each task item in the array can include:
743
+ * - `id`: The task identifier (must match one of the tasks in the union type)
744
+ * - `payload`: Strongly-typed payload matching the task's input type
745
+ * - `options`: Optional task-specific settings including:
746
+ * - `queue`: Specify a queue for the task
747
+ * - `concurrencyKey`: Control concurrent execution
748
+ * - `delay`: Delay before task execution
749
+ * - `ttl`: Time-to-live for the task
750
+ * - `tags`: Array of tags for the task
751
+ * - `maxAttempts`: Maximum retry attempts
752
+ * - `metadata`: Additional metadata
753
+ * - `maxDuration`: Maximum execution duration
754
+ *
755
+ * The function provides full type safety for:
756
+ * - Task IDs
757
+ * - Payload types
758
+ * - Return value types
759
+ * - Error handling
760
+ */
761
+ async function batchTriggerAndWaitTasks(items, requestOptions) {
762
+ const ctx = v3_1.taskContext.ctx;
763
+ if (!ctx) {
764
+ throw new Error("batchTriggerAndWait can only be used from inside a task.run()");
765
+ }
766
+ const apiClient = v3_1.apiClientManager.clientOrThrow();
767
+ return await tracer_js_1.tracer.startActiveSpan("batch.triggerByTaskAndWait()", async (span) => {
768
+ const response = await apiClient.batchTriggerV2({
769
+ items: await Promise.all(items.map(async (item) => {
770
+ const taskMetadata = v3_1.taskCatalog.getTask(item.task.id);
771
+ const parsedPayload = taskMetadata?.fns.parsePayload
772
+ ? await taskMetadata?.fns.parsePayload(item.payload)
773
+ : item.payload;
774
+ const payloadPacket = await (0, v3_1.stringifyIO)(parsedPayload);
775
+ return {
776
+ task: item.task.id,
777
+ payload: payloadPacket.data,
778
+ options: {
779
+ lockToVersion: v3_1.taskContext.worker?.version,
780
+ queue: item.options?.queue,
781
+ concurrencyKey: item.options?.concurrencyKey,
782
+ test: v3_1.taskContext.ctx?.run.isTest,
783
+ payloadType: payloadPacket.dataType,
784
+ delay: item.options?.delay,
785
+ ttl: item.options?.ttl,
786
+ tags: item.options?.tags,
787
+ maxAttempts: item.options?.maxAttempts,
788
+ metadata: item.options?.metadata,
789
+ maxDuration: item.options?.maxDuration,
790
+ },
791
+ };
792
+ })),
793
+ dependentAttempt: ctx.attempt.id,
794
+ }, {}, requestOptions);
795
+ span.setAttribute("batchId", response.id);
796
+ span.setAttribute("runCount", response.runs.length);
797
+ span.setAttribute("isCached", response.isCached);
798
+ if (response.isCached) {
799
+ console.warn(`Result is a cached response because the request was idempotent.`);
800
+ }
801
+ if (response.idempotencyKey) {
802
+ span.setAttribute("idempotencyKey", response.idempotencyKey);
803
+ }
804
+ const result = await v3_1.runtime.waitForBatch({
805
+ id: response.id,
806
+ runs: response.runs.map((run) => run.id),
807
+ ctx,
808
+ });
809
+ const runs = await handleBatchTaskRunExecutionResultV2(result.items);
810
+ return {
811
+ id: result.id,
812
+ runs,
813
+ };
814
+ }, {
815
+ kind: api_1.SpanKind.PRODUCER,
816
+ });
282
817
  }
283
818
  async function trigger_internal(name, id, payload, parsePayload, options, requestOptions) {
284
819
  const apiClient = v3_1.apiClientManager.clientOrThrow();
@@ -292,6 +827,7 @@ async function trigger_internal(name, id, payload, parsePayload, options, reques
292
827
  test: v3_1.taskContext.ctx?.run.isTest,
293
828
  payloadType: payloadPacket.dataType,
294
829
  idempotencyKey: await (0, v3_1.makeIdempotencyKey)(options?.idempotencyKey),
830
+ idempotencyKeyTTL: options?.idempotencyKeyTTL,
295
831
  delay: options?.delay,
296
832
  ttl: options?.ttl,
297
833
  tags: options?.tags,
@@ -306,30 +842,25 @@ async function trigger_internal(name, id, payload, parsePayload, options, reques
306
842
  name,
307
843
  tracer: tracer_js_1.tracer,
308
844
  icon: "trigger",
309
- attributes: {
310
- [semantic_conventions_1.SEMATTRS_MESSAGING_OPERATION]: "publish",
311
- ["messaging.client_id"]: v3_1.taskContext.worker?.id,
312
- [semantic_conventions_1.SEMATTRS_MESSAGING_SYSTEM]: "trigger.dev",
313
- },
314
845
  onResponseBody: (body, span) => {
315
- body &&
316
- typeof body === "object" &&
317
- !Array.isArray(body) &&
318
- "id" in body &&
319
- typeof body.id === "string" &&
320
- span.setAttribute("messaging.message.id", body.id);
846
+ if (body && typeof body === "object" && !Array.isArray(body)) {
847
+ if ("id" in body && typeof body.id === "string") {
848
+ span.setAttribute("runId", body.id);
849
+ }
850
+ }
321
851
  },
322
852
  ...requestOptions,
323
853
  });
324
854
  return handle;
325
855
  }
326
- async function batchTrigger_internal(name, id, items, parsePayload, requestOptions, queue) {
856
+ async function batchTrigger_internal(name, taskIdentifier, items, options, parsePayload, requestOptions, queue) {
327
857
  const apiClient = v3_1.apiClientManager.clientOrThrow();
328
- const response = await apiClient.batchTriggerTask(id, {
858
+ const response = await apiClient.batchTriggerV2({
329
859
  items: await Promise.all(items.map(async (item) => {
330
860
  const parsedPayload = parsePayload ? await parsePayload(item.payload) : item.payload;
331
861
  const payloadPacket = await (0, v3_1.stringifyIO)(parsedPayload);
332
862
  return {
863
+ task: taskIdentifier,
333
864
  payload: payloadPacket.data,
334
865
  options: {
335
866
  queue: item.options?.queue ?? queue,
@@ -337,6 +868,7 @@ async function batchTrigger_internal(name, id, items, parsePayload, requestOptio
337
868
  test: v3_1.taskContext.ctx?.run.isTest,
338
869
  payloadType: payloadPacket.dataType,
339
870
  idempotencyKey: await (0, v3_1.makeIdempotencyKey)(item.options?.idempotencyKey),
871
+ idempotencyKeyTTL: item.options?.idempotencyKeyTTL,
340
872
  delay: item.options?.delay,
341
873
  ttl: item.options?.ttl,
342
874
  tags: item.options?.tags,
@@ -347,20 +879,40 @@ async function batchTrigger_internal(name, id, items, parsePayload, requestOptio
347
879
  },
348
880
  };
349
881
  })),
350
- }, { spanParentAsLink: true }, {
882
+ }, {
883
+ spanParentAsLink: true,
884
+ idempotencyKey: await (0, v3_1.makeIdempotencyKey)(options?.idempotencyKey),
885
+ idempotencyKeyTTL: options?.idempotencyKeyTTL,
886
+ }, {
351
887
  name,
352
888
  tracer: tracer_js_1.tracer,
353
889
  icon: "trigger",
354
- attributes: {
355
- [semantic_conventions_1.SEMATTRS_MESSAGING_OPERATION]: "publish",
356
- ["messaging.client_id"]: v3_1.taskContext.worker?.id,
357
- [semantic_conventions_1.SEMATTRS_MESSAGING_SYSTEM]: "trigger.dev",
890
+ onResponseBody(body, span) {
891
+ if (body && typeof body === "object" && !Array.isArray(body)) {
892
+ if ("id" in body && typeof body.id === "string") {
893
+ span.setAttribute("batchId", body.id);
894
+ }
895
+ if ("runs" in body && Array.isArray(body.runs)) {
896
+ span.setAttribute("runCount", body.runs.length);
897
+ }
898
+ if ("isCached" in body && typeof body.isCached === "boolean") {
899
+ if (body.isCached) {
900
+ console.warn(`Result is a cached response because the request was idempotent.`);
901
+ }
902
+ span.setAttribute("isCached", body.isCached);
903
+ }
904
+ if ("idempotencyKey" in body && typeof body.idempotencyKey === "string") {
905
+ span.setAttribute("idempotencyKey", body.idempotencyKey);
906
+ }
907
+ }
358
908
  },
359
909
  ...requestOptions,
360
910
  });
361
911
  const handle = {
362
- batchId: response.batchId,
363
- runs: response.runs.map((id) => ({ id })),
912
+ batchId: response.id,
913
+ isCached: response.isCached,
914
+ idempotencyKey: response.idempotencyKey,
915
+ runs: response.runs,
364
916
  publicAccessToken: response.publicAccessToken,
365
917
  };
366
918
  return handle;
@@ -383,7 +935,6 @@ async function triggerAndWait_internal(name, id, payload, parsePayload, options,
383
935
  concurrencyKey: options?.concurrencyKey,
384
936
  test: v3_1.taskContext.ctx?.run.isTest,
385
937
  payloadType: payloadPacket.dataType,
386
- idempotencyKey: await (0, v3_1.makeIdempotencyKey)(options?.idempotencyKey),
387
938
  delay: options?.delay,
388
939
  ttl: options?.ttl,
389
940
  tags: options?.tags,
@@ -392,31 +943,15 @@ async function triggerAndWait_internal(name, id, payload, parsePayload, options,
392
943
  maxDuration: options?.maxDuration,
393
944
  },
394
945
  }, {}, requestOptions);
395
- span.setAttribute("messaging.message.id", response.id);
396
- if (options?.idempotencyKey) {
397
- // If an idempotency key is provided, we can check if the result is already available
398
- const result = await apiClient.getRunResult(response.id);
399
- if (result) {
400
- v3_1.logger.log(`Result reused from previous task run with idempotency key '${options.idempotencyKey}'.`, {
401
- runId: response.id,
402
- idempotencyKey: options.idempotencyKey,
403
- });
404
- return await handleTaskRunExecutionResult(result);
405
- }
406
- }
946
+ span.setAttribute("runId", response.id);
407
947
  const result = await v3_1.runtime.waitForTask({
408
948
  id: response.id,
409
949
  ctx,
410
950
  });
411
- return await handleTaskRunExecutionResult(result);
951
+ return await handleTaskRunExecutionResult(result, id);
412
952
  }, {
413
953
  kind: api_1.SpanKind.PRODUCER,
414
954
  attributes: {
415
- [v3_1.SemanticInternalAttributes.STYLE_ICON]: "trigger",
416
- [semantic_conventions_1.SEMATTRS_MESSAGING_OPERATION]: "publish",
417
- ["messaging.client_id"]: v3_1.taskContext.worker?.id,
418
- [semantic_conventions_1.SEMATTRS_MESSAGING_DESTINATION]: id,
419
- [semantic_conventions_1.SEMATTRS_MESSAGING_SYSTEM]: "trigger.dev",
420
955
  ...(0, v3_1.accessoryAttributes)({
421
956
  items: [
422
957
  {
@@ -436,11 +971,12 @@ async function batchTriggerAndWait_internal(name, id, items, parsePayload, reque
436
971
  }
437
972
  const apiClient = v3_1.apiClientManager.clientOrThrow();
438
973
  return await tracer_js_1.tracer.startActiveSpan(name, async (span) => {
439
- const response = await apiClient.batchTriggerTask(id, {
974
+ const response = await apiClient.batchTriggerV2({
440
975
  items: await Promise.all(items.map(async (item) => {
441
976
  const parsedPayload = parsePayload ? await parsePayload(item.payload) : item.payload;
442
977
  const payloadPacket = await (0, v3_1.stringifyIO)(parsedPayload);
443
978
  return {
979
+ task: id,
444
980
  payload: payloadPacket.data,
445
981
  options: {
446
982
  lockToVersion: v3_1.taskContext.worker?.version,
@@ -448,7 +984,6 @@ async function batchTriggerAndWait_internal(name, id, items, parsePayload, reque
448
984
  concurrencyKey: item.options?.concurrencyKey,
449
985
  test: v3_1.taskContext.ctx?.run.isTest,
450
986
  payloadType: payloadPacket.dataType,
451
- idempotencyKey: await (0, v3_1.makeIdempotencyKey)(item.options?.idempotencyKey),
452
987
  delay: item.options?.delay,
453
988
  ttl: item.options?.ttl,
454
989
  tags: item.options?.tags,
@@ -460,52 +995,21 @@ async function batchTriggerAndWait_internal(name, id, items, parsePayload, reque
460
995
  })),
461
996
  dependentAttempt: ctx.attempt.id,
462
997
  }, {}, requestOptions);
463
- span.setAttribute("messaging.message.id", response.batchId);
464
- const getBatchResults = async () => {
465
- // We need to check if the results are already available, but only if any of the items options has an idempotency key
466
- const hasIdempotencyKey = items.some((item) => item.options?.idempotencyKey);
467
- if (hasIdempotencyKey) {
468
- const results = await apiClient.getBatchResults(response.batchId);
469
- if (results) {
470
- return results;
471
- }
472
- }
473
- return {
474
- id: response.batchId,
475
- items: [],
476
- };
477
- };
478
- const existingResults = await getBatchResults();
479
- const incompleteRuns = response.runs.filter((runId) => !existingResults.items.some((item) => item.id === runId));
480
- if (incompleteRuns.length === 0) {
481
- v3_1.logger.log(`Results reused from previous task runs because of the provided idempotency keys.`);
482
- // All runs are already completed
483
- const runs = await handleBatchTaskRunExecutionResult(existingResults.items);
484
- return {
485
- id: existingResults.id,
486
- runs,
487
- };
998
+ span.setAttribute("batchId", response.id);
999
+ span.setAttribute("runCount", response.runs.length);
1000
+ span.setAttribute("isCached", response.isCached);
1001
+ if (response.isCached) {
1002
+ console.warn(`Result is a cached response because the request was idempotent.`);
1003
+ }
1004
+ if (response.idempotencyKey) {
1005
+ span.setAttribute("idempotencyKey", response.idempotencyKey);
488
1006
  }
489
1007
  const result = await v3_1.runtime.waitForBatch({
490
- id: response.batchId,
491
- runs: incompleteRuns,
1008
+ id: response.id,
1009
+ runs: response.runs.map((run) => run.id),
492
1010
  ctx,
493
1011
  });
494
- // Combine the already completed runs with the newly completed runs, ordered by the original order
495
- const combinedItems = [];
496
- for (const runId of response.runs) {
497
- const existingItem = existingResults.items.find((item) => item.id === runId);
498
- if (existingItem) {
499
- combinedItems.push(existingItem);
500
- }
501
- else {
502
- const newItem = result.items.find((item) => item.id === runId);
503
- if (newItem) {
504
- combinedItems.push(newItem);
505
- }
506
- }
507
- }
508
- const runs = await handleBatchTaskRunExecutionResult(combinedItems);
1012
+ const runs = await handleBatchTaskRunExecutionResult(result.items, id);
509
1013
  return {
510
1014
  id: result.id,
511
1015
  runs,
@@ -513,12 +1017,6 @@ async function batchTriggerAndWait_internal(name, id, items, parsePayload, reque
513
1017
  }, {
514
1018
  kind: api_1.SpanKind.PRODUCER,
515
1019
  attributes: {
516
- [v3_1.SemanticInternalAttributes.STYLE_ICON]: "trigger",
517
- ["messaging.batch.message_count"]: items.length,
518
- [semantic_conventions_1.SEMATTRS_MESSAGING_OPERATION]: "publish",
519
- ["messaging.client_id"]: v3_1.taskContext.worker?.id,
520
- [semantic_conventions_1.SEMATTRS_MESSAGING_DESTINATION]: id,
521
- [semantic_conventions_1.SEMATTRS_MESSAGING_SYSTEM]: "trigger.dev",
522
1020
  ...(0, v3_1.accessoryAttributes)({
523
1021
  items: [
524
1022
  {
@@ -531,17 +1029,35 @@ async function batchTriggerAndWait_internal(name, id, items, parsePayload, reque
531
1029
  },
532
1030
  });
533
1031
  }
534
- async function handleBatchTaskRunExecutionResult(items) {
1032
+ async function handleBatchTaskRunExecutionResult(items, taskIdentifier) {
1033
+ const someObjectStoreOutputs = items.some((item) => item.ok && item.outputType === "application/store");
1034
+ if (!someObjectStoreOutputs) {
1035
+ const results = await Promise.all(items.map(async (item) => {
1036
+ return await handleTaskRunExecutionResult(item, taskIdentifier);
1037
+ }));
1038
+ return results;
1039
+ }
1040
+ return await tracer_js_1.tracer.startActiveSpan("store.downloadPayloads", async (span) => {
1041
+ const results = await Promise.all(items.map(async (item) => {
1042
+ return await handleTaskRunExecutionResult(item, taskIdentifier);
1043
+ }));
1044
+ return results;
1045
+ }, {
1046
+ kind: api_1.SpanKind.INTERNAL,
1047
+ [v3_1.SemanticInternalAttributes.STYLE_ICON]: "cloud-download",
1048
+ });
1049
+ }
1050
+ async function handleBatchTaskRunExecutionResultV2(items) {
535
1051
  const someObjectStoreOutputs = items.some((item) => item.ok && item.outputType === "application/store");
536
1052
  if (!someObjectStoreOutputs) {
537
1053
  const results = await Promise.all(items.map(async (item) => {
538
- return await handleTaskRunExecutionResult(item);
1054
+ return await handleTaskRunExecutionResult(item, item.taskIdentifier ?? "unknown");
539
1055
  }));
540
1056
  return results;
541
1057
  }
542
1058
  return await tracer_js_1.tracer.startActiveSpan("store.downloadPayloads", async (span) => {
543
1059
  const results = await Promise.all(items.map(async (item) => {
544
- return await handleTaskRunExecutionResult(item);
1060
+ return await handleTaskRunExecutionResult(item, item.taskIdentifier ?? "unknown");
545
1061
  }));
546
1062
  return results;
547
1063
  }, {
@@ -549,13 +1065,14 @@ async function handleBatchTaskRunExecutionResult(items) {
549
1065
  [v3_1.SemanticInternalAttributes.STYLE_ICON]: "cloud-download",
550
1066
  });
551
1067
  }
552
- async function handleTaskRunExecutionResult(execution) {
1068
+ async function handleTaskRunExecutionResult(execution, taskIdentifier) {
553
1069
  if (execution.ok) {
554
1070
  const outputPacket = { data: execution.output, dataType: execution.outputType };
555
1071
  const importedPacket = await (0, v3_1.conditionallyImportPacket)(outputPacket, tracer_js_1.tracer);
556
1072
  return {
557
1073
  ok: true,
558
1074
  id: execution.id,
1075
+ taskIdentifier: (execution.taskIdentifier ?? taskIdentifier),
559
1076
  output: await (0, v3_1.parsePacket)(importedPacket),
560
1077
  };
561
1078
  }
@@ -563,6 +1080,7 @@ async function handleTaskRunExecutionResult(execution) {
563
1080
  return {
564
1081
  ok: false,
565
1082
  id: execution.id,
1083
+ taskIdentifier: (execution.taskIdentifier ?? taskIdentifier),
566
1084
  error: (0, v3_1.createErrorTaskError)(execution.error),
567
1085
  };
568
1086
  }