Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Effect.withRetry: retry w/ knowledge of past attempts #4458

Open
jessekelly881 opened this issue Feb 15, 2025 · 1 comment
Open

Effect.withRetry: retry w/ knowledge of past attempts #4458

jessekelly881 opened this issue Feb 15, 2025 · 1 comment
Labels
enhancement New feature or request

Comments

@jessekelly881
Copy link
Contributor

jessekelly881 commented Feb 15, 2025

What is the problem this feature would solve?

It's sometime necessary to have access to the context of previous retry attempts when running a new retry attempt. For example, when receiving a parse error from an llm response it is useful to be able to send the parse error message to the llm. Or in other cases it is useful to keep track of how many times a retry has taken place.

What is the feature you are proposing to solve the problem?

A fn like

Effect.withRetry({
    run: (previousFailures: Cause[], runCount: number) => Effect.fail(""),
   // ... normal retry params: while, etc. 
})

What alternatives have you considered?

runCount could just be extracted from previousResults.length

@jessekelly881 jessekelly881 added the enhancement New feature or request label Feb 15, 2025
@mattrossman
Copy link
Contributor

I was looking for a similar functionality recently. Here's a userland version of this with just the count tracking:

function retryWith<A, E>(f: (retryCount: number) => Effect.Effect<A, E>, options: Effect.Retry.Options<E>) {
  return Effect.gen(function*() {
    const retryCount = yield* Ref.make(0)
    return yield* Ref.get(retryCount).pipe(
      Effect.flatMap((i) => f(i)),
      Effect.tapError(() => Ref.update(retryCount, x => x +1)),
      Effect.retry(options)
    )
  })
}

// Example
retryWith((i) => Effect.fail(i), {
  times: 2
})

I briefly tried accumulating errors from previous runs instead of just the count, but getting TypeScript to infer the error type was more involved.

I call it retryWith here because it isn't very pipeline-friendly, and when I compare existing APIs like withRandom vs randomWith, it appears the .with* functions more often wrap existing effects and are more pipeline-friendly, while .*With functions often produce a standalone effect from a factory function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants