|
23 | 23 | ReadTimeoutException |
24 | 24 | RequestCancellationException |
25 | 25 | RequestTimeoutException) |
26 | | - (io.aleph.dirigiste Pools) |
| 26 | + (io.aleph.dirigiste IPool Pools) |
27 | 27 | (io.netty.channel ConnectTimeoutException) |
28 | 28 | (io.netty.handler.codec Headers) |
29 | 29 | (io.netty.handler.codec.http HttpHeaders) |
30 | 30 | (java.net |
31 | 31 | InetSocketAddress |
32 | 32 | URI) |
33 | | - (java.util.concurrent TimeoutException))) |
| 33 | + (java.util.concurrent Executor TimeoutException))) |
34 | 34 |
|
35 | 35 | (defn start-server |
36 | 36 | "Starts an HTTP server using the provided Ring `handler`. Returns a server |
|
133 | 133 | (def ^:no-doc default-response-executor |
134 | 134 | (flow/utilization-executor 0.9 256 {:onto? false})) |
135 | 135 |
|
| 136 | +;; Wrapper record to associate a response-executor with a connection pool. |
| 137 | +;; This enables the `request` function to use the pool's executor for response deferreds. |
| 138 | +(defrecord PoolWithExecutor [^IPool pool ^Executor response-executor] |
| 139 | + java.io.Closeable |
| 140 | + (close [_] (.shutdown pool)) |
| 141 | + |
| 142 | + IPool |
| 143 | + (shutdown [_] (.shutdown pool))) |
| 144 | + |
| 145 | +(defn- get-pool |
| 146 | + "Returns the underlying IPool from a pool or PoolWithExecutor." |
| 147 | + ^IPool [pool] |
| 148 | + (if (instance? PoolWithExecutor pool) |
| 149 | + (:pool pool) |
| 150 | + pool)) |
| 151 | + |
| 152 | +(defn- get-response-executor |
| 153 | + "Returns the response-executor from a PoolWithExecutor, or the default executor." |
| 154 | + [pool] |
| 155 | + (if (instance? PoolWithExecutor pool) |
| 156 | + (:response-executor pool) |
| 157 | + default-response-executor)) |
| 158 | + |
136 | 159 | (defn connection-pool |
137 | 160 | "Returns a connection pool which can be used as an argument in `request`. |
138 | 161 |
|
|
251 | 274 |
|
252 | 275 | true |
253 | 276 | (update :ssl-context #(client/ssl-context % http-versions insecure?))) |
| 277 | + response-executor' (:response-executor connection-options) |
254 | 278 | p (promise) |
255 | 279 | create-pool-fn (or pool-builder-fn |
256 | 280 | flow/instrumented-pool) |
257 | 281 | create-pool-ctrl-fn (or pool-controller-builder-fn |
258 | 282 | #(Pools/utilizationController target-utilization connections-per-host total-connections)) |
259 | | - pool (create-pool-fn |
| 283 | + raw-pool (create-pool-fn |
260 | 284 | {:generate (fn [host] |
261 | 285 | (let [c (promise) |
262 | 286 | conn (create-connection |
263 | 287 | host |
264 | 288 | conn-options' |
265 | 289 | middleware |
266 | | - #(flow/dispose @p host [@c]))] |
| 290 | + #(flow/dispose (get-pool @p) host [@c]))] |
267 | 291 | (deliver c conn) |
268 | 292 | [conn])) |
269 | 293 | :destroy (fn [_ c] |
|
273 | 297 | :control-period control-period |
274 | 298 | :max-queue-size max-queue-size |
275 | 299 | :controller (create-pool-ctrl-fn) |
276 | | - :stats-callback stats-callback})] |
| 300 | + :stats-callback stats-callback}) |
| 301 | + pool (if response-executor' |
| 302 | + (->PoolWithExecutor raw-pool response-executor') |
| 303 | + raw-pool)] |
277 | 304 | @(deliver p pool))) |
278 | 305 |
|
279 | 306 | (def ^:no-doc default-connection-pool |
|
384 | 411 | request-timeout |
385 | 412 | read-timeout] |
386 | 413 | :or {pool default-connection-pool |
387 | | - response-executor default-response-executor |
388 | 414 | middleware identity |
389 | 415 | connection-timeout aleph.netty/default-connect-timeout} |
390 | 416 | :as req}] |
391 | | - (let [dispose-conn! (atom (fn [])) |
392 | | - result (d/deferred response-executor) |
393 | | - response (executor/with-executor response-executor |
| 417 | + (let [response-executor' (or response-executor (get-response-executor pool)) |
| 418 | + raw-pool (get-pool pool) |
| 419 | + dispose-conn! (atom (fn [])) |
| 420 | + result (d/deferred response-executor') |
| 421 | + response (executor/with-executor response-executor' |
394 | 422 | ((middleware |
395 | 423 | (fn [req] |
396 | 424 | (let [k (client/req->domain req) |
397 | 425 | start (System/currentTimeMillis)] |
398 | 426 |
|
399 | 427 | ;; acquire a connection |
400 | | - (-> (flow/acquire pool k) |
| 428 | + (-> (flow/acquire raw-pool k) |
401 | 429 | (maybe-timeout! pool-timeout) |
402 | 430 |
|
403 | 431 | ;; pool timeout triggered |
|
410 | 438 | ;; NOTE: All error handlers below delegate disposal of the |
411 | 439 | ;; connection to the error handler on `result` which uses this |
412 | 440 | ;; function. |
413 | | - (reset! dispose-conn! (fn [] (flow/dispose pool k conn))) |
| 441 | + (reset! dispose-conn! (fn [] (flow/dispose raw-pool k conn))) |
414 | 442 |
|
415 | 443 | (if (realized? result) |
416 | 444 | ;; to account for race condition between setting `dispose-conn!` |
|
478 | 506 | (<= 400 (:status rsp))) |
479 | 507 | (do |
480 | 508 | (log/trace "Connection finished. Disposing...") |
481 | | - (flow/dispose pool k conn)) |
482 | | - (flow/release pool k conn))))) |
| 509 | + (flow/dispose raw-pool k conn)) |
| 510 | + (flow/release raw-pool k conn))))) |
483 | 511 | (-> rsp |
484 | 512 | (dissoc :aleph/destroy-conn?) |
485 | 513 | (assoc :connection-time (- end start))))))))) |
|
0 commit comments