{"id":25875619,"url":"https://github.com/hiteshjasani/clj-relentless","last_synced_at":"2026-06-09T19:31:21.763Z","repository":{"id":62433981,"uuid":"75896651","full_name":"hiteshjasani/clj-relentless","owner":"hiteshjasani","description":"Enabling intelligent retry logic","archived":false,"fork":false,"pushed_at":"2018-01-29T22:23:03.000Z","size":10,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-29T01:03:31.528Z","etag":null,"topics":["clojure","clojure-library"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hiteshjasani.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-08T02:50:27.000Z","updated_at":"2019-04-12T14:37:39.000Z","dependencies_parsed_at":"2022-11-01T21:16:14.005Z","dependency_job_id":null,"html_url":"https://github.com/hiteshjasani/clj-relentless","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/hiteshjasani/clj-relentless","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiteshjasani%2Fclj-relentless","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiteshjasani%2Fclj-relentless/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiteshjasani%2Fclj-relentless/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiteshjasani%2Fclj-relentless/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hiteshjasani","download_url":"https://codeload.github.com/hiteshjasani/clj-relentless/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hiteshjasani%2Fclj-relentless/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34123171,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["clojure","clojure-library"],"created_at":"2025-03-02T10:18:39.131Z","updated_at":"2026-06-09T19:31:21.737Z","avatar_url":"https://github.com/hiteshjasani.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# clj-relentless\n\n[![Clojars Project](https://img.shields.io/clojars/v/org.jasani/clj-relentless.svg)](https://clojars.org/org.jasani/clj-relentless)  [![CircleCI](https://circleci.com/gh/hiteshjasani/clj-relentless.svg?style=svg)](https://circleci.com/gh/hiteshjasani/clj-relentless)\n\nA Clojure library designed to enable easy and intelligent retrying of\ncode in the face of exceptions.\n\nNetworking code needs a retry strategy when things don't work the\nfirst time.  Failures may be recoverable (temporary network glitches,\nan overburdened server or an expired access token) or non-recoverable\nand being able to influence subsequent retry attempts is valuable.\n\n\n## Installation\n\nNote that this is an early release, so the api may change.\n\nIn leiningen dependencies:\n\n```clojure\n[org.jasani/clj-relentless \"x.y.z\"]\n```\n\nIn your code:\n\n```clojure\n(:require [relentless.core :refer [try-times]])\n```\n\n\n## Usage\n\nCalls that work the first time won't be retried.\n\n```clojure\n(try-times 3\n           (fn [e] (println (str \"received exception: \" e)))\n           (println \"running\")\n           (+ 2 3))\n\n;; running\n;; 5\n```\n\nExample checking the exception.\n\n```clojure\n(try-times 3\n           (fn [e] (println (str \"received exception: \" e)))\n           (println \"running\")\n           (/ 1 0))\n\n;; running\n;; received exception: java.lang.ArithmeticException: Divide by zero\n;; running\n;; received exception: java.lang.ArithmeticException: Divide by zero\n;; running\n;; received exception: java.lang.ArithmeticException: Divide by zero\n;; running\n;; ArithmeticException Divide by zero  clojure.lang.Numbers.divide (Numbers.java:158)\n```\n\nExample calling with an exponential backoff strategy.\n\n```clojure\n(try-times 4\n           (fn [e n]\n             (let [delay (nth [16000 9000 4000 1000] (dec n))]\n               (println (str \"delaying for \" delay))\n               (Thread/sleep delay)))\n           (println \"running\")\n           (/ 1 0))\n\n;; running\n;; delaying for 1000\n;; running\n;; delaying for 4000\n;; running\n;; delaying for 9000\n;; running\n;; delaying for 16000\n;; running\n;; ArithmeticException Divide by zero  clojure.lang.Numbers.divide (Numbers.java:158)\n```\n\nRetry for only Arithmetic exceptions and only after we've encountered\nthem at least once.  Our handler is able to change some state so that\nthe subsequent retry is successful.  While this example is using\nnumbers, one can easily imagine them being replaced with network\nservices where the client tries a backup one if the first is not\nresponding.\n\n```clojure\n(let [denom (atom 0)]\n  (try-times 3\n             (fn [e n]\n               (if (and (instance? java.lang.ArithmeticException e)\n                        (\u003c n 3))\n                 (do\n                   (println \"resetting denom\")\n                   (reset! denom 3))\n                 (println (str \"received exception: \" e))))\n             (println \"running\")\n             (/ 1 @denom)))\n\n;; running\n;; received exception: java.lang.ArithmeticException: Divide by zero\n;; running\n;; resetting denom\n;; running\n;; 1/3\n```\n\n## License\n\nCopyright © 2016 Hitesh Jasani\n\nDistributed under the Eclipse Public License, the same as Clojure.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiteshjasani%2Fclj-relentless","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhiteshjasani%2Fclj-relentless","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhiteshjasani%2Fclj-relentless/lists"}