Sherlock is an Erlang library that provides a connection pooling mechanism for any purposes. It aims to simplify the management of database connections in a concurrent environment.
This 'pool manager' without singletone process called 'manager' and based on ETS and counters. Works fine with pool overloads.
start_pool/2
sherlock:start_pool(PoolName::any(), Options::#{}) -> any().stop_pool/1
sherlock:stop_pool(PoolName::any()) -> any().checkout/1
sherlock:checkout(PoolName::any()) ->
{ok, WorkerPid::pid(), MRef::reference()} | {error, Reason::any()}.checkout/2
sherlock:checkout(PoolName::any(), Timeout::nonnegint()) ->
{ok, WorkerPid::pid(), MRef::reference()} | {error, Reason::any()}.checkin/2
sherlock:checkin(PoolName::any(), {WorkerPid::pid(), MRef::reference()}) ->
any().transaction/2
sherlock:transaction(PoolName::any(), Fun::function()) when is_function(Fun, 1) ->
Result::any() | {error, any()}.transaction/3
sherlock:transaction(PoolName::any(), Fun::function(), Timeout::nonnegint()) when is_function(Fun, 1) ->
Result::any() | {error, any()}.Example of usage with postgres epgsql driver:
sys.config
[
{sherlock, [
{pools, #{
test_database =>
#{
min_size => 4, %% minimal size of pool
max_size => 16, %% maximum pool size
refresh => 50, %% time in millis for checks enlarge/shrink pool
mfa => {
epgsql,
connect,
[#{
host => "localhost",
username => "postgres",
password => "postgres",
database => "postgres",
port => 5432,
timeout => 300,
application_name => "sherlock_test_app"
}]
}
}
}}
]}
].sherlock_test.erl
-module(sherlock_test).
-define(POOL, test_database).
%% API
-export([make_request/2]).
make_request(SQL, Args) ->
Fun = fun(WorkerPid) -> epgsql:equery(WorkerPid, SQL, Args) end,
case sherlock:transaction(?POOL, Fun) of
{error, _} = Error ->
Error;
Result ->
Result
end.