-
Notifications
You must be signed in to change notification settings - Fork 241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support cancellation during client connection establishment #721
base: master
Are you sure you want to change the base?
Changes from 7 commits
9a66ceb
8e1edd9
ad58861
568847c
d14b846
d2233c6
ef28e80
11e9eef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
(ns aleph.util | ||
(:require [manifold.deferred :as d])) | ||
|
||
(defn on-error | ||
[d f] | ||
(d/on-realized d identity f)) | ||
Comment on lines
+4
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK for now, but this should be in Manifold |
||
|
||
(defn propagate-error | ||
"Registers an error callback with source which will attempt to propagate the error to destination. | ||
|
||
If the error was propagated (i.e. destination wasn't yet realized), on-propagate is invoked with | ||
the error value. | ||
|
||
Returns source." | ||
([source destination] | ||
(propagate-error source destination identity)) | ||
([source destination on-propagate] | ||
(on-error source (fn [e] | ||
(when (d/error! destination e) | ||
(on-propagate e)))))) | ||
Comment on lines
+8
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1480,17 +1480,21 @@ | |
(is (some-> @connect-future .isCancelled))))))) | ||
|
||
(deftest test-in-flight-request-cancellation | ||
(let [conn-established (promise) | ||
conn-closed (promise)] | ||
(let [conn-established (atom nil) | ||
conn-closed (atom nil)] | ||
(with-raw-handler (fn [req] | ||
(deliver conn-established true) | ||
(deliver @conn-established true) | ||
(s/on-closed (:body req) | ||
(fn [] | ||
(deliver conn-closed true)))) | ||
(deliver @conn-closed true)))) | ||
;; NOTE: The atom indirection here is needed because `with-raw-handler` will run the body | ||
;; twice (for HTTP1 and HTTP2), so we need a new promise for each run. | ||
(reset! conn-established (promise)) | ||
(reset! conn-closed (promise)) | ||
(let [rsp (http-get "/")] | ||
(is (= true (deref conn-established 1000 :timeout))) | ||
(is (= true (deref @conn-established 1000 :timeout))) | ||
(http/cancel-request! rsp) | ||
(is (= true (deref conn-closed 1000 :timeout))) | ||
(is (= true (deref @conn-closed 1000 :timeout))) | ||
Comment on lines
-1463
to
+1497
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
(is (thrown? RequestCancellationException (deref rsp 1000 :timeout))))))) | ||
|
||
(deftest ^:leak test-leak-in-raw-stream-handler | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
(ns aleph.util-test | ||
(:require [aleph.util :as util] | ||
[clojure.test :refer [deftest is testing]] | ||
[manifold.deferred :as d])) | ||
|
||
(deftest test-propagate-error | ||
(testing "Happy path" | ||
(let [src (d/deferred) | ||
dst (d/deferred) | ||
prp (promise)] | ||
(util/propagate-error src dst (fn [e] (deliver prp e))) | ||
(d/error! src :boom) | ||
(is (d/realized? dst)) | ||
Comment on lines
+12
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this a race condition? Might need to put them on same executor and thread. |
||
(is (= :boom (d/error-value dst nil))) | ||
(is (= :boom (deref prp 0 nil))))) | ||
|
||
(testing "Without on-propagate" | ||
(let [src (d/deferred) | ||
dst (d/deferred)] | ||
(util/propagate-error src dst) | ||
(d/error! src :boom) | ||
(is (d/realized? dst)))) | ||
|
||
(testing "Exception in on-propagate" | ||
(let [src (d/deferred) | ||
dst (d/deferred)] | ||
(util/propagate-error src dst (fn [_] (throw (RuntimeException. "Oops")))) | ||
(d/error! src :boom) | ||
(is (d/realized? dst)) | ||
(is (= :boom (d/error-value dst nil))))) | ||
|
||
(testing "Already realized destination" | ||
(let [src (d/deferred) | ||
dst (d/success-deferred :ok)] | ||
(util/propagate-error src dst) | ||
(d/error! src :boom) | ||
(is (d/realized? dst)) | ||
(is (= nil (d/error-value dst nil))))) | ||
|
||
(testing "Successfully realized source" | ||
(let [src (d/deferred) | ||
dst (d/deferred)] | ||
(util/propagate-error src dst) | ||
(d/success! src :ok) | ||
(is (not (d/realized? dst)))))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be documented why you would use this over chain or on-realized.