{"id":13459916,"url":"https://github.com/avast/retry-go","last_synced_at":"2025-05-13T16:05:56.550Z","repository":{"id":37549778,"uuid":"98185104","full_name":"avast/retry-go","owner":"avast","description":"Simple golang library for retry mechanism","archived":false,"fork":false,"pushed_at":"2025-03-21T09:53:28.000Z","size":202,"stargazers_count":2644,"open_issues_count":10,"forks_count":160,"subscribers_count":32,"default_branch":"master","last_synced_at":"2025-04-22T11:39:09.403Z","etag":null,"topics":["go","golang","hacktoberfest","retry","retry-library"],"latest_commit_sha":null,"homepage":"http://godoc.org/github.com/avast/retry-go","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/avast.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-24T11:48:53.000Z","updated_at":"2025-04-20T06:54:32.000Z","dependencies_parsed_at":"2024-04-18T09:27:08.470Z","dependency_job_id":"217fef06-1088-4eb0-96c5-fa3c96659eca","html_url":"https://github.com/avast/retry-go","commit_stats":{"total_commits":173,"total_committers":43,"mean_commits":4.023255813953488,"dds":0.6878612716763006,"last_synced_commit":"01d7e0007ca266461dd395bc76ee7d14b2a73b63"},"previous_names":[],"tags_count":72,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avast%2Fretry-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avast%2Fretry-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avast%2Fretry-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avast%2Fretry-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/avast","download_url":"https://codeload.github.com/avast/retry-go/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252590528,"owners_count":21772935,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","hacktoberfest","retry","retry-library"],"created_at":"2024-07-31T10:00:32.367Z","updated_at":"2025-05-05T22:50:27.906Z","avatar_url":"https://github.com/avast.png","language":"Go","funding_links":[],"categories":["Go","公用事业公司","Utilities","语言资源库","Repositories"],"sub_categories":["实用程序/Miscellaneous","Utility/Miscellaneous","go"],"readme":"# retry\n\n[![Release](https://img.shields.io/github/release/avast/retry-go.svg?style=flat-square)](https://github.com/avast/retry-go/releases/latest)\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)\n![GitHub Actions](https://github.com/avast/retry-go/actions/workflows/workflow.yaml/badge.svg)\n[![Go Report Card](https://goreportcard.com/badge/github.com/avast/retry-go?style=flat-square)](https://goreportcard.com/report/github.com/avast/retry-go)\n[![Go Reference](https://pkg.go.dev/badge/github.com/avast/retry-go/v4.svg)](https://pkg.go.dev/github.com/avast/retry-go/v4)\n[![codecov.io](https://codecov.io/github/avast/retry-go/coverage.svg?branch=master)](https://codecov.io/github/avast/retry-go?branch=master)\n[![Sourcegraph](https://sourcegraph.com/github.com/avast/retry-go/-/badge.svg)](https://sourcegraph.com/github.com/avast/retry-go?badge)\n\nSimple library for retry mechanism\n\nSlightly inspired by\n[Try::Tiny::Retry](https://metacpan.org/pod/Try::Tiny::Retry)\n\n# SYNOPSIS\n\nHTTP GET with retry:\n\n    url := \"http://example.com\"\n    var body []byte\n\n    err := retry.Do(\n    \tfunc() error {\n    \t\tresp, err := http.Get(url)\n    \t\tif err != nil {\n    \t\t\treturn err\n    \t\t}\n    \t\tdefer resp.Body.Close()\n    \t\tbody, err = ioutil.ReadAll(resp.Body)\n    \t\tif err != nil {\n    \t\t\treturn err\n    \t\t}\n    \t\treturn nil\n    \t},\n    )\n\n    if err != nil {\n    \t// handle error\n    }\n\n    fmt.Println(string(body))\n\nHTTP GET with retry with data:\n\n    url := \"http://example.com\"\n\n    body, err := retry.DoWithData(\n    \tfunc() ([]byte, error) {\n    \t\tresp, err := http.Get(url)\n    \t\tif err != nil {\n    \t\t\treturn nil, err\n    \t\t}\n    \t\tdefer resp.Body.Close()\n    \t\tbody, err := ioutil.ReadAll(resp.Body)\n    \t\tif err != nil {\n    \t\t\treturn nil, err\n    \t\t}\n\n    \t\treturn body, nil\n    \t},\n    )\n\n    if err != nil {\n    \t// handle error\n    }\n\n    fmt.Println(string(body))\n\n[More examples](https://github.com/avast/retry-go/tree/master/examples)\n\n# SEE ALSO\n\n* [giantswarm/retry-go](https://github.com/giantswarm/retry-go) - slightly\ncomplicated interface.\n\n* [sethgrid/pester](https://github.com/sethgrid/pester) - only http retry for\nhttp calls with retries and backoff\n\n* [cenkalti/backoff](https://github.com/cenkalti/backoff) - Go port of the\nexponential backoff algorithm from Google's HTTP Client Library for Java. Really\ncomplicated interface.\n\n* [rafaeljesus/retry-go](https://github.com/rafaeljesus/retry-go) - looks good,\nslightly similar as this package, don't have 'simple' `Retry` method\n\n* [matryer/try](https://github.com/matryer/try) - very popular package,\nnonintuitive interface (for me)\n\n# BREAKING CHANGES\n\n* 4.0.0\n\n    - infinity retry is possible by set `Attempts(0)` by PR [#49](https://github.com/avast/retry-go/pull/49)\n\n* 3.0.0\n\n    - `DelayTypeFunc` accepts a new parameter `err` - this breaking change affects only your custom Delay Functions. This change allow [make delay functions based on error](examples/delay_based_on_error_test.go).\n\n* 1.0.2 -\u003e 2.0.0\n\n    - argument of `retry.Delay` is final delay (no multiplication by `retry.Units` anymore)\n    - function `retry.Units` are removed\n    - [more about this breaking change](https://github.com/avast/retry-go/issues/7)\n\n* 0.3.0 -\u003e 1.0.0\n\n    - `retry.Retry` function are changed to `retry.Do` function\n    - `retry.RetryCustom` (OnRetry) and `retry.RetryCustomWithOpts` functions are now implement via functions produces Options (aka `retry.OnRetry`)\n\n## Usage\n\n#### func  BackOffDelay\n\n```go\nfunc BackOffDelay(n uint, _ error, config *Config) time.Duration\n```\nBackOffDelay is a DelayType which increases delay between consecutive retries\n\n#### func  Do\n\n```go\nfunc Do(retryableFunc RetryableFunc, opts ...Option) error\n```\n\n#### func  DoWithData\n\n```go\nfunc DoWithData[T any](retryableFunc RetryableFuncWithData[T], opts ...Option) (T, error)\n```\n\n#### func  FixedDelay\n\n```go\nfunc FixedDelay(_ uint, _ error, config *Config) time.Duration\n```\nFixedDelay is a DelayType which keeps delay the same through all iterations\n\n#### func  IsRecoverable\n\n```go\nfunc IsRecoverable(err error) bool\n```\nIsRecoverable checks if error is an instance of `unrecoverableError`\n\n#### func  RandomDelay\n\n```go\nfunc RandomDelay(_ uint, _ error, config *Config) time.Duration\n```\nRandomDelay is a DelayType which picks a random delay up to config.maxJitter\n\n#### func  Unrecoverable\n\n```go\nfunc Unrecoverable(err error) error\n```\nUnrecoverable wraps an error in `unrecoverableError` struct\n\n#### type Config\n\n```go\ntype Config struct {\n}\n```\n\n\n#### type DelayTypeFunc\n\n```go\ntype DelayTypeFunc func(n uint, err error, config *Config) time.Duration\n```\n\nDelayTypeFunc is called to return the next delay to wait after the retriable\nfunction fails on `err` after `n` attempts.\n\n#### func  CombineDelay\n\n```go\nfunc CombineDelay(delays ...DelayTypeFunc) DelayTypeFunc\n```\nCombineDelay is a DelayType the combines all of the specified delays into a new\nDelayTypeFunc\n\n#### type Error\n\n```go\ntype Error []error\n```\n\nError type represents list of errors in retry\n\n#### func (Error) As\n\n```go\nfunc (e Error) As(target interface{}) bool\n```\n\n#### func (Error) Error\n\n```go\nfunc (e Error) Error() string\n```\nError method return string representation of Error It is an implementation of\nerror interface\n\n#### func (Error) Is\n\n```go\nfunc (e Error) Is(target error) bool\n```\n\n#### func (Error) Unwrap\n\n```go\nfunc (e Error) Unwrap() error\n```\nUnwrap the last error for compatibility with `errors.Unwrap()`. When you need to\nunwrap all errors, you should use `WrappedErrors()` instead.\n\n    err := Do(\n    \tfunc() error {\n    \t\treturn errors.New(\"original error\")\n    \t},\n    \tAttempts(1),\n    )\n\n    fmt.Println(errors.Unwrap(err)) # \"original error\" is printed\n\nAdded in version 4.2.0.\n\n#### func (Error) WrappedErrors\n\n```go\nfunc (e Error) WrappedErrors() []error\n```\nWrappedErrors returns the list of errors that this Error is wrapping. It is an\nimplementation of the `errwrap.Wrapper` interface in package\n[errwrap](https://github.com/hashicorp/errwrap) so that `retry.Error` can be\nused with that library.\n\n#### type OnRetryFunc\n\n```go\ntype OnRetryFunc func(attempt uint, err error)\n```\n\nFunction signature of OnRetry function\n\n#### type Option\n\n```go\ntype Option func(*Config)\n```\n\nOption represents an option for retry.\n\n#### func  Attempts\n\n```go\nfunc Attempts(attempts uint) Option\n```\nAttempts set count of retry. Setting to 0 will retry until the retried function\nsucceeds. default is 10\n\n#### func  AttemptsForError\n\n```go\nfunc AttemptsForError(attempts uint, err error) Option\n```\nAttemptsForError sets count of retry in case execution results in given `err`\nRetries for the given `err` are also counted against total retries. The retry\nwill stop if any of given retries is exhausted.\n\nadded in 4.3.0\n\n#### func  Context\n\n```go\nfunc Context(ctx context.Context) Option\n```\nContext allow to set context of retry default are Background context\n\nexample of immediately cancellation (maybe it isn't the best example, but it\ndescribes behavior enough; I hope)\n\n    ctx, cancel := context.WithCancel(context.Background())\n    cancel()\n\n    retry.Do(\n    \tfunc() error {\n    \t\t...\n    \t},\n    \tretry.Context(ctx),\n    )\n\n#### func  Delay\n\n```go\nfunc Delay(delay time.Duration) Option\n```\nDelay set delay between retry default is 100ms\n\n#### func  DelayType\n\n```go\nfunc DelayType(delayType DelayTypeFunc) Option\n```\nDelayType set type of the delay between retries default is BackOff\n\n#### func  LastErrorOnly\n\n```go\nfunc LastErrorOnly(lastErrorOnly bool) Option\n```\nreturn the direct last error that came from the retried function default is\nfalse (return wrapped errors with everything)\n\n#### func  MaxDelay\n\n```go\nfunc MaxDelay(maxDelay time.Duration) Option\n```\nMaxDelay set maximum delay between retry does not apply by default\n\n#### func  MaxJitter\n\n```go\nfunc MaxJitter(maxJitter time.Duration) Option\n```\nMaxJitter sets the maximum random Jitter between retries for RandomDelay\n\n#### func  OnRetry\n\n```go\nfunc OnRetry(onRetry OnRetryFunc) Option\n```\nOnRetry function callback are called each retry\n\nlog each retry example:\n\n    retry.Do(\n    \tfunc() error {\n    \t\treturn errors.New(\"some error\")\n    \t},\n    \tretry.OnRetry(func(n uint, err error) {\n    \t\tlog.Printf(\"#%d: %s\\n\", n, err)\n    \t}),\n    )\n\n#### func  RetryIf\n\n```go\nfunc RetryIf(retryIf RetryIfFunc) Option\n```\nRetryIf controls whether a retry should be attempted after an error (assuming\nthere are any retry attempts remaining)\n\nskip retry if special error example:\n\n    retry.Do(\n    \tfunc() error {\n    \t\treturn errors.New(\"special error\")\n    \t},\n    \tretry.RetryIf(func(err error) bool {\n    \t\tif err.Error() == \"special error\" {\n    \t\t\treturn false\n    \t\t}\n    \t\treturn true\n    \t})\n    )\n\nBy default RetryIf stops execution if the error is wrapped using\n`retry.Unrecoverable`, so above example may also be shortened to:\n\n    retry.Do(\n    \tfunc() error {\n    \t\treturn retry.Unrecoverable(errors.New(\"special error\"))\n    \t}\n    )\n\n#### func  UntilSucceeded\n\n```go\nfunc UntilSucceeded() Option\n```\nUntilSucceeded will retry until the retried function succeeds. Equivalent to\nsetting Attempts(0).\n\n#### func  WithTimer\n\n```go\nfunc WithTimer(t Timer) Option\n```\nWithTimer provides a way to swap out timer module implementations. This\nprimarily is useful for mocking/testing, where you may not want to explicitly\nwait for a set duration for retries.\n\nexample of augmenting time.After with a print statement\n\n    type struct MyTimer {}\n\n    func (t *MyTimer) After(d time.Duration) \u003c- chan time.Time {\n        fmt.Print(\"Timer called!\")\n        return time.After(d)\n    }\n\n    retry.Do(\n        func() error { ... },\n    \t   retry.WithTimer(\u0026MyTimer{})\n    )\n\n#### func  WrapContextErrorWithLastError\n\n```go\nfunc WrapContextErrorWithLastError(wrapContextErrorWithLastError bool) Option\n```\nWrapContextErrorWithLastError allows the context error to be returned wrapped\nwith the last error that the retried function returned. This is only applicable\nwhen Attempts is set to 0 to retry indefinitly and when using a context to\ncancel / timeout\n\ndefault is false\n\n    ctx, cancel := context.WithCancel(context.Background())\n    defer cancel()\n\n    retry.Do(\n    \tfunc() error {\n    \t\t...\n    \t},\n    \tretry.Context(ctx),\n    \tretry.Attempts(0),\n    \tretry.WrapContextErrorWithLastError(true),\n    )\n\n#### type RetryIfFunc\n\n```go\ntype RetryIfFunc func(error) bool\n```\n\nFunction signature of retry if function\n\n#### type RetryableFunc\n\n```go\ntype RetryableFunc func() error\n```\n\nFunction signature of retryable function\n\n#### type RetryableFuncWithData\n\n```go\ntype RetryableFuncWithData[T any] func() (T, error)\n```\n\nFunction signature of retryable function with data\n\n#### type Timer\n\n```go\ntype Timer interface {\n\tAfter(time.Duration) \u003c-chan time.Time\n}\n```\n\nTimer represents the timer used to track time for a retry.\n\n## Contributing\n\nContributions are very much welcome.\n\n### Makefile\n\nMakefile provides several handy rules, like README.md `generator` , `setup` for prepare build/dev environment, `test`, `cover`, etc...\n\nTry `make help` for more information.\n\n### Before pull request\n\n\u003e maybe you need `make setup` in order to setup environment\n\nplease try:\n* run tests (`make test`)\n* run linter (`make lint`)\n* if your IDE don't automaticaly do `go fmt`, run `go fmt` (`make fmt`)\n\n### README\n\nREADME.md are generate from template [.godocdown.tmpl](.godocdown.tmpl) and code documentation via [godocdown](https://github.com/robertkrimen/godocdown).\n\nNever edit README.md direct, because your change will be lost.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favast%2Fretry-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Favast%2Fretry-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favast%2Fretry-go/lists"}