All Projects → safwank → Elixirretry

safwank / Elixirretry

Licence: other
Simple Elixir macros for linear retry, exponential backoff and wait with composable delays

Programming Languages

elixir
2628 projects

Projects that are alternatives of or similar to Elixirretry

Retry
A simple, stateless, functional mechanism to perform actions repetitively until successful.
Stars: ✭ 406 (+29.3%)
Mutual labels:  delay, retry
waiter
Delayed iteration for polling and retries.
Stars: ✭ 17 (-94.59%)
Mutual labels:  delay, retry
retryx
Promise-based retry workflow library.
Stars: ✭ 21 (-93.31%)
Mutual labels:  retry
Flutter advanced networkimage
flutter advanced network image provider
Stars: ✭ 282 (-10.19%)
Mutual labels:  retry
awsretry
Decorate your AWS Boto3 Calls with AWSRetry.backoff(). This will allows your calls to get around the AWS Eventual Consistency Errors.
Stars: ✭ 42 (-86.62%)
Mutual labels:  retry
backoff
PHP library providing retry functionality with multiple backoff strategies and jitter support
Stars: ✭ 132 (-57.96%)
Mutual labels:  retry
java-retrying
java retry module, based on guava-retrying, support sync/async retry
Stars: ✭ 19 (-93.95%)
Mutual labels:  retry
redelay
Clojure library for first class lifecycle-managed state.
Stars: ✭ 44 (-85.99%)
Mutual labels:  delay
Retry
because you should never give up, at least not on the first try
Stars: ✭ 303 (-3.5%)
Mutual labels:  retry
sisyphus
The java retry framework.(支持注解的 java 重试框架)
Stars: ✭ 126 (-59.87%)
Mutual labels:  retry
Swiftqueue
Job Scheduler for IOS with Concurrent run, failure/retry, persistence, repeat, delay and more
Stars: ✭ 276 (-12.1%)
Mutual labels:  delay
perseverance
Make your functions 💪 resilient and 🚥 fail-fast to 💩 failures or ⌚ delays
Stars: ✭ 12 (-96.18%)
Mutual labels:  retry
retry
Simple and easy retry mechanism package for Go
Stars: ✭ 54 (-82.8%)
Mutual labels:  retry
HTMLTestRunner cn
HTMLTestRunner 汉化版,同时支持python 2和3,增加截图展示功能,失败重试
Stars: ✭ 191 (-39.17%)
Mutual labels:  retry
Retry Axios
🦖 A super flexible interceptor for Axios that makes it easy to retry requests.
Stars: ✭ 296 (-5.73%)
Mutual labels:  retry
sdmq
is a simple delay message queue, based on redis and kotlin
Stars: ✭ 31 (-90.13%)
Mutual labels:  delay
resilience4clj-circuitbreaker
Resilience4Clj circuit breaker lets you decorate a function call (usually with a potential of external failure) with a safety mechanism to interrupt the propagation of failures.
Stars: ✭ 40 (-87.26%)
Mutual labels:  retry
streamdelay
A delay + dump button for live streams, allowing screening and redaction of explict content.
Stars: ✭ 31 (-90.13%)
Mutual labels:  delay
Input Spinner
A Number-Spinner, Support keyboard operations and continuous changing.
Stars: ✭ 313 (-0.32%)
Mutual labels:  delay
Retry
♻️ The most advanced interruptible mechanism to perform actions repetitively until successful.
Stars: ✭ 294 (-6.37%)
Mutual labels:  retry

Build Status

ElixirRetry

Simple Elixir macros for linear retry, exponential backoff and wait with composable delays.

Installation

Add retry to your list of dependencies in mix.exs:

  def deps do
    [{:retry, "~> 0.14"}]
  end

Ensure retry is started before your application:

  def application do
    [applications: [:retry]]
  end

Documentation

Check out the API reference for the latest documentation.

Features

Retrying

The retry([with: _,] do: _, after: _, else: _) macro provides a way to retry a block of code on failure with a variety of delay and give up behaviors. By default, the execution of a block is considered a failure if it returns :error, {:error, _} or raises a runtime error.

An optional list of atoms can be specified in :atoms if you need to retry anything other than :error or {:error, _}, e.g. retry([with: _, atoms: [:not_ok]], do: _, after: _, else: _).

Similarly, an optional list of exceptions can be specified in :rescue_only if you need to retry anything other than RuntimeError, e.g. retry([with: _, rescue_only: [CustomError]], do: _, after: _, else: _).

The after block evaluates only when the do block returns a valid value before timeout.

On the other hand, the else block evaluates only when the do block remains erroneous after timeout.

Example -- constant backoff

result = retry with: constant_backoff(100) |> Stream.take(10) do
  ExternalApi.do_something # fails if other system is down
after
  result -> result
else
  error -> error
end

This example retries every 100 milliseconds and gives up after 10 attempts.

Example -- linear backoff

result = retry with: linear_backoff(10, 2) |> cap(1_000) |> Stream.take(10) do
  ExternalApi.do_something # fails if other system is down
after
  result -> result
else
  error -> error
end

This example increases the delay linearly with each retry, starting with 10 milliseconds, caps the delay at 1 second and gives up after 10 attempts.

Example -- exponential backoff

result = retry with: exponential_backoff() |> randomize |> expiry(10_000), rescue_only: [TimeoutError] do
  ExternalApi.do_something # fails if other system is down
after
  result -> result
else
  error -> error
end

This will try the block, and return the result, as soon as it succeeds. On a timeout error, this example will wait an exponentially increasing amount of time (exponential_backoff/0). Each delay will be randomly adjusted to remain within +/-10% of its original value (randomize/2). Finally, it will stop retrying after 10 seconds have elapsed (expiry/2).

Example -- retry annotation

use Retry.Annotation

@retry with: constant_backoff(100) |> Stream.take(10)
def some_func(arg) do
  ExternalApi.do_something # fails if other system is down
end

This example shows how you can annotate a function to retry every 100 milliseconds and gives up after 10 attempts.

Delay streams

The with: option of retry accepts any Stream that yields integers. These integers will be interpreted as the amount of time to delay before retrying a failed operation. When the stream is exhausted retry will give up, returning the last value of the block.

Example
result = retry with: Stream.cycle([500]) do
  ExternalApi.do_something # fails if other system is down
after
  result -> result
else
  error -> error  
end

This will retry failures forever, waiting 0.5 seconds between attempts.

Retry.DelayStreams provides a set of fully composable helper functions for building useful delay behaviors such as the ones in previous examples. See the Retry.DelayStreams module docs for full details and addition behavior not covered here. For convenience these functions are imported by use Retry so you can, usually, use them without prefixing them with the module name.

Waiting

Similar to retry(with: _, do: _), the wait(delay_stream, do: _, after: _, else: _) macro provides a way to wait for a block of code to be truthy with a variety of delay and give up behaviors. The execution of a block is considered a failure if it returns false or nil.

wait constant_backoff(100) |> expiry(1_000) do
  we_there_yet?
after
  _ ->
    {:ok, "We have arrived!"}
else
  _ ->
    {:error, "We're still on our way :("}
end

This example retries every 100 milliseconds and expires after 1 second.

The after block evaluates only when the do block returns a truthy value.

On the other hand, the else block evaluates only when the do block remains falsy after timeout.

Pretty nifty for those pesky asynchronous tests and building more reliable systems in general!

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].