Exponential backoff retry logic
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-linkedin: apply dune fmt

Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.

+57 -14
+50 -14
README.md
··· 5 5 6 6 ## Installation 7 7 8 + Install with opam: 9 + 10 + ```sh 11 + $ opam install retry 8 12 ``` 9 - opam install retry 13 + 14 + If opam cannot find the package, it may not yet be released in the public 15 + `opam-repository`. Add the overlay repository, then install it: 16 + 17 + ```sh 18 + $ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git 19 + $ opam update 20 + $ opam install retry 10 21 ``` 11 22 12 23 ## Usage 13 24 25 + ### Retry on exception 26 + 14 27 ```ocaml 15 - let config = Retry.config ~max_retries:5 () in 28 + let config = Retry.config ~max_retries:5 () 16 29 let should_retry = function 17 30 | Eio.Net.Connection_refused _ -> true 18 31 | _ -> false 19 - in 20 - Retry.with_retry ~clock ~config ~should_retry (fun () -> 21 - connect_to_server ()) 32 + 33 + let run ~clock = 34 + Retry.with_retry ~clock ~config ~should_retry (fun () -> 35 + connect_to_server ()) 22 36 ``` 23 37 24 - For result-returning functions: 38 + ### Retry on `Error` result 25 39 26 40 ```ocaml 27 - Retry.with_retry_result ~clock ~config 28 - ~should_retry:(fun `Unavailable -> true | _ -> false) 29 - (fun () -> call_api ()) 41 + let run ~clock = 42 + Retry.with_retry_result ~clock ~config 43 + ~should_retry:(function `Unavailable -> true | _ -> false) 44 + (fun () -> call_api ()) 30 45 ``` 31 46 47 + ### Behaviour after the last attempt 48 + 49 + `with_retry` runs the callback once, then up to `max_retries` more times 50 + with exponential backoff between attempts. Delays grow as 51 + `backoff_factor * 2 ^ attempt`, capped at `backoff_max`, and randomised 52 + when `jitter` is `true`. 53 + 54 + If every attempt still fails, the library surfaces the **last** failure 55 + unchanged: 56 + 57 + - `with_retry` re-raises the most recent exception from the callback. 58 + Exceptions rejected by `should_retry` are re-raised immediately without 59 + further retries. 60 + - `with_retry_result` returns the most recent `Error`. An `Error` rejected 61 + by `should_retry` is returned immediately. 62 + 63 + Use `Retry.calculate_backoff ~config ~attempt` to inspect what the delay 64 + would be for a given attempt without running the retry loop. 65 + 32 66 ## API 33 67 34 - - `Retry.config` -- Create config (`?max_retries`, `?backoff_factor`, `?backoff_max`, `?jitter`) 35 - - `Retry.default_config` -- 3 retries, 0.3s backoff, 120s max, jitter on 36 - - `Retry.with_retry` -- Retry on exception 37 - - `Retry.with_retry_result` -- Retry on error result 38 - - `Retry.calculate_backoff` -- Compute delay for a given attempt 68 + - `Retry.config ?max_retries ?backoff_factor ?backoff_max ?jitter ()` 69 + - `Retry.default_config` -- 3 retries, 0.3s backoff factor, 120s cap, 70 + jitter on. 71 + - `Retry.with_retry ~clock ~config ~should_retry f` -- retry on exception. 72 + - `Retry.with_retry_result ~clock ~config ~should_retry f` -- retry on 73 + error result. 74 + - `Retry.calculate_backoff ~config ~attempt` -- inspect the computed delay. 39 75 40 76 ## Licence 41 77
+4
dune
··· 1 1 (env 2 2 (dev 3 3 (flags :standard %{dune-warnings}))) 4 + 5 + (mdx 6 + (files README.md) 7 + (libraries retry eio))
+2
dune-project
··· 1 1 (lang dune 3.21) 2 + (using mdx 0.4) 2 3 3 4 (name retry) 4 5 ··· 22 23 (logs (>= 0.7)) 23 24 (alcotest :with-test) 24 25 (eio_main :with-test) 26 + (mdx :with-test) 25 27 (odoc :with-doc)))
+1
retry.opam
··· 16 16 "logs" {>= "0.7"} 17 17 "alcotest" {with-test} 18 18 "eio_main" {with-test} 19 + "mdx" {with-test} 19 20 "odoc" {with-doc} 20 21 ] 21 22 build: [