This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-12
Channels
- # aleph (3)
- # announcements (15)
- # architecture (6)
- # babashka (35)
- # babashka-sci-dev (10)
- # biff (5)
- # calva (9)
- # cherry (1)
- # cider (44)
- # clj-kondo (31)
- # cljfx (1)
- # clojure (108)
- # clojure-europe (32)
- # clojure-norway (12)
- # clojurescript (15)
- # conjure (3)
- # cursive (8)
- # datahike (1)
- # datalevin (19)
- # datascript (1)
- # datomic (59)
- # emacs (4)
- # graphql (3)
- # jobs (1)
- # luminus (6)
- # meander (9)
- # membrane (45)
- # nbb (67)
- # off-topic (16)
- # portal (3)
- # remote-jobs (1)
- # scittle (8)
- # shadow-cljs (46)
- # test-check (7)
- # tools-deps (5)
- # vim (63)
- # web-security (11)
- # xtdb (15)
TIL that if you use
, you do not have any timeout guarantees when reading the HTTP body.
This is also true even if you set connectTimeout
and request timeout
.
https://bugs.openjdk.org/browse/JDK-8258397
And sure enough a scheduling job doing a HTTP call got stuck. However the container it was running thought everything was fine and were not restarted at any point, and thus the scheduling job did not run for a couple of weeks.
So it goes ๐
(clj-http and Apache HttpComponents do time out properly when told to do so though.)
it uses a separate lib that brings in a few middleware, one of which does enable this (https://github.com/mizosoft/methanol)
Thanks! Yeah, I found methanol also when googling this issue. It's also solvable using plain java/clojure with HttpClient/sendAsync like this:
(defn get-or-cancel [^CompletableFuture fut]
(try
(.get fut 2 TimeUnit/SECONDS)
(catch TimeoutException _timeout
(.cancel fut false))))
(defonce client (HttpClient/newHttpClient))
(comment
(let [req (-> (HttpRequest/newBuilder)
(.uri (URI. ""))
(.timeout (Duration/ofSeconds 2))
(.GET)
(.build))]
(try
(let [resp (.sendAsync client req (HttpResponse$BodyHandlers/ofString))]
(get-or-cancel resp))
(catch Throwable t
(println "exception..." t)
(println (ex-message t))))))
That said it would be much better if there was a simple .readTimeout and/or .requestTimeout that applied to the regular HttpClient/send.I wonder how much human time has been spent on debugging what basically amounts to the absence of socket timeouts. I know I've spent a lot. The network in azure container instances is not very stable.
I am not sure your solution would actually trigger cancelation of the underlying stream consumer. But I am on mobile, too lazy to check.
> The default HttpClient implementation returns CompletableFuture objects that are cancelable. CompletableFuture objects derived from cancelable futures are themselves cancelable. Invoking cancel(true) on a cancelable future that is not completed, attempts to cancel the HTTP exchange in an effort to release underlying resources as soon as possible. No guarantee is made as to exactly when the cancellation request may be taken into account. In particular, the request might still get sent to the server, as its processing might already have started asynchronously in another thread, and the underlying resources may only be released asynchronously. That sounds good enough? https://docs.oracle.com/en/java/javase/18/docs/api/java.net.http/java/net/http/HttpClient.html#sendAsync(java.net.http.HttpRequest,java.net.http.HttpResponse.BodyHandler,java.net.http.HttpResponse.PushPromiseHandler)
I have not tried to verify it myself though
I did verify that the future respects the timeout
Sounds good. That might be a good way to avoid methanol indeed. I will test that after my holidays. Thanks for the tip
Thanks for your tip as well. +1 for adding a default timeout value for telex. More libraries should do this, I think.
what's the best channel to ask code architecture/design system questions?
#architecture probably ๐
thanks, that seems adjacent to my potential question!