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

feat(async module): added onRetry option for retry fn #229

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

gperdomor
Copy link

@gperdomor gperdomor commented Aug 30, 2024

Tip

The owner of this PR can publish a preview release by commenting /publish in this PR. Afterwards, anyone can try it out by running pnpm add radashi@pr<PR_NUMBER>.

Summary

Related issue, if any:

For any code change,

  • Related documentation has been updated, if needed
  • Related tests have been added or updated, if needed
  • Related benchmarks have been added or updated, if needed

Does this PR introduce a breaking change?

No

Bundle impact

Status File Size 1 Difference
M src/async/retry.ts 532 +29 (+6%)

Footnotes

  1. Function size includes the import dependencies of the function.

@gperdomor gperdomor requested a review from aleclarson as a code owner August 30, 2024 00:58
@gperdomor gperdomor changed the title feat: added onRetry option for retry fn feat(async module): added onRetry option for retry fn Aug 30, 2024
src/async/retry.ts Outdated Show resolved Hide resolved
tests/async/retry.test.ts Outdated Show resolved Hide resolved
@MarlonPassos-git
Copy link
Contributor

@gperdomor Thank you for the PR! The proposed changes significantly improve the function. However, I’ve left a few comments for discussion and adjustments before we can proceed

@aleclarson
Copy link
Member

Hey @gperdomor, thanks for your contribution 👍

I plan to review this after I get v12.2.0 out (just gotta finish the release notes, probably next week).

Comment on lines 3 to 22
export type RetryOptions = {
times?: number
delay?: number | null
onRetry?: (err: Error, attemptNumber: number) => void
backoff?: (count: number) => number
}

/**
* Retries the given function the specified number of times.
*
* @param {Object} options - The employee who is responsible for the project.
* @param {number} [options.times=3] - Number of attempts.
* @param {number} [options.delay] - Specify milliseconds to sleep between attempts.
* @param {Function} [options.onRetry=null] - Is invoked after a new retry is performed. It's passed the Error that triggered it as a parameter and the attempt number.
* @param {Function} [options.backoff=null] - The backoff option is like delay but uses a function to sleep -- makes for easy exponential backoff.
* @param {Function} func - Function to be executed
*
* @see https://radashi.js.org/reference/async/retry
* @example
* ```ts
Copy link
Contributor

@MarlonPassos-git MarlonPassos-git Sep 8, 2024

Choose a reason for hiding this comment

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

When I said to use Jsoc, I meant to use it in the type, because using it only in the function would not have a good integration with VSCode.

after:
image

before:
image

Suggested change
export type RetryOptions = {
times?: number
delay?: number | null
onRetry?: (err: Error, attemptNumber: number) => void
backoff?: (count: number) => number
}
/**
* Retries the given function the specified number of times.
*
* @param {Object} options - The employee who is responsible for the project.
* @param {number} [options.times=3] - Number of attempts.
* @param {number} [options.delay] - Specify milliseconds to sleep between attempts.
* @param {Function} [options.onRetry=null] - Is invoked after a new retry is performed. It's passed the Error that triggered it as a parameter and the attempt number.
* @param {Function} [options.backoff=null] - The backoff option is like delay but uses a function to sleep -- makes for easy exponential backoff.
* @param {Function} func - Function to be executed
*
* @see https://radashi.js.org/reference/async/retry
* @example
* ```ts
export type RetryOptions = {
/**
* Number of attempts.
*
* @default 3
*/
times?: number
/** Specify milliseconds to sleep between attempts */
delay?: number | null
/**
* Is invoked after a new retry is performed. It's passed the Error that triggered it as a parameter and the attempt number.
*
* @default null
*/
onRetry?: (err: Error, attemptNumber: number) => void
/**
* The backoff option is like delay but uses a function to sleep -- makes for easy exponential backoff.
*
* @default null
*/
backoff?: (count: number) => number
}
/**
* Retries the given function the specified number of times.
*
* @see https://radashi.js.org/reference/async/retry
* @example
* ```ts

@aleclarson
Copy link
Member

aleclarson commented Sep 8, 2024

Thanks for this PR, @gperdomor! It's great to have you here.

If you'd like to address Marlon's comments, go right ahead. Otherwise, I'll get around to it at some point (after I get the v12.2.0 out, of course).

Two questions I had:

  1. Is this mainly intended for logging purposes, or do you have other use cases in mind?
  2. Do you think adding the ability to prevent further retries could also be useful to you? Perhaps we should make sure that throwing inside the onRetry callback is properly handled, so you can bail out that way.

Your feedback would be appreciated.

@aleclarson aleclarson added the new feature This PR adds a new function or extends an existing one label Sep 21, 2024
@aleclarson aleclarson added this to the v12.3.0 milestone Sep 21, 2024
@aleclarson
Copy link
Member

Ping @gperdomor: It'd be great to get your perspective on #229 (comment)

@aleclarson
Copy link
Member

Closing due to lack of response. Can reopen when you have more time. 👍

@gperdomor
Copy link
Author

gperdomor commented Oct 14, 2024

Thanks for this PR, @gperdomor! It's great to have you here.

If you'd like to address Marlon's comments, go right ahead. Otherwise, I'll get around to it at some point (after I get the v12.2.0 out, of course).

Two questions I had:

  1. Is this mainly intended for logging purposes, or do you have other use cases in mind?
  2. Do you think adding the ability to prevent further retries could also be useful to you? Perhaps we should make sure that throwing inside the onRetry callback is properly handled, so you can bail out that way.

Your feedback would be appreciated.

Hi @aleclarson, I didn't saw this, sorry...

  1. Is this mainly intended for logging purposes, or do you have other use cases in mind?

In my case, I want to log...

  1. Do you think adding the ability to prevent further retries could also be useful to you? Perhaps we should make sure that throwing inside the onRetry callback is properly handled, so you can bail out that way.

Mmmmm... I don't know, I think could be useful fro request calls, for example maybe a should not retry if status code is 401 or 403 because in all retries we should get the same result, bt we can retry if status is something like 408 (Request Timeout)

@aleclarson aleclarson reopened this Oct 14, 2024
@gperdomor
Copy link
Author

@aleclarson for the second topic, what do you think it's a better option:

  1. Update onRetry parameter to return true to allow the retry and false to exit?
  2. Similar to 1 but throw error to abort
  3. Add a new onRetryValidation to with boolean result to decide if onRetry will be executed or not...

Copy link
Member

@aleclarson aleclarson left a comment

Choose a reason for hiding this comment

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

Hey @gperdomor, I've had time to think about this a bit.

  • Recently, we've decided to align our APIs to popular, full-featured, standalone packages. (We don't want to clone them in their entirety, just mimic them to make migrating to them easier if you ever need more than Radashi provides.) In this case, that's the p-retry package.
  • Therefore, this option should align with onFailedAttempt from p-retry. That includes naming, the function signature, and when it gets called.
  • Finally, with the addition of a signal option in feat: add signal option to retry and parallel #262, we'll have a means of aborting the retry loop, so this PR can stay focused on the onFailedAttempt feature.

Any questions, just ask. 👍

@aleclarson
Copy link
Member

Ping @gperdomor, let me know if you'll have time for this PR. 👍


Hey! There's a new requirement for PRs that introduce new features. Without this requirement met, we won't be able to merge this. Note that this PR can still be included in a beta prerelease before this requirement is fulfilled.

⚠️ Note: You need to run git rebase main before this file will appear locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature This PR adds a new function or extends an existing one
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants