Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mpenet/auspex
Mini wrapper over java CompletableFuture with a manifold deferred after-taste
https://github.com/mpenet/auspex
asynchronous clojure future promise
Last synced: 17 days ago
JSON representation
Mini wrapper over java CompletableFuture with a manifold deferred after-taste
- Host: GitHub
- URL: https://github.com/mpenet/auspex
- Owner: mpenet
- License: epl-1.0
- Created: 2019-08-26T17:14:59.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2024-01-29T18:03:38.000Z (10 months ago)
- Last Synced: 2024-10-13T10:29:54.115Z (about 1 month ago)
- Topics: asynchronous, clojure, future, promise
- Language: Clojure
- Homepage:
- Size: 126 KB
- Stars: 42
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# auspex
Auspex is small wrapper over java-11+ `CompletableFuture` that **mimics** most
of [manifold](https://github.com/ztellman/manifold) `deferred` API, including
`chain`, `catch`, `finally`, `loop/recur`, `zip`, `let-flow` and most of the
nice stuff. I'd like to emphasize, Auspex **does not** include manifold, you can
use both auspex and manifold together but the main goal of the library is not to
enable this.`qbits.auspex/future` returns a here represents the result of an asynchronous
computation, similary to a manifold.deferred and not like clojure.core/future
which also bundles an execution context.Composition functions (`then`, `fmap`, `complete!`, `handle`, `finally`) all
have an extra/optional `executor` argument that allows to control where
computation happens, otherwise they will use the execution context of the
previous step. So if you specify an executor at a level be aware that
subsequent levels will re-use it unless you specify otherwise.## API
[quickdoc documentation](API.md)
## Usage
Some examples
```clj
(require '[qbits.auspex :as a])(let [f (a/future)]
(a/success! f ::foo) -> true
@f
;; returns ::foo
)(let [f (a/future)]
(a/error! f (ex-info "Oh no" {})) -> true
@f
;; returns ExceptionInfo Oh no
)(let [f (a/future)]
(a/handle f (fn [x err]
(prn x err)))
(a/success! f ::foo);; prints nil ::foo
)(let [f (-> (a/future (fn [] 0))
(a/then inc)
(a/then inc))]@f
;; returns 2
)(let [f (-> (a/future (fn [] 0))
(a/then inc clojure.lang.Agent/soloExecutor)
(a/then inc clojure.lang.Agent/pooledExecutor))]@f
;; similar as before but with steps running on different executors
)(let [f0 (a/future)
f (a/chain f0
inc
inc
inc)];; chain returns a separate future, feeding f0 will set f0 to 0, f
;; will be the future with the composition result
(a/success! f0 0)
@f
;; returns 3@f0
;; returns 0
)(let [f0 (a/future)
f (-> (a/chain f0
inc
(fn [x] (throw (ex-info "Oh no" {})))
inc)
(a/catch (fn [_] "no big deal")))](a/success! f0 0)
@f
;; prints no big deal
)(let [f0 (a/future)
f (-> (a/chain f0
inc
(fn [x] (throw (ex-info "Oh no" {})))
inc)
(a/catch clojure.lang.ExceptionInfo (fn [_] 10))
(a/finally (fn [] (prn "...and done"))))](a/success! f0 0)
@f
;; returns 10
;; prints ...and done
)@(a/zip (a/success-future 1)
2
(a/success-future 3))
;; returns (1 2 3)@(a/one (a/future)
(a/success-future 2)
(a/success-future 3))
;; returns 2@(a/timeout! (a/future (fn []
(Thread/sleep 50)
::foo)
clojure.lang.Agent/soloExecutor)
10
::timed-out)
;; returns ::timed-out@(a/loop [x []]
(if (< (count x) 5)
(a/recur (conj x (count x)))
x))
;; returns [0 1 2 3 4]@(a/loop [x 0]
(a/chain x
inc
#(if (< % 5)
(a/recur %)
%)))
;; returns 5@(a/let-flow [x (a/future (fn [] 0))
:when (= x 0)
y (+ x 1)
z (a/future (fn [] (inc y)))]
[x y z]);; return [0 1 2]
```
## Installation
[![Clojars Project](https://img.shields.io/clojars/v/cc.qbits/auspex.svg)](https://clojars.org/cc.qbits/auspex)
## License
Copyright © 2019 Max Penet
Distributed under the Eclipse Public License either version 1.0 or (at
your option) any later version.