Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

add functions to change options of a pool

  • Loading branch information...
commit 7d72c55f0b06a42065317f8d69d83a0355d6cbae 1 parent 25e1186
@benoitc authored
View
30 README.md
@@ -126,6 +126,36 @@ the request body:
- `{file, File}` : To send a file
- Bin: To send a binary
+### Use a pool
+
+To reuse a connection globally in your application you can also use a
+socket pool. On startup, hackney launch a pool named default. To use it
+do the following<pre>Method = get,
+URL = <<"https://friendpaste.com">>,
+Headers = [],
+Payload = <<>>,
+Options = [{pool, default}],
+{ok, StatusCode, RespHeaders, Client} = hackney:request(Method, URL, Headers,
+ Payload, Options).</pre>
+
+By adding the tuple `{pool, default}` to the options, hackney will use
+the connections stored in that pool.
+
+You can also use different pools in your application which will allows
+you to maintain some kind of group of connections.
+
+```
+PoolName = mypool,
+Options = [{timeout, 150000}, {pool_size, 100}],
+{ok, Pid} = hackney:start_pool(PoolName, Options),`''
+
+`timeout` is the time we keep alive the conneciton in the pool,
+`pool_size` is the number of connections maintained in the pool. Each
+connection in a pool is monitored and closed connections are removed
+automatically.
+
+To close a pool do:<pre>hackney:stop_pool(PoolName).</pre>
+
Contribute
----------
For issues, comments or feedback please [create an issue!] [1][1]: http://github.com/benoitc/hackney/issues "hackney issues"
View
1  TODO.md
@@ -2,7 +2,6 @@
todo of hackney
-- Add multiple connexions pool support
- Add multipart support
- Add Websockets support
- Add SPDY support
View
30 doc/README.md
@@ -126,6 +126,36 @@ the request body:
- `{file, File}` : To send a file
- Bin: To send a binary
+### Use a pool
+
+To reuse a connection globally in your application you can also use a
+socket pool. On startup, hackney launch a pool named default. To use it
+do the following<pre>Method = get,
+URL = <<"https://friendpaste.com">>,
+Headers = [],
+Payload = <<>>,
+Options = [{pool, default}],
+{ok, StatusCode, RespHeaders, Client} = hackney:request(Method, URL, Headers,
+ Payload, Options).</pre>
+
+By adding the tuple `{pool, default}` to the options, hackney will use
+the connections stored in that pool.
+
+You can also use different pools in your application which will allows
+you to maintain some kind of group of connections.
+
+```
+PoolName = mypool,
+Options = [{timeout, 150000}, {pool_size, 100}],
+{ok, Pid} = hackney:start_pool(PoolName, Options),`''
+
+`timeout` is the time we keep alive the conneciton in the pool,
+`pool_size` is the number of connections maintained in the pool. Each
+connection in a pool is monitored and closed connections are removed
+automatically.
+
+To close a pool do:<pre>hackney:stop_pool(PoolName).</pre>
+
Contribute
----------
For issues, comments or feedback please [create an issue!] [1][1]: http://github.com/benoitc/hackney/issues "hackney issues"
View
26 doc/hackney.md
@@ -11,7 +11,7 @@
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#body-1">body/1</a></td><td>Return the full body sent with the response.</td></tr><tr><td valign="top"><a href="#body-2">body/2</a></td><td>Return the full body sent with the response as long as the body
-length doesn't go over MaxLength.</td></tr><tr><td valign="top"><a href="#close-1">close/1</a></td><td></td></tr><tr><td valign="top"><a href="#connect-1">connect/1</a></td><td></td></tr><tr><td valign="top"><a href="#connect-3">connect/3</a></td><td></td></tr><tr><td valign="top"><a href="#connect-4">connect/4</a></td><td></td></tr><tr><td valign="top"><a href="#pool-1">pool/1</a></td><td>get current pool pid or name used by a client if needed.</td></tr><tr><td valign="top"><a href="#request-1">request/1</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-2">request/2</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-3">request/3</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-4">request/4</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-5">request/5</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#send_request-2">send_request/2</a></td><td></td></tr><tr><td valign="top"><a href="#set_sockopts-2">set_sockopts/2</a></td><td></td></tr><tr><td valign="top"><a href="#skip_body-1">skip_body/1</a></td><td>skip the full body.</td></tr><tr><td valign="top"><a href="#start-0">start/0</a></td><td>Start the couchbeam process.</td></tr><tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stop the couchbeam process.</td></tr><tr><td valign="top"><a href="#stream_body-1">stream_body/1</a></td><td>Stream the response body.</td></tr></table>
+length doesn't go over MaxLength.</td></tr><tr><td valign="top"><a href="#close-1">close/1</a></td><td>close the client.</td></tr><tr><td valign="top"><a href="#connect-1">connect/1</a></td><td>connect a socket and create a client state.</td></tr><tr><td valign="top"><a href="#connect-3">connect/3</a></td><td></td></tr><tr><td valign="top"><a href="#connect-4">connect/4</a></td><td></td></tr><tr><td valign="top"><a href="#pool-1">pool/1</a></td><td>get current pool pid or name used by a client if needed.</td></tr><tr><td valign="top"><a href="#request-1">request/1</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-2">request/2</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-3">request/3</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-4">request/4</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#request-5">request/5</a></td><td>make a request.</td></tr><tr><td valign="top"><a href="#send_request-2">send_request/2</a></td><td></td></tr><tr><td valign="top"><a href="#set_sockopts-2">set_sockopts/2</a></td><td>add set sockets options in the client.</td></tr><tr><td valign="top"><a href="#skip_body-1">skip_body/1</a></td><td>skip the full body.</td></tr><tr><td valign="top"><a href="#start-0">start/0</a></td><td>Start the couchbeam process.</td></tr><tr><td valign="top"><a href="#start_pool-2">start_pool/2</a></td><td>start a pool.</td></tr><tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stop the couchbeam process.</td></tr><tr><td valign="top"><a href="#stop_pool-1">stop_pool/1</a></td><td>stop a pool.</td></tr><tr><td valign="top"><a href="#stream_body-1">stream_body/1</a></td><td>Stream the response body.</td></tr></table>
<a name="functions"></a>
@@ -44,14 +44,14 @@ length doesn't go over MaxLength.<a name="close-1"></a>
`close(Client) -> any()`
-<a name="connect-1"></a>
+close the client<a name="connect-1"></a>
###connect/1##
`connect(Client) -> any()`
-<a name="connect-3"></a>
+connect a socket and create a client state.<a name="connect-3"></a>
###connect/3##
@@ -154,7 +154,7 @@ Args:
`set_sockopts(Client, Options) -> any()`
-<a name="skip_body-1"></a>
+add set sockets options in the client<a name="skip_body-1"></a>
###skip_body/1##
@@ -170,14 +170,28 @@ skip the full body. (read all the body if needed).<a name="start-0"></a>
`start() -> any()`
-Start the couchbeam process. Useful when testing using the shell.<a name="stop-0"></a>
+Start the couchbeam process. Useful when testing using the shell.<a name="start_pool-2"></a>
+
+###start_pool/2##
+
+
+`start_pool(Name, Options) -> any()`
+
+start a pool<a name="stop-0"></a>
###stop/0##
`stop() -> any()`
-Stop the couchbeam process. Useful when testing using the shell.<a name="stream_body-1"></a>
+Stop the couchbeam process. Useful when testing using the shell.<a name="stop_pool-1"></a>
+
+###stop_pool/1##
+
+
+`stop_pool(Name) -> any()`
+
+stop a pool<a name="stream_body-1"></a>
###stream_body/1##
View
67 doc/hackney_pool.md
@@ -13,14 +13,23 @@ __Behaviours:__ [`gen_server`](gen_server.md).<a name="index"></a>
##Function Index##
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#pool_size-1">pool_size/1</a></td><td></td></tr><tr><td valign="top"><a href="#pool_size-2">pool_size/2</a></td><td></td></tr><tr><td valign="top"><a href="#release-3">release/3</a></td><td></td></tr><tr><td valign="top"><a href="#socket-2">socket/2</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr><tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr></table>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#child_spec-2">child_spec/2</a></td><td>return a child spec suitable for embeding your pool in the
+supervisor.</td></tr><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr><tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr><tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr><tr><td valign="top"><a href="#max_poolsize-1">max_poolsize/1</a></td><td>get max pool size.</td></tr><tr><td valign="top"><a href="#pool_size-1">pool_size/1</a></td><td>get total pool size.</td></tr><tr><td valign="top"><a href="#pool_size-2">pool_size/2</a></td><td>get the pool size for <code>{Transport, Host0, Port}</code></td></tr><tr><td valign="top"><a href="#release-3">release/3</a></td><td>release a socket in the pool.</td></tr><tr><td valign="top"><a href="#set_poolsize-2">set_poolsize/2</a></td><td>change the pool size.</td></tr><tr><td valign="top"><a href="#set_timeout-2">set_timeout/2</a></td><td>change the connection timeout.</td></tr><tr><td valign="top"><a href="#socket-2">socket/2</a></td><td>fetch a socket from the pool.</td></tr><tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr><tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr><tr><td valign="top"><a href="#start_pool-2">start_pool/2</a></td><td>start a pool.</td></tr><tr><td valign="top"><a href="#stop_pool-1">stop_pool/1</a></td><td>stop a pool.</td></tr><tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr><tr><td valign="top"><a href="#timeout-1">timeout/1</a></td><td>get timeout.</td></tr></table>
<a name="functions"></a>
##Function Details##
-<a name="code_change-3"></a>
+<a name="child_spec-2"></a>
+
+###child_spec/2##
+
+
+`child_spec(Name, Options0) -> any()`
+
+return a child spec suitable for embeding your pool in the
+supervisor<a name="code_change-3"></a>
###code_change/3##
@@ -55,27 +64,49 @@ __Behaviours:__ [`gen_server`](gen_server.md).<a name="index"></a>
`init(Options) -> any()`
-<a name="pool_size-1"></a>
+<a name="max_poolsize-1"></a>
+
+###max_poolsize/1##
+
+
+`max_poolsize(PidOrName) -> any()`
+
+get max pool size<a name="pool_size-1"></a>
###pool_size/1##
`pool_size(PidOrName) -> any()`
-<a name="pool_size-2"></a>
+get total pool size<a name="pool_size-2"></a>
###pool_size/2##
`pool_size(PidOrName, X2) -> any()`
-<a name="release-3"></a>
+get the pool size for `{Transport, Host0, Port}`<a name="release-3"></a>
###release/3##
`release(PidOrName, X2, Socket) -> any()`
+release a socket in the pool<a name="set_poolsize-2"></a>
+
+###set_poolsize/2##
+
+
+`set_poolsize(PidOrName, NewSize) -> any()`
+
+change the pool size<a name="set_timeout-2"></a>
+
+###set_timeout/2##
+
+
+`set_timeout(PidOrName, NewTimeout) -> any()`
+
+change the connection timeout
<a name="socket-2"></a>
###socket/2##
@@ -83,7 +114,7 @@ __Behaviours:__ [`gen_server`](gen_server.md).<a name="index"></a>
`socket(PidOrName, X2) -> any()`
-<a name="start_link-0"></a>
+fetch a socket from the pool<a name="start_link-0"></a>
###start_link/0##
@@ -97,10 +128,32 @@ __Behaviours:__ [`gen_server`](gen_server.md).<a name="index"></a>
`start_link(Options0) -> any()`
-<a name="terminate-2"></a>
+<a name="start_pool-2"></a>
+
+###start_pool/2##
+
+
+`start_pool(Name, Options) -> any()`
+
+start a pool<a name="stop_pool-1"></a>
+
+###stop_pool/1##
+
+
+`stop_pool(Name) -> any()`
+
+stop a pool<a name="terminate-2"></a>
###terminate/2##
`terminate(Reason, State) -> any()`
+<a name="timeout-1"></a>
+
+###timeout/1##
+
+
+`timeout(PidOrName) -> any()`
+
+get timeout
View
40 doc/overview.edoc
@@ -186,6 +186,46 @@ the request body:
- `{file, File}' : To send a file
- Bin: To send a binary
+### Use a pool
+
+To reuse a connection globally in your application you can also use a
+socket pool. On startup, hackney launch a pool named default. To use it
+do the following
+
+```
+Method = get,
+URL = <<"https://friendpaste.com">>,
+Headers = [],
+Payload = <<>>,
+Options = [{pool, default}],
+{ok, StatusCode, RespHeaders, Client} = hackney:request(Method, URL, Headers,
+ Payload, Options).
+'''
+
+By adding the tuple `{pool, default}` to the options, hackney will use
+the connections stored in that pool.
+
+You can also use different pools in your application which will allows
+you to maintain some kind of group of connections.
+
+```
+PoolName = mypool,
+Options = [{timeout, 150000}, {pool_size, 100}],
+{ok, Pid} = hackney:start_pool(PoolName, Options),
+'''
+
+`timeout' is the time we keep alive the conneciton in the pool,
+`pool_size' is the number of connections maintained in the pool. Each
+connection in a pool is monitored and closed connections are removed
+automatically.
+
+
+To close a pool do:
+
+```
+hackney:stop_pool(PoolName).
+'''
+
Contribute
----------
View
16 src/hackney.erl
@@ -11,6 +11,7 @@
-export([connect/1, connect/3, connect/4,
close/1,
set_sockopts/2,
+ start_pool/2, stop_pool/1,
request/1, request/2, request/3, request/4, request/5,
send_request/2,
stream_body/1,
@@ -30,6 +31,7 @@ start() ->
stop() ->
application:stop(hackney).
+%% @doc connect a socket and create a client state.
connect(#client{state=connected}=Client) ->
{ok, Client};
@@ -54,12 +56,23 @@ connect(Transport, Host, Port, #client{socket=Skt}=Client)
connect(Transport, Host, Port, Options) when is_list(Options) ->
connect(Transport, Host, Port, #client{options=Options}).
+
+%% @doc close the client
close(Client) ->
hackney_response:close(Client).
+%% @doc add set sockets options in the client
set_sockopts(#client{transport=Transport, socket=Skt}, Options) ->
Transport:setopts(Skt, Options).
+%% @doc start a pool
+start_pool(Name, Options) ->
+ hackney_pool:start_pool(Name, Options).
+
+%% @doc stop a pool
+stop_pool(Name) ->
+ hackney_pool:stop_pool(Name).
+
%% @doc make a request
-spec request(binary()|list())
@@ -187,6 +200,9 @@ pool(#client{options=Opts}) ->
end.
+
+%% internal functions
+%%
socket_from_pool(Pool, {Transport, Host, Port}=Key, Client) ->
case hackney_pool:socket(Pool, Key) of
{ok, Skt} ->
View
66 src/hackney_pool.erl
@@ -13,7 +13,10 @@
-export([start_link/0, start_link/1]).
-export([socket/2, release/3,
- pool_size/1, pool_size/2]).
+ pool_size/1, pool_size/2,
+ max_poolsize/1, set_poolsize/2,
+ timeout/1, set_timeout/2,
+ child_spec/2, start_pool/2, stop_pool/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -25,24 +28,69 @@
connections = dict:new(),
sockets = dict:new()}).
-
+%% @doc fetch a socket from the pool
socket(PidOrName, {Transport, Host0, Port}) ->
Host = string:to_lower(Host0),
Pid = self(),
gen_server:call(PidOrName, {socket, {Transport, Host, Port}, Pid}).
+%% @doc release a socket in the pool
release(PidOrName, {Transport, Host0, Port}, Socket) ->
Host = string:to_lower(Host0),
gen_server:call(PidOrName, {release, {Transport, Host, Port}, Socket}).
-
+%% @doc get total pool size
pool_size(PidOrName) ->
gen_server:call(PidOrName, pool_size).
+%% @doc get the pool size for `{Transport, Host0, Port}'
pool_size(PidOrName, {Transport, Host0, Port}) ->
Host = string:to_lower(Host0),
gen_server:call(PidOrName, {pool_size, {Transport, Host, Port}}).
+%% @doc get max pool size
+max_poolsize(PidOrName) ->
+ gen_server:call(PidOrName, max_poolsize).
+
+%% @doc change the pool size
+set_poolsize(default, NewSize) ->
+ set_poolsize(whereis(hackney_pool), NewSize);
+set_poolsize(PidOrName, NewSize) ->
+ gen_server:cast(PidOrName, {set_poolsize, NewSize}).
+
+%% @doc get timeout
+timeout(PidOrName) ->
+ gen_server:call(PidOrName, timeout).
+
+%% @doc change the connection timeout
+%%
+set_timeout(PidOrName, NewTimeout) ->
+ gen_server:cast(PidOrName, {set_timeout, NewTimeout}).
+
+
+
+%% @doc return a child spec suitable for embeding your pool in the
+%% supervisor
+child_spec(Name, Options0) ->
+ Options = [{name, Name} | Options0],
+ {Name, {hackney_pool, start_link, [Options]},
+ permanent, 10000, worker, [Name]}.
+
+%% @doc start a pool
+start_pool(Name, Options) ->
+ Spec = child_spec(Name, Options),
+ supervisor:start_child(hackney_sup, Spec).
+
+%% @doc stop a pool
+stop_pool(Name) ->
+ case supervisor:terminate_child(hackney_sup, Name) of
+ ok ->
+ supervisor:delete_child(hackney_sup, Name);
+ Error ->
+ Error
+ end.
+
+
start_link() ->
start_link([]).
@@ -60,7 +108,10 @@ init(Options) ->
Timeout = proplists:get_value(timeout, Options),
{ok, #state{pool_size=PoolSize, timeout=Timeout}}.
-
+handle_call(timeout, _From, #state{timeout=Timeout}=State) ->
+ {reply, Timeout, State};
+handle_call(max_poolsize, _From, #state{pool_size=Size}=State) ->
+ {reply, Size, State};
handle_call({socket, Key, Pid}, _From, State) ->
{Reply, NewState} = find_connection(Key, Pid, State),
{reply, Reply, NewState};
@@ -78,6 +129,11 @@ handle_call({pool_size, Key}, _From, #state{connections=Conns}=State) ->
end,
{ok, Size, State}.
+handle_cast({set_poolsize, NewSize}, State) ->
+ {noreply, State#state{pool_size=NewSize}};
+handle_cast({set_timeout, NewTimeout}, State) ->
+ {noreply, State#state{timeout=NewTimeout}};
+
handle_cast(_Msg, State) ->
{noreply, State}.
@@ -102,7 +158,7 @@ code_change(_OldVsn, State, _Extra) ->
{ok, State}.
terminate(_Reason, #state{sockets=Sockets}) ->
- lists:foreach(fun(Socket, {{Transport, _, _}, Timer}) ->
+ lists:foreach(fun({Socket, {{Transport, _, _}, Timer}}) ->
cancel_timer(Socket, Timer),
Transport:close(Socket)
end, dict:to_list(Sockets)),
Please sign in to comment.
Something went wrong with that request. Please try again.