Generic connection pool manager for Erlang applications
Switch branches/tags
Nothing to show
Pull request Compare This branch is 4 commits behind abs:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
include
src
.gitignore
LICENSE
Makefile
README

README

NOMENCLATURE
------------
Endpoint: A database system, or any other connection-oriented service.


INTRODUCTION
------------
connection_pool is a generic connection pool manager for Erlang applications.

Goals:
- Allow pools to be started by OTP supervisors.
- Assign symbolic names to pools (e.g. 'redis.master', 'redis.slave:0', 'redis.slave:1').
- Return 'dead_enpoint' if all connections to an endpoint go away.  This allows the caller to call another endpoint or return acceptable empty results.
- Try to re-establish dead connections.
- Support reassinging endpoint details on a running system. 
- Make it easy to support new types of endpoints.


SUPPORTED ENDPOINT TYPES
------------------------
Currently, the following types of endpoints are supported:

PostgreSQL with epgsql driver (https://github.com/wg/epgsql)

MySQL with http://code.google.com/p/erlang-mysql-driver/ and mysql_conn2.erl (in this package)
NOTE: Don't use MySQL if you have a choice.  Use PostgreSQL.

Redis with Redo driver (https://github.com/JacobVorreuter/redo)
NOTE: If you are using Erldis, we highly recommend using Redo instead.


DEFINING ENDPOINTS
------------------
Example of a set of master-slaves endpoint definitions for Redis:

-define(REDIS_NODES, [
    {'external:0', [{'master', {"127.0.0.1", 6479}}, {'slaves', [{"127.0.0.1", 6480}]}]},
    {'default:0', [{'master', {"127.0.0.1", 6579}}, {'slaves', [{"127.0.0.1", 6580}]}]},
    {'default:1', [{'master', {"127.0.0.1", 6679}}, {'slaves', [{"127.0.0.1", 6680}]}]},
    {'global:0', [{'master', {"127.0.0.1", 6779}}, {'slaves', [{"127.0.0.1", 6780}]}]}
]).


GENERATING CHILD SPECS
----------------------
redo_pool_specs() ->
    [redo_pool:spec(Details) || Details <- connection_pool_utils:pools(redis, ?REDIS_NODES)]. 

% supervisor
init([]) ->
    {ok, {{one_for_one, 3, 40}, redo_pool_specs()}}.


OVERRIDING DEFAULT MODULES
--------------------------
-module(my_redis_pool).
-extends(redo_pool).
-export([num_connections/0]).

% Default is 5, but we want 10.
num_connections() -> 10.


BASIC USAGE
-----------
redis_cmd(PoolName, F) ->
    connection_pool:run({redo_pool, PoolName}, F).

get_foo_bar() ->
    [Foo, Bar] = redis_cmd('default:0', fun(C) ->
        redo:cmd(C, [
            [<<"get">>, <<"foo">>],
            [<<"get">>, <<"bar">>]
        ]) 
    end).


POSTGRESQL POOL STARTED BY SUPERVISOR
-------------------------------------
psql_pool_specs() ->
    PsqlNodes = [{'db:0', [{'master', ["127.0.0.1", "user", "pass", [{database, "db0"}]]}]}],
    [psql_pool:spec(Details) || Details <- connection_pool_utils:pools(psql, PsqlNodes)].

init([]) ->
    {ok, {{one_for_one, 3, 40}, psql_pool_specs()}}.


POSTGRESQL POOL STARTED DIRECTLY (WITHOUT SUPERVISOR)
-----------------------------------------------------
foo() ->
    PsqlNodes = [{'db:0', [{'master', ["127.0.0.1", "user", "pass", [{database, "db0"}]]}]}],
    [{Name, Details}] = connection_pool_utils:pools(psql, PsqlNodes),
    {ok, Pool} = connection_pool:start_link({psql_pool, Name}, Details),
    % do stuff
    connection_pool:close(Pool).


MYSQL
-----
-define(MYSQL_NODES, [{'db:0', [{'master', {{'host', '127.0.0.1'},
                                            {'name', 'foo0'},
                                            {'password', 'foo0p4ss'},
                                            {'port', '3306'},
                                            {'user', 'mysqlu'}}
                                }]}]).

mysql_pool_specs() ->
    [mysql_pool:spec({Name, mysql_pool:details(Details)}) ||
        {Name, Details} <-
            connection_pool_utils:pools(mysql, ?MYSQL_NODES)].