Subversion Repositories SE.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 7u83 1
# Poolboy - A hunky Erlang worker pool factory
2
 
3
[![Build Status](https://api.travis-ci.org/devinus/poolboy.svg?branch=master)](https://travis-ci.org/devinus/poolboy)
4
 
5
[![Support via Gratipay](https://cdn.rawgit.com/gratipay/gratipay-badge/2.3.0/dist/gratipay.png)](https://gratipay.com/devinus/)
6
 
7
Poolboy is a **lightweight**, **generic** pooling library for Erlang with a
8
focus on **simplicity**, **performance**, and **rock-solid** disaster recovery.
9
 
10
## Usage
11
 
12
```erl-sh
13
1> Worker = poolboy:checkout(PoolName).
14
<0.9001.0>
15
2> gen_server:call(Worker, Request).
16
ok
17
3> poolboy:checkin(PoolName, Worker).
18
ok
19
```
20
 
21
## Example
22
 
23
This is an example application showcasing database connection pools using
24
Poolboy and [epgsql](https://github.com/epgsql/epgsql).
25
 
26
### example.app
27
 
28
```erlang
29
{application, example, [
30
    {description, "An example application"},
31
    {vsn, "0.1"},
32
    {applications, [kernel, stdlib, sasl, crypto, ssl]},
33
    {modules, [example, example_worker]},
34
    {registered, [example]},
35
    {mod, {example, []}},
36
    {env, [
37
        {pools, [
38
            {pool1, [
39
                {size, 10},
40
                {max_overflow, 20}
41
			], [
42
                {hostname, "127.0.0.1"},
43
                {database, "db1"},
44
                {username, "db1"},
45
                {password, "abc123"}
46
            ]},
47
            {pool2, [
48
                {size, 5},
49
                {max_overflow, 10}
50
			], [
51
                {hostname, "127.0.0.1"},
52
                {database, "db2"},
53
                {username, "db2"},
54
                {password, "abc123"}
55
            ]}
56
        ]}
57
    ]}
58
]}.
59
```
60
 
61
### example.erl
62
 
63
```erlang
64
-module(example).
65
-behaviour(application).
66
-behaviour(supervisor).
67
 
68
-export([start/0, stop/0, squery/2, equery/3]).
69
-export([start/2, stop/1]).
70
-export([init/1]).
71
 
72
start() ->
73
    application:start(?MODULE).
74
 
75
stop() ->
76
    application:stop(?MODULE).
77
 
78
start(_Type, _Args) ->
79
    supervisor:start_link({local, example_sup}, ?MODULE, []).
80
 
81
stop(_State) ->
82
    ok.
83
 
84
init([]) ->
85
    {ok, Pools} = application:get_env(example, pools),
86
    PoolSpecs = lists:map(fun({Name, SizeArgs, WorkerArgs}) ->
87
        PoolArgs = [{name, {local, Name}},
88
            		{worker_module, example_worker}] ++ SizeArgs,
89
        poolboy:child_spec(Name, PoolArgs, WorkerArgs)
90
    end, Pools),
91
    {ok, {{one_for_one, 10, 10}, PoolSpecs}}.
92
 
93
squery(PoolName, Sql) ->
94
    poolboy:transaction(PoolName, fun(Worker) ->
95
        gen_server:call(Worker, {squery, Sql})
96
    end).
97
 
98
equery(PoolName, Stmt, Params) ->
99
    poolboy:transaction(PoolName, fun(Worker) ->
100
        gen_server:call(Worker, {equery, Stmt, Params})
101
    end).
102
```
103
 
104
### example_worker.erl
105
 
106
```erlang
107
-module(example_worker).
108
-behaviour(gen_server).
109
-behaviour(poolboy_worker).
110
 
111
-export([start_link/1]).
112
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
113
         code_change/3]).
114
 
115
-record(state, {conn}).
116
 
117
start_link(Args) ->
118
    gen_server:start_link(?MODULE, Args, []).
119
 
120
init(Args) ->
121
    process_flag(trap_exit, true),
122
    Hostname = proplists:get_value(hostname, Args),
123
    Database = proplists:get_value(database, Args),
124
    Username = proplists:get_value(username, Args),
125
    Password = proplists:get_value(password, Args),
126
    {ok, Conn} = epgsql:connect(Hostname, Username, Password, [
127
        {database, Database}
128
    ]),
129
    {ok, #state{conn=Conn}}.
130
 
131
handle_call({squery, Sql}, _From, #state{conn=Conn}=State) ->
132
    {reply, epgsql:squery(Conn, Sql), State};
133
handle_call({equery, Stmt, Params}, _From, #state{conn=Conn}=State) ->
134
    {reply, epgsql:equery(Conn, Stmt, Params), State};
135
handle_call(_Request, _From, State) ->
136
    {reply, ok, State}.
137
 
138
handle_cast(_Msg, State) ->
139
    {noreply, State}.
140
 
141
handle_info(_Info, State) ->
142
    {noreply, State}.
143
 
144
terminate(_Reason, #state{conn=Conn}) ->
145
    ok = epgsql:close(Conn),
146
    ok.
147
 
148
code_change(_OldVsn, State, _Extra) ->
149
    {ok, State}.
150
```
151
 
152
## Options
153
 
154
- `name`: the pool name
155
- `worker_module`: the module that represents the workers
156
- `size`: maximum pool size
157
- `max_overflow`: maximum number of workers created if pool is empty
158
- `strategy`: `lifo` or `fifo`, determines whether checked in workers should be
159
  placed first or last in the line of available workers. So, `lifo` operates like a traditional stack; `fifo` like a queue. Default is `lifo`.
160
 
161
## Authors
162
 
163
- Devin Torres (devinus) <devin@devintorres.com>
164
- Andrew Thompson (Vagabond) <andrew@hijacked.us>
165
- Kurt Williams (onkel-dirtus) <kurt.r.williams@gmail.com>
166
 
167
## License
168
 
169
Poolboy is available in the public domain (see `UNLICENSE`).
170
Poolboy is also optionally available under the ISC license (see `LICENSE`),
171
meant especially for jurisdictions that do not recognize public domain works.