From 2c9801886c9284c243d64d31527182bbbfcdd4dd Mon Sep 17 00:00:00 2001 From: nicktrn <55853254+nicktrn@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:58:52 +0100 Subject: [PATCH 1/3] add duration wait threshold --- packages/trigger-sdk/src/v3/wait.ts | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/packages/trigger-sdk/src/v3/wait.ts b/packages/trigger-sdk/src/v3/wait.ts index fe5c16e93b..0e57122853 100644 --- a/packages/trigger-sdk/src/v3/wait.ts +++ b/packages/trigger-sdk/src/v3/wait.ts @@ -369,6 +369,12 @@ export class WaitpointTimeoutError extends Error { } } +const DURATION_WAIT_CHARGE_THRESHOLD_MS = 5000; + +function printWaitBelowThreshold() { + console.warn(`Waits of ${DURATION_WAIT_CHARGE_THRESHOLD_MS / 1000}s or less are charged.`); +} + export const wait = { for: async (options: WaitForOptions) => { const ctx = taskContext.ctx; @@ -380,6 +386,36 @@ export const wait = { const start = Date.now(); const durationInMs = calculateDurationInMs(options); + + if (durationInMs <= DURATION_WAIT_CHARGE_THRESHOLD_MS) { + return tracer.startActiveSpan( + `wait.for()`, + async (span) => { + if (durationInMs <= 0) { + return; + } + + printWaitBelowThreshold(); + + await new Promise((resolve) => setTimeout(resolve, durationInMs)); + }, + { + attributes: { + [SemanticInternalAttributes.STYLE_ICON]: "wait", + ...accessoryAttributes({ + items: [ + { + text: nameForWaitOptions(options), + variant: "normal", + }, + ], + style: "codepath", + }), + }, + } + ); + } + const date = new Date(start + durationInMs); const result = await apiClient.waitForDuration(ctx.run.id, { date: date, @@ -417,6 +453,46 @@ export const wait = { throw new Error("wait.forToken can only be used from inside a task.run()"); } + // Calculate duration in ms + const durationInMs = options.date.getTime() - Date.now(); + + if (durationInMs <= DURATION_WAIT_CHARGE_THRESHOLD_MS) { + return tracer.startActiveSpan( + `wait.for()`, + async (span) => { + if (durationInMs === 0) { + return; + } + + if (durationInMs < 0) { + if (options.throwIfInThePast) { + throw new Error("Date is in the past"); + } + + return; + } + + printWaitBelowThreshold(); + + await new Promise((resolve) => setTimeout(resolve, durationInMs)); + }, + { + attributes: { + [SemanticInternalAttributes.STYLE_ICON]: "wait", + ...accessoryAttributes({ + items: [ + { + text: options.date.toISOString(), + variant: "normal", + }, + ], + style: "codepath", + }), + }, + } + ); + } + const apiClient = apiClientManager.clientOrThrow(); const result = await apiClient.waitForDuration(ctx.run.id, { From 8627c53dcd283779b2769a95c96111fb27ee394c Mon Sep 17 00:00:00 2001 From: nicktrn <55853254+nicktrn@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:14:27 +0100 Subject: [PATCH 2/3] improve wording --- packages/trigger-sdk/src/v3/wait.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/trigger-sdk/src/v3/wait.ts b/packages/trigger-sdk/src/v3/wait.ts index 0e57122853..4768a9e7ee 100644 --- a/packages/trigger-sdk/src/v3/wait.ts +++ b/packages/trigger-sdk/src/v3/wait.ts @@ -372,7 +372,9 @@ export class WaitpointTimeoutError extends Error { const DURATION_WAIT_CHARGE_THRESHOLD_MS = 5000; function printWaitBelowThreshold() { - console.warn(`Waits of ${DURATION_WAIT_CHARGE_THRESHOLD_MS / 1000}s or less are charged.`); + console.warn( + `Waits of ${DURATION_WAIT_CHARGE_THRESHOLD_MS / 1000}s or less count towards compute usage.` + ); } export const wait = { From 01c64ec262aa0910824c86fb94a5aad5764e925c Mon Sep 17 00:00:00 2001 From: James Ritchie Date: Mon, 7 Apr 2025 14:50:24 +0100 Subject: [PATCH 3/3] Updates the wait overview, wait.for and wait.until pages copy to better explain compute costs --- docs/snippets/paused-execution-free.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/snippets/paused-execution-free.mdx b/docs/snippets/paused-execution-free.mdx index e58678fe95..7a9483d451 100644 --- a/docs/snippets/paused-execution-free.mdx +++ b/docs/snippets/paused-execution-free.mdx @@ -1,4 +1,4 @@ - - In the Trigger.dev Cloud we automatically pause execution of tasks when they are waiting for - longer than a few seconds. You are not charged when execution is paused. - +In the Trigger.dev Cloud we automatically pause execution of tasks when they are waiting for +longer than a few seconds. + +When triggering and waiting for subtasks, the parent is checkpointed and while waiting does not count towards compute usage. When waiting for a time period (`wait.for` or `wait.until`), if the wait is longer than 5 seconds we checkpoint and it does not count towards compute usage. \ No newline at end of file