From dcfdaadfe4ea130fe2ef710fb7338020d5e8b7da Mon Sep 17 00:00:00 2001 From: Sam Neubardt Date: Tue, 9 Feb 2016 12:33:38 -0500 Subject: [PATCH] Add finagle-clojure/core.async, integration with clojure.core.async --- core.async/.gitignore | 11 +++ core.async/README.md | 8 +++ core.async/project.clj | 15 ++++ core.async/src/finagle_clojure/core_async.clj | 71 +++++++++++++++++++ .../test/finagle_clojure/core_async_test.clj | 17 +++++ 5 files changed, 122 insertions(+) create mode 100644 core.async/.gitignore create mode 100644 core.async/README.md create mode 100644 core.async/project.clj create mode 100644 core.async/src/finagle_clojure/core_async.clj create mode 100644 core.async/test/finagle_clojure/core_async_test.clj diff --git a/core.async/.gitignore b/core.async/.gitignore new file mode 100644 index 0000000..c53038e --- /dev/null +++ b/core.async/.gitignore @@ -0,0 +1,11 @@ +/target +/classes +/checkouts +pom.xml +pom.xml.asc +*.jar +*.class +/.lein-* +/.nrepl-port +.hgignore +.hg/ diff --git a/core.async/README.md b/core.async/README.md new file mode 100644 index 0000000..599fc36 --- /dev/null +++ b/core.async/README.md @@ -0,0 +1,8 @@ +# finagle-clojure/core.async + +Clojure core.async adapters for finagle-clojure. + +### Dependency + + [finagle-clojure/core.async "0.4.2-SNAPSHOT"] + diff --git a/core.async/project.clj b/core.async/project.clj new file mode 100644 index 0000000..0b38156 --- /dev/null +++ b/core.async/project.clj @@ -0,0 +1,15 @@ +(defproject finagle-clojure/core.async "0.4.2-SNAPSHOT" + :description "Clojure core.async integration with finagle-clojure" + :url "https://github.com/twitter/finagle-clojure" + :license {:name "Apache License, Version 2.0" + :url "https://www.apache.org/licenses/LICENSE-2.0"} + :scm {:name "git" :url "http://github.com/finagle/finagle-clojure"} + :plugins [[lein-midje "3.2"]] + :profiles {:test {:dependencies [[midje "1.8.3" :exclusions [org.clojure/clojure]]]} + :dev [:test {:dependencies [[org.clojure/clojure "1.8.0"]]}] + :1.7 [:test {:dependencies [[org.clojure/clojure "1.7.0"]]}] + :1.6 [:test {:dependencies [[org.clojure/clojure "1.6.0"]]}] + :1.5 [:test {:dependencies [[org.clojure/clojure "1.5.1"]]}] + :1.4 [:test {:dependencies [[org.clojure/clojure "1.4.0"]]}]} + :dependencies [[finagle-clojure/core "0.4.2-SNAPSHOT"] + [org.clojure/core.async "0.2.374"]]) diff --git a/core.async/src/finagle_clojure/core_async.clj b/core.async/src/finagle_clojure/core_async.clj new file mode 100644 index 0000000..e9e915b --- /dev/null +++ b/core.async/src/finagle_clojure/core_async.clj @@ -0,0 +1,71 @@ +(ns finagle-clojure.core-async + "Adapters to use Futures with core.async." + (:require [finagle-clojure.futures :as f] + [finagle-clojure.scala :as scala] + [clojure.core.async :as a]) + (:import [com.twitter.util Future])) + +(defn ^:no-doc throw-error + [o] + (if (instance? Throwable o) + (throw o) + o)) + +;; this needs to be a macro so it expands in the scope of the enclosing go block +;; otherwise the async take complains that it isn't in a go block +;; throw-error needs to be public so it's visible in the macro +(defmacro chan + "Enqueues the value or Throwable that a Future is defined with to a channel. + If no chan is provided a new `promise-chan` will be created and returned. + + *Arguments*: + + * `f`: a Future + * `c`: (optional) a core.async chan + + *Returns*: + + The chan to which the result of Future `f` will be enqueued. + + See the helper fns [[chan f (a/promise-chan))) + ([^Future f c] + (f/on-success* f (enqueue-to-chan c)) + (f/on-failure* f (enqueue-to-chan c)) + c)) diff --git a/core.async/test/finagle_clojure/core_async_test.clj b/core.async/test/finagle_clojure/core_async_test.clj new file mode 100644 index 0000000..d9988f4 --- /dev/null +++ b/core.async/test/finagle_clojure/core_async_test.clj @@ -0,0 +1,17 @@ +(ns finagle-clojure.core-async-test + (:require [finagle-clojure.core-async :refer :all] + [finagle-clojure.futures :as f] + [clojure.core.async :as a] + [midje.sweet :refer :all])) + +(facts "future->chan" + (chan (f/exception (Exception.)))) => (throws Exception) + (chan (f/value :value))) => :value + (a/chan (f/value :value))))) => :value + (let [c (a/chan 1) + e (Exception.)] + (a/chan (f/exception e) c)) => e + (a/ nil) + (let [c (a/chan 1)] + (a/chan (f/value :value) c)) => :value + (a/ nil))