clj-http-client/test/com/puppetlabs/http/client/impl/async_close_test.clj
Jeremy Barlow f859bd907a (TK-101) Move closing of http clients to a separate thread
This commit moves each close call made on a `CloseableHttpAsyncClient`
from the thread on which the request callback is made over to a
different thread in order to avoid a deadlock.

Previously, the client close call was made in the context of thread from
which the callback was invoked.  The Apache HTTP async client library
makes these calls from one of its i/o reactor threads.  In the case of a
"failed" request, e.g., failure to make the client connection, this call
occurs in the context of the primary i/o reactor thread.  The client
close call does an indefinite join on the primary i/o reactor thread
and, therefore, this call causes a deadlock.  The client never closes
and all resources associated with it - threads, file descriptors, etc. -
remain open until the process is shutdown.

This commit introduces a new class, `AsyncClose`, which manages a small,
fixed size thread pool from which client close calls can be executed.
The `async` Clojure and `JavaClient` APIs were updated to use `AsyncClose`
whenever a client needs to be closed from a callback.
2014-10-20 14:22:56 -07:00

22 lines
826 B
Clojure

(ns com.puppetlabs.http.client.impl.async-close-test
(:import (java.io Closeable)
(com.puppetlabs.http.client.impl AsyncClose))
(:require [clojure.test :refer :all]))
(defn closeable
[closeable-promise]
(reify Closeable
(close [this]
(deliver closeable-promise (Thread/currentThread)))))
(deftest closeable-asynchronously-closed
(testing "Close called asynchronously on a closeable"
(let [closeable-promise (promise)
closeable (closeable closeable-promise)]
(AsyncClose/close closeable)
(is @closeable-promise "Promise realized as nil")
(is (instance? Thread @closeable-promise) "Thread not delivered")
(is (not (identical? (Thread/currentThread) @closeable-promise))
"Closeable closed from originating thread, not asynchronously"))))