{"id":16660595,"url":"https://github.com/mpenet/auspex","last_synced_at":"2025-08-08T07:06:34.325Z","repository":{"id":42989105,"uuid":"204524741","full_name":"mpenet/auspex","owner":"mpenet","description":"Mini wrapper over java CompletableFuture with a manifold deferred after-taste","archived":false,"fork":false,"pushed_at":"2024-01-29T18:03:38.000Z","size":129,"stargazers_count":42,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-03T22:51:08.852Z","etag":null,"topics":["asynchronous","clojure","future","promise"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mpenet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":"FUNDING.yml","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},"funding":{"github":"mpenet"}},"created_at":"2019-08-26T17:14:59.000Z","updated_at":"2024-06-04T04:42:18.000Z","dependencies_parsed_at":"2024-01-29T19:44:09.220Z","dependency_job_id":null,"html_url":"https://github.com/mpenet/auspex","commit_stats":{"total_commits":79,"total_committers":4,"mean_commits":19.75,"dds":0.4177215189873418,"last_synced_commit":"62aa94f58c221f13550e9a38f1a98e1827043a07"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/mpenet/auspex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fauspex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fauspex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fauspex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fauspex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpenet","download_url":"https://codeload.github.com/mpenet/auspex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpenet%2Fauspex/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269379138,"owners_count":24407363,"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","status":"online","status_checked_at":"2025-08-08T02:00:09.200Z","response_time":72,"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":["asynchronous","clojure","future","promise"],"created_at":"2024-10-12T10:29:57.105Z","updated_at":"2025-08-08T07:06:34.301Z","avatar_url":"https://github.com/mpenet.png","language":"Clojure","funding_links":["https://github.com/sponsors/mpenet"],"categories":[],"sub_categories":[],"readme":"# auspex\n\nAuspex is small wrapper over java-11+ `CompletableFuture` that **mimics** most\nof [manifold](https://github.com/ztellman/manifold) `deferred` API, including\n`chain`, `catch`, `finally`, `loop/recur`, `zip`, `let-flow` and most of the\nnice stuff. I'd like to emphasize, Auspex **does not** include manifold, you can\nuse both auspex and manifold together but the main goal of the library is not to\nenable this.\n\n`qbits.auspex/future` returns a here represents the result of an asynchronous\ncomputation, similary to a manifold.deferred and not like clojure.core/future\nwhich also bundles an execution context.\n\nComposition functions (`then`, `fmap`, `complete!`, `handle`, `finally`) all\nhave an extra/optional `executor` argument that allows to control where\ncomputation happens, otherwise they will use the execution context of the\nprevious step.  So if you specify an executor at a level be aware that\nsubsequent levels will re-use it unless you specify otherwise.\n\n## API\n\n[quickdoc documentation](API.md)\n\n## Usage\n\nSome examples\n\n```clj\n(require '[qbits.auspex :as a])\n\n(let [f (a/future)]\n  (a/success! f ::foo) -\u003e true\n  @f\n  ;; returns ::foo\n  )\n\n(let [f (a/future)]\n  (a/error! f (ex-info \"Oh no\" {})) -\u003e true\n  @f\n  ;; returns ExceptionInfo Oh no\n )\n\n\n(let [f (a/future)]\n  (a/handle f (fn [x err]\n                (prn x err)))\n  (a/success! f ::foo)\n\n  ;; prints nil ::foo\n  )\n\n\n(let [f (-\u003e (a/future (fn [] 0))\n            (a/then inc)\n            (a/then inc))]\n\n  @f\n  ;; returns 2\n  )\n\n(let [f (-\u003e (a/future (fn [] 0))\n            (a/then inc clojure.lang.Agent/soloExecutor)\n            (a/then inc clojure.lang.Agent/pooledExecutor))]\n\n  @f\n  ;; similar as before but with steps running on different executors\n  )\n\n(let [f0 (a/future)\n      f (a/chain f0\n                 inc\n                 inc\n                 inc)]\n\n  ;; chain returns a separate future, feeding f0 will set f0 to 0, f\n  ;; will be the future with the composition result\n  (a/success! f0 0)\n  @f\n  ;; returns 3\n\n  @f0\n  ;; returns 0\n  )\n\n(let [f0 (a/future)\n      f (-\u003e (a/chain f0\n                  inc\n                  (fn [x] (throw (ex-info \"Oh no\" {})))\n                  inc)\n            (a/catch (fn [_] \"no big deal\")))]\n\n  (a/success! f0 0)\n  @f\n  ;; prints no big deal\n  )\n\n(let [f0 (a/future)\n      f (-\u003e (a/chain f0\n                  inc\n                  (fn [x] (throw (ex-info \"Oh no\" {})))\n                  inc)\n            (a/catch clojure.lang.ExceptionInfo (fn [_] 10))\n            (a/finally (fn [] (prn \"...and done\"))))]\n\n  (a/success! f0 0)\n  @f\n  ;; returns 10\n  ;; prints ...and done\n  )\n\n\n@(a/zip (a/success-future 1)\n        2\n        (a/success-future 3))\n;; returns (1 2 3)\n\n\n@(a/one (a/future)\n        (a/success-future 2)\n        (a/success-future 3))\n;; returns 2\n\n\n@(a/timeout! (a/future (fn []\n                         (Thread/sleep 50)\n                         ::foo)\n                       clojure.lang.Agent/soloExecutor)\n             10\n             ::timed-out)\n;; returns ::timed-out\n\n\n@(a/loop [x []]\n   (if (\u003c (count x) 5)\n     (a/recur (conj x (count x)))\n     x))\n;; returns [0 1 2 3 4]\n\n@(a/loop [x 0]\n   (a/chain x\n            inc\n            #(if (\u003c % 5)\n               (a/recur %)\n               %)))\n;; returns 5\n\n@(a/let-flow [x (a/future (fn [] 0))\n              :when (= x 0)\n              y (+ x 1)\n              z (a/future (fn [] (inc y)))]\n  [x y z])\n\n;; return [0 1 2]\n\n```\n\n## Installation\n\n[![Clojars Project](https://img.shields.io/clojars/v/cc.qbits/auspex.svg)](https://clojars.org/cc.qbits/auspex)\n\n## License\n\nCopyright © 2019 Max Penet\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpenet%2Fauspex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpenet%2Fauspex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpenet%2Fauspex/lists"}