Skip to content

Conversation

@TooTallNate
Copy link
Member

@TooTallNate TooTallNate commented Nov 6, 2025

Changed RetryableError to use milliseconds instead of seconds for numeric retryAfter values.

What changed?

  • Modified the RetryableError class to interpret numeric retryAfter values as milliseconds instead of seconds
  • Updated documentation and examples to reflect this change
  • Added dependency on @workflow/utils package to use the parseDurationToDate function
  • Updated examples in documentation to show proper usage with:
    • Duration strings (e.g., "5m", "30s")
    • Millisecond values (e.g., 5000 for 5 seconds)
    • Date objects

How to test?

  1. Create a workflow that uses RetryableError with different retryAfter formats:
    // With milliseconds
    throw new RetryableError("Test retry", { retryAfter: 5000 });
    
    // With duration string
    throw new RetryableError("Test retry", { retryAfter: "5m" });
    
    // With Date object
    throw new RetryableError("Test retry", { retryAfter: new Date(Date.now() + 10000) });
  2. Verify that the retry behavior correctly respects the specified durations

Why make this change?

Using milliseconds as the unit for numeric time values is more consistent with JavaScript conventions (like setTimeout and other timing functions). This change makes the API more intuitive for JavaScript developers and aligns with standard practices in the ecosystem.

@changeset-bot
Copy link

changeset-bot bot commented Nov 6, 2025

🦋 Changeset detected

Latest commit: faaf9eb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@workflow/core Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/web-shared Patch
workflow Patch
@workflow/sveltekit Patch
@workflow/world-testing Patch
@workflow/ai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Contributor

vercel bot commented Nov 6, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview Comment Nov 6, 2025 9:44pm
example-nextjs-workflow-webpack Ready Ready Preview Comment Nov 6, 2025 9:44pm
example-workflow Ready Ready Preview Comment Nov 6, 2025 9:44pm
workbench-nitro-workflow Ready Ready Preview Comment Nov 6, 2025 9:44pm
workbench-nuxt-workflow Ready Ready Preview Comment Nov 6, 2025 9:44pm
workbench-sveltekit-workflow Ready Ready Preview Comment Nov 6, 2025 9:44pm
workbench-vite-workflow Ready Ready Preview Comment Nov 6, 2025 9:44pm
workflow-docs Ready Ready Preview Comment Nov 6, 2025 9:44pm

Copy link
Member Author

TooTallNate commented Nov 6, 2025

if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
// Customize the duration before retrying
// Customize the duration before retrying (assume "Retry-After" is an ISO string)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

retry after header js meant to be either seconds, or a HTTP Date format - not ISO

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After

"@workflow/core": patch
---

Change `RetryableError` "retryAfter" option number value to represent milliseconds instead of seconds
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's emphasize the breaking change nature. I wanna get in the habit of doing that so that LLMs can easily do migrations (and create migration guides)

throw new RetryableError( // [!code highlight]
`Rate limited by ${url}`, // [!code highlight]
{ retryAfter: `${retryAfter} seconds` } // [!code highlight]
{ retryAfter: new Date(retryAfter) } // [!code highlight]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

// Delay the retry until after a timeout (assume "Retry-After" is an ISO string)
throw new RetryableError("Too many requests. Retrying...", { // [!code highlight]
retryAfter: parseInt(retryAfter), // [!code highlight]
retryAfter: new Date(retryAfter), // [!code highlight]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same


if (response.status >= 500) {
// Exponential backoffs
// Exponential backoffs (in milliseconds)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant comment

@TooTallNate TooTallNate changed the base branch from workflow-utils to graphite-base/240 November 6, 2025 21:37
@TooTallNate TooTallNate force-pushed the 11-05-change_retryableerror_retryafter_option_number_value_to_represent_milliseconds_instead_of_seconds branch from e3c655b to faaf9eb Compare November 6, 2025 21:41
@TooTallNate TooTallNate changed the base branch from graphite-base/240 to main November 6, 2025 21:41
@TooTallNate TooTallNate merged commit 7013f29 into main Nov 6, 2025
5 of 25 checks passed
@TooTallNate TooTallNate deleted the 11-05-change_retryableerror_retryafter_option_number_value_to_represent_milliseconds_instead_of_seconds branch November 6, 2025 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants