Skip to content

Commit cf15810

Browse files
leonardbbenoitc
authored andcommitted
(feat) Support 'checkout_timeout' option (#520)
* (feat) Support 'checkout_timeout' option Allow caller to handle overload when pool is maxed out rather than returning incorrect 'connection_timeout' response * (fix) fix timeout on pool test causing CI failure * (fix) Fall back to connect_timeout when checkout_timeout is not set
1 parent 499de03 commit cf15810

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

src/hackney.erl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ request(Method, URL, Headers, Body) ->
238238
%% <li>`{proxy, proxy_options()}': to connect via a proxy.</li>
239239
%% <li>`insecure': to perform "insecure" SSL connections and
240240
%% transfers without checking the certificate</li>
241+
%% <li>`{checkout_timeout, infinity | integer()}': timeout used when
242+
%% checking out a socket from the pool, in milliseconds. Default is 8000</li>
241243
%% <li>`{connect_timeout, infinity | integer()}': timeout used when
242244
%% establishing a connection, in milliseconds. Default is 8000</li>
243245
%% <li>`{recv_timeout, infinity | integer()}': timeout used when

src/hackney_pool.erl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ checkout(Host0, Port, Transport, #client{options=Opts}=Client) ->
6868
Name = proplists:get_value(pool, Opts, default),
6969
Pool = find_pool(Name, Opts),
7070
ConnectTimeout = proplists:get_value(connect_timeout, Opts, 8000),
71+
%% Fall back to using connect_timeout if checkout_timeout is not set
72+
CheckoutTimeout = proplists:get_value(checkout_timeout, Opts, ConnectTimeout),
7173
case catch gen_server:call(Pool, {checkout, {Host, Port, Transport},
72-
Pid, RequestRef}, ConnectTimeout) of
74+
Pid, RequestRef}, CheckoutTimeout) of
7375
{ok, Socket, Owner} ->
7476
CheckinReference = {Host, Port, Transport},
7577
{ok, {Name, RequestRef, CheckinReference, Owner, Transport}, Socket};
@@ -82,7 +84,7 @@ checkout(Host0, Port, Transport, #client{options=Opts}=Client) ->
8284
{'EXIT', {timeout, _}} ->
8385
% socket will still checkout so to avoid deadlock we send in a cancellation
8486
gen_server:cast(Pool, {checkout_cancel, {Host, Port, Transport}, RequestRef}),
85-
{error, connect_timeout}
87+
{error, checkout_timeout}
8688
end.
8789

8890
%% @doc release a socket in the pool

test/hackney_pool_tests.erl

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ dummy_test() ->
88

99
multipart_test_() ->
1010
{setup, fun start/0, fun stop/1,
11-
[queue_timeout()]}.
11+
[{timeout, 120, queue_timeout()},
12+
{timeout, 120, checkout_timeout()}]}.
1213

1314
start() ->
1415
error_logger:tty(false),
@@ -39,7 +40,20 @@ queue_timeout() ->
3940
ok = hackney:finish_send_body(Ref),
4041
{ok, _Status, _Headers, Ref} = hackney:start_response(Ref),
4142
ok = hackney:skip_body(Ref),
42-
{ok, _} = hackney:request(post, URL, Headers, stream, Opts)
43+
{ok, Ref2} = hackney:request(post, URL, Headers, stream, Opts),
44+
hackney:close(Ref2)
4345
end
4446
end.
4547

48+
checkout_timeout() ->
49+
fun() ->
50+
URL = <<"http://localhost:8123/pool">>,
51+
Headers = [],
52+
Opts = [{max_body, 2048}, {pool, pool_test}, {connect_timeout, 1000}, {checkout_timeout, 100}],
53+
case hackney:request(post, URL, Headers, stream, Opts) of
54+
{ok, Ref} ->
55+
{error, Error} = hackney:request(post, URL, Headers, stream, Opts),
56+
hackney:close(Ref),
57+
?assertEqual(Error, checkout_timeout)
58+
end
59+
end.

0 commit comments

Comments
 (0)