{"id":13587210,"url":"https://github.com/softwaremill/retry","last_synced_at":"2025-04-04T22:07:13.372Z","repository":{"id":8224031,"uuid":"9662659","full_name":"softwaremill/retry","owner":"softwaremill","description":"because you should never give up, at least not on the first try","archived":false,"fork":false,"pushed_at":"2024-05-17T00:16:25.000Z","size":201,"stargazers_count":349,"open_issues_count":14,"forks_count":36,"subscribers_count":36,"default_branch":"master","last_synced_at":"2024-05-21T01:45:42.096Z","etag":null,"topics":["future","retry","scala","scalajs"],"latest_commit_sha":null,"homepage":"https://softwaremill.com/open-source","language":"Scala","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/softwaremill.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":"2013-04-25T03:03:46.000Z","updated_at":"2024-08-01T16:33:12.066Z","dependencies_parsed_at":"2024-01-01T01:26:40.435Z","dependency_job_id":"731c83f0-d4fb-4a89-b9f5-78ac060ea656","html_url":"https://github.com/softwaremill/retry","commit_stats":{"total_commits":181,"total_committers":14,"mean_commits":"12.928571428571429","dds":0.5082872928176796,"last_synced_commit":"cfb01b995828f4efcf35751f0acdfd6d945c000f"},"previous_names":["softprops/retry"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Fretry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Fretry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Fretry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softwaremill%2Fretry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softwaremill","download_url":"https://codeload.github.com/softwaremill/retry/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247256112,"owners_count":20909240,"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":["future","retry","scala","scalajs"],"created_at":"2024-08-01T15:06:06.139Z","updated_at":"2025-04-04T22:07:13.352Z","avatar_url":"https://github.com/softwaremill.png","language":"Scala","funding_links":[],"categories":["Scala","容错组件"],"sub_categories":[],"readme":"# retry\n\ndon't give up\n\n## install\n\nWith sbt, add the following to your project's build.sbt\n\n```scala\nlibraryDependencies += \"com.softwaremill.retry\" %% \"retry\" % \"0.3.6\"\n```\n## usage\n\nApplications fail. Network connections drop. Connections timeout. Bad things happen.\n\nFailure to address this will cause other bad things to happen. Effort is the measurement of how hard you try.\n\nYou can give your application perseverance with retry.\n\nRetry provides interfaces for common retry strategies that operate on Scala [Futures][fut].\n\nBasic usage requires three things\n\n- an implicit execution context for executing futures \n- a definition of [Success](#defining-success) encode what \"success\" means for the type of your future\n- a block of code that results in a Scala [Future][fut].\n\nDepending on your strategy for retrying a future you may also need an [odelay.Timer][timer] for asynchronously scheduling followup attempts\n\nRetry provides a set of defaults that provide `retry.Success` definitions for [Option][option], [Either][either], [Try][try], and a partial function (defined with Success.definedAt(partialFunction)) out of the box.\n\n```scala\nimport scala.concurrent.ExecutionContext.Implicits.global\nimport scala.concurrent.Future\n\nretry.Backoff().apply(() =\u003e Future {\n  // something that can \"fail\"\n})\n```\n\n### Defining success\n\nRetry needs to know what _success_ means in the context of your Future in order to know when to retry an operation.\n\nIt does this through a generic `Success[-T](pred: T =\u003e Boolean)` type class, where `T` matches the type your [Future][fut] will resolve to.\n\nRetry looks for this definition within implicit scope of the retry.\n\nYou may wish define an application-specific definition of what \"success\" means for your future. You can do so by specifying the following in scope of the retry.\n\n```scala\nimplicit val perfectTen = Success[Int](_ == 10)\n```\n\nIf your future completes with anything other than 10, it will be considered a failure and will be retried. Here's to you, tiger mom!\n\nSuccess values may also be composed with `and` and `or` semantics\n\n```scala\n// will be considered a success when the preconditions of both successA and successB are met\nval successC = successA.and(successB)\n\n// will be considered a success when the predconditions of either successC or successD are met\nval successE = successC.or(successD)\n```\n\n### Sleep schedules\n\nRather than blocking a thread, retry attempts are scheduled using Timers. Your application may run within a platform that provides its own way for scheduling tasks. If an [odelay.jdk.JdkTimer](https://github.com/softwaremill/odelay#jdktimer) isn't what you're looking for, you may wish to use the `odelay.Timer` for netty, [odelay.netty.Timer](https://github.com/softwaremill/odelay#netty3timers) in the `odelay-netty` module or an [odelay.twitter.TwitterTimer](https://github.com/softwaremill/odelay#twittertimers) available in the `odelay-twitter` module.\n\nSee the [odelay docs][odelay] for defining your own timer. If none of these aren't what you're looking for, please open a pull request!\n\n### According to Policy\n\nRetry logic is implemented in modules whose behavior vary but all produce a common interface: a `retry.Policy`.\n\n```scala\ntrait Policy {\n  def apply[T](promise: () =\u003e Future[T])\n     (implicit success: Success[T],\n      executor: ExecutionContext): Future[T]\n}\n```          \n\n#### Directly\n\nThe `retry.Directly` module defines interfaces for retrying a future directly\nafter a failed attempt.\n\n```scala\n// retry 4 times\nval future = retry.Directly(4) { () =\u003e\n  attempt\n}\n```\n\n#### Pause\n\nThe `retry.Pause` module defines interfaces for retrying a future with a configurable pause in between attempts\n\n```scala\n// retry 3 times pausing 30 seconds in between attempts\nval future = retry.Pause(3, 30.seconds).apply { () =\u003e\n  attempt\n}\n```\n\n#### Backoff\n\nThe `retry.Backoff` modules defines interfaces for retrying a future with a configureable pause and exponential\nbackoff factor.\n\n\n```scala\n// retry 4 times with a delay of 1 second which will be multipled\n// by 2 on every attempt\nval future = retry.Backoff(4, 1.second).apply { () =\u003e\n  attempt\n}\n```\n\n#### When\n\nAll of the retry strategies above assume you are representing failure in your Future's result type. In cases where the\nresult of your future is \"exceptional\". You can use the When module which takes a PartialFunction of Any to Policy.\n\n```scala\nval policy = retry.When {\n  case NonFatal(e) =\u003e retry.Pause(3, 1.second)\n}\n\npolicy(execptionalAttempt)\n```\n\nNote, The domain of the PartialFunction passed to When may cover both the exception thrown _or_ the successful result of the future.\n\n#### FailFast\n\n`retry.FailFast` allows you to wrap any of the above policies and define which failures should immediately stop the retries.\n\nThe difference between `retry.FailFast` and `retry.When` with a partial function for `Throwable`s is that `retry.When`\npasses the execution to another policy after the first retry, whereas `retry.FailFast` uses the inner policy logic\nfor each retry. For instance, it allows using a policy that retries forever together with a fail fast logic\non some irrecoverable exceptions.\n\n```scala\nval innerPolicy = retry.Backoff.forever\nval policy = retry.FailFast(innerPolicy) {\n  case e: FooException     =\u003e true\n  case e: RuntimeException =\u003e isFatal(e.getCause)\n}\n\npolicy(issueRequest)\n```\n\nWhen the provided partial function is not defined at a particular `Throwable`, the retry logic is defined by the wrapped policy.\n\n#### Suggested library usage\n\nSince all retry modules now produce a generic interface, a `retry.Policy`, if you wish to write clients of services you may wish to make define\na Success for the type of that service and capture an configurable reference to a Policy so that clients may swap policies based on use case.\n\n```scala\ncase class Client(retryPolicy: retry.Policy = retry.Directly()) {\n  def request = retryPolicy(mkRequest)\n}\n\nval defaultClient = Client()\n\nval customClient = defaultClient.copy(\n  retryPolicy = retry.Backoff()\n)\n```\n\n## Credits\n\nOriginally created by [Doug Tangren](https://github.com/softprops), maintained by [SoftwareMill](https://softwaremill.com).\n\n[timer]: https://github.com/softwaremill/odelay#timers\n[odelay]: https://github.com/softwaremill/odelay#readme\n[fut]: http://www.scala-lang.org/api/current/index.html#scala.concurrent.Future\n[either]: http://www.scala-lang.org/api/current/index.html#scala.util.Either\n[option]: http://www.scala-lang.org/api/current/index.html#scala.Option\n[try]: http://www.scala-lang.org/api/current/index.html#scala.util.Try\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwaremill%2Fretry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftwaremill%2Fretry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftwaremill%2Fretry/lists"}