├── .gitignore
├── Makefile
├── README.rdoc
├── doc
├── README.md
├── edoc-info
├── eredis_pool.md
├── eredis_pool_app.md
├── eredis_pool_sup.md
├── erlang.png
└── stylesheet.css
├── rebar
├── rebar.config
├── src
├── eredis_pool.app.src
├── eredis_pool.erl
├── eredis_pool_app.erl
└── eredis_pool_sup.erl
├── test.config
└── test
└── eredis_pool_tests.erl
/.gitignore:
--------------------------------------------------------------------------------
1 | *.beam
2 | ebin
3 | .eunit
4 | *~
5 | erl_crash.dump
6 | db
7 | deps
8 | .DS_Store
9 | eunit.coverage.xml
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | ERL=erl
2 | BEAMDIR=./deps/*/ebin ./ebin
3 | REBAR=./rebar
4 |
5 | all: clean get-deps update-deps compile xref
6 |
7 | update-deps:
8 | @$(REBAR) update-deps
9 |
10 | get-deps:
11 | @$(REBAR) get-deps
12 |
13 | compile:
14 | @$(REBAR) compile
15 |
16 | xref:
17 | @$(REBAR) xref skip_deps=true
18 |
19 | clean:
20 | @ $(REBAR) clean
21 |
22 | eunit:
23 | @rm -rf .eunit
24 | @mkdir -p .eunit
25 | @ERL_FLAGS="-config test.config" $(REBAR) skip_deps=true eunit
26 |
27 | test: eunit
28 |
29 | edoc:
30 | @$(REBAR) skip_deps=true doc
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | = eredis_pool
2 |
3 | eredis_pool is Pool of Redis clients, using eredis and poolboy.
4 |
5 | eredis:
6 | https://github.com/wooga/eredis
7 |
8 | poolboy:
9 | https://github.com/devinus/poolboy
10 |
11 | ==Setup
12 |
13 | $ git clone git://github.com/hiroeorz/eredis_pool.git
14 | $ cd eredis_pool
15 | $ make get-deps
16 | $ make
17 |
18 | ==Testing
19 | $ make test
20 |
21 | ==Settings
22 | edit src/eredis_pool.app.src
23 |
24 | {application, eredis_pool,
25 | [
26 | {description, ""},
27 | {vsn, "1"},
28 | {registered, []},
29 | {applications, [
30 | kernel,
31 | stdlib
32 | ]},
33 | {mod, { eredis_pool_app, []}},
34 | {env, [
35 | {global_or_local, local},
36 | {pools, [
37 | {default, [
38 | {size, 10},
39 | {max_overflow, 20}
40 | ], [] }
41 | ]}
42 | ]}
43 | ]}.
44 |
45 | add new pools.
46 | {env, [
47 | {global_or_local, local},
48 | {pools, [
49 | {default, [
50 | {size, 10},
51 | {max_overflow, 20}
52 | ], []},
53 | {pool1, [
54 | {size, 30},
55 | {max_overflow, 20}
56 | ], [
57 | {host, "127.0.0.1"},
58 | {port, 6379}
59 | ]},
60 | {pool2, [
61 | {size, 20},
62 | {max_overflow, 20}
63 | ], [
64 | {host, "127.0.0.1"},
65 | {port, 6379},
66 | {database, "user_db"},
67 | {password, "abc"},
68 | {reconnect_sleep, 100}
69 | ]}
70 | ]}
71 | ]}
72 |
73 |
74 | ==Examples
75 |
76 | application start.
77 | eredis_pool:start().
78 | ok
79 |
80 | key-value set and get
81 | eredis_pool:q({global, dbsrv}, ["SET", "foo", "bar"]).
82 | {ok,<<"OK">>}
83 |
84 | eredis_pool:q({global, dbsrv}, ["GET", "foo"]).
85 | {ok,<<"bar">>}
86 |
87 | Redis Pipeline
88 | Pipeline = [["SET", a, "1"],
89 | ["LPUSH", b, "3"],
90 | ["LPUSH", b, "2"]].
91 | eredis_pool:qp({global,dbsrv}, Pipeline).
92 |
93 | create new pool with default settings.
94 | eredis_pool:create_pool(pool1, 10).
95 | {ok,<0.64.0>}
96 |
97 | and omissible argments(host, port, database, password reconnect_sleep).
98 | eredis_pool:create_pool(pool1, 10, "127.0.0.1", 6379, 1, "abc", 100).
99 | {ok,<0.64.0>}
100 |
101 | using new pool
102 | eredis_pool:q(pool1, ["GET", "foo"]).
103 | {ok,<<"bar">>}
104 |
105 | delete pool
106 | eredis_pool:delete_pool(pool1).
107 | ok
108 |
109 |
110 |
111 | Other commands is here.
112 | http://redis.io/commands
113 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | #The eredis_pool application#
4 |
5 |
6 | ##Modules##
7 |
8 |
9 |
13 |
14 |
--------------------------------------------------------------------------------
/doc/edoc-info:
--------------------------------------------------------------------------------
1 | {application,eredis_pool}.
2 | {packages,[]}.
3 | {modules,[eredis_pool,eredis_pool_app,eredis_pool_sup]}.
4 |
--------------------------------------------------------------------------------
/doc/eredis_pool.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | #Module eredis_pool#
4 | * [Description](#description)
5 | * [Function Index](#index)
6 | * [Function Details](#functions)
7 |
8 |
9 | .
10 |
11 | Copyright (c) (C) 2011, Hiroe Shin
12 |
13 | __Authors:__ Hiroe Shin ([`shin@mac-hiroe-orz-17.local`](mailto:shin@mac-hiroe-orz-17.local)).
14 |
15 | ##Function Index##
16 |
17 |
18 |
20 |
21 |
22 |
23 |
24 | ##Function Details##
25 |
26 |
27 |
28 | ###create_pool/2##
29 |
30 |
31 | create_pool(PoolName::atom(), Size::integer()) -> {ok, pid()} | {error, {already_started, pid()}}
32 |
33 |
34 |
35 | create new pool.
36 |
37 | ###create_pool/3##
38 |
39 |
40 | create_pool(PoolName::atom(), Size::integer(), Host::string()) -> {ok, pid()} | {error, {already_started, pid()}}
41 |
42 |
43 |
44 |
45 |
46 | ###create_pool/4##
47 |
48 |
49 | create_pool(PoolName::atom(), Size::integer(), Host::string(), Port::integer()) -> {ok, pid()} | {error, {already_started, pid()}}
50 |
51 |
52 |
53 |
54 |
55 | ###create_pool/5##
56 |
57 |
58 | create_pool(PoolName::atom(), Size::integer(), Host::string(), Port::integer(), Database::string()) -> {ok, pid()} | {error, {already_started, pid()}}
59 |
60 |
61 |
62 |
63 |
64 | ###create_pool/6##
65 |
66 |
67 | create_pool(PoolName::atom(), Size::integer(), Host::string(), Port::integer(), Database::string(), Password::string()) -> {ok, pid()} | {error, {already_started, pid()}}
68 |
69 |
70 |
71 |
72 |
73 | ###create_pool/7##
74 |
75 |
76 | create_pool(PoolName::atom(), Size::integer(), Host::string(), Port::integer(), Database::string(), Password::string(), ReconnectSleep::integer()) -> {ok, pid()} | {error, {already_started, pid()}}
77 |
78 |
79 |
80 |
81 |
82 | ###delete_pool/1##
83 |
84 |
85 | delete_pool(PoolName::atom()) -> ok | {error, not_found}
86 |
87 |
88 |
89 | delet pool and disconnected to Redis.
90 |
91 | ###q/2##
92 |
93 |
94 | q(PoolName::atom(), Command::iolist()) -> {ok, binary() | [binary()]} | {error, Reason::binary()}
95 |
96 |
97 |
98 |
99 | Executes the given command in the specified connection. The
100 | command must be a valid Redis command and may contain arbitrary
101 | data which will be converted to binaries. The returned values will
102 | always be binaries.
103 |
104 | ###q/3##
105 |
106 |
107 | q(PoolName::atom(), Command::iolist(), Timeout::integer()) -> {ok, binary() | [binary()]} | {error, Reason::binary()}
108 |
109 |
110 |
111 |
112 |
113 | ###start/0##
114 |
115 |
116 | `start() -> any()`
117 |
118 |
119 |
120 | ###stop/0##
121 |
122 |
123 | `stop() -> any()`
124 |
125 |
126 |
127 | ###transaction/2##
128 |
129 |
130 | `transaction(PoolName, Fun) -> any()`
131 |
132 |
--------------------------------------------------------------------------------
/doc/eredis_pool_app.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | #Module eredis_pool_app#
4 | * [Function Index](#index)
5 | * [Function Details](#functions)
6 |
7 |
8 | __Behaviours:__ [`application`](application.md).
9 |
10 | ##Function Index##
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ##Function Details##
19 |
20 |
21 |
22 | ###start/2##
23 |
24 |
25 | `start(StartType, StartArgs) -> any()`
26 |
27 |
28 |
29 | ###stop/1##
30 |
31 |
32 | `stop(State) -> any()`
33 |
34 |
--------------------------------------------------------------------------------
/doc/eredis_pool_sup.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | #Module eredis_pool_sup#
4 | * [Function Index](#index)
5 | * [Function Details](#functions)
6 |
7 |
8 | __Behaviours:__ [`supervisor`](supervisor.md).
9 |
10 | ##Function Index##
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ##Function Details##
19 |
20 |
21 |
22 | ###create_pool/3##
23 |
24 |
25 | create_pool(PoolName::atom(), Size::integer(), Options::[tuple()]) -> {ok, pid()} | {error, {already_started, pid()}}
26 |
27 |
28 |
29 | create new pool.
30 |
31 | ###delete_pool/1##
32 |
33 |
34 | delete_pool(PoolName::atom()) -> ok | {error, not_found}
35 |
36 |
37 |
38 | delet pool and disconnected to Redis.
39 |
40 | ###init/1##
41 |
42 |
43 | `init(X1) -> any()`
44 |
45 |
46 |
47 | ###start_link/0##
48 |
49 |
50 | `start_link() -> any()`
51 |
52 |
53 |
54 | ###start_link/2##
55 |
56 |
57 | `start_link(Pools, GlobalOrLocal) -> any()`
58 |
59 |
--------------------------------------------------------------------------------
/doc/erlang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiroeorz/eredis_pool/bc37bcf72afd1e5c69635fadba020ee2a73087d1/doc/erlang.png
--------------------------------------------------------------------------------
/doc/stylesheet.css:
--------------------------------------------------------------------------------
1 | /* standard EDoc style sheet */
2 | body {
3 | font-family: Verdana, Arial, Helvetica, sans-serif;
4 | margin-left: .25in;
5 | margin-right: .2in;
6 | margin-top: 0.2in;
7 | margin-bottom: 0.2in;
8 | color: #000000;
9 | background-color: #ffffff;
10 | }
11 | h1,h2 {
12 | margin-left: -0.2in;
13 | }
14 | div.navbar {
15 | background-color: #add8e6;
16 | padding: 0.2em;
17 | }
18 | h2.indextitle {
19 | padding: 0.4em;
20 | background-color: #add8e6;
21 | }
22 | h3.function,h3.typedecl {
23 | background-color: #add8e6;
24 | padding-left: 1em;
25 | }
26 | div.spec {
27 | margin-left: 2em;
28 | background-color: #eeeeee;
29 | }
30 | a.module,a.package {
31 | text-decoration:none
32 | }
33 | a.module:hover,a.package:hover {
34 | background-color: #eeeeee;
35 | }
36 | ul.definitions {
37 | list-style-type: none;
38 | }
39 | ul.index {
40 | list-style-type: none;
41 | background-color: #eeeeee;
42 | }
43 |
44 | /*
45 | * Minor style tweaks
46 | */
47 | ul {
48 | list-style-type: square;
49 | }
50 | table {
51 | border-collapse: collapse;
52 | }
53 | td {
54 | padding: 3
55 | }
56 |
--------------------------------------------------------------------------------
/rebar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiroeorz/eredis_pool/bc37bcf72afd1e5c69635fadba020ee2a73087d1/rebar
--------------------------------------------------------------------------------
/rebar.config:
--------------------------------------------------------------------------------
1 | %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
2 | %% ex: ts=4 sw=4 ft=erlang et
3 |
4 | {erl_opts, [warnings_as_errors,
5 | warn_export_all]}.
6 |
7 | {xref_checks, [undefined_function_calls]}.
8 | {cover_enabled, true}.
9 |
10 | {edoc_opts, [{doclet, edown_doclet},
11 | {dialyzer_specs, all},
12 | {report_missing_type, true},
13 | {report_type_mismatch, true},
14 | {pretty_print, erl_pp},
15 | {preprocess, true}]}.
16 |
17 | {deps, [
18 | {eredis,
19 | "1.*",
20 | {git, "https://github.com/wooga/eredis.git",
21 | {tag, "v1.0.8"}}},
22 |
23 | {poolboy,
24 | "1.5.*",
25 | {git, "https://github.com/devinus/poolboy.git",
26 | {tag, "1.5.1"}}}
27 | ]}.
28 |
--------------------------------------------------------------------------------
/src/eredis_pool.app.src:
--------------------------------------------------------------------------------
1 | {application, eredis_pool,
2 | [
3 | {description, ""},
4 | {vsn, "1.1"},
5 | {registered, []},
6 | {applications, [
7 | kernel,
8 | stdlib
9 | ]},
10 | {mod, { eredis_pool_app, []}},
11 | {env, []}
12 |
13 | %% sample configuration.
14 | %%
15 | %% {env, [
16 | %% {pools, [
17 | %% {dbsrv, [
18 | %% {size, 10},
19 | %% {max_overflow, 30}
20 | %% ]}
21 | %% ]}
22 | %% ]}
23 | %%
24 |
25 | ]}.
26 |
--------------------------------------------------------------------------------
/src/eredis_pool.erl:
--------------------------------------------------------------------------------
1 | %%%-------------------------------------------------------------------
2 | %%% @author Hiroe Shin
3 | %%% @copyright (C) 2011, Hiroe Shin
4 | %%% @doc
5 | %%%
6 | %%% @end
7 | %%% Created : 9 Oct 2011 by Hiroe Shin
8 | %%%-------------------------------------------------------------------
9 | -module(eredis_pool).
10 |
11 | %% Include
12 | -include_lib("eunit/include/eunit.hrl").
13 |
14 | %% Default timeout for calls to the client gen_server
15 | %% Specified in http://www.erlang.org/doc/man/gen_server.html#call-3
16 | -define(TIMEOUT, 5000).
17 |
18 | %% API
19 | -export([start/0, stop/0]).
20 | -export([q/2, q/3, qp/2, qp/3, transaction/2,
21 | create_pool/2, create_pool/3, create_pool/4, create_pool/5,
22 | create_pool/6, create_pool/7,
23 | delete_pool/1]).
24 |
25 | %%%===================================================================
26 | %%% API functions
27 | %%%===================================================================
28 |
29 | start() ->
30 | application:start(?MODULE).
31 |
32 | stop() ->
33 | application:stop(?MODULE).
34 |
35 | %% ===================================================================
36 | %% @doc create new pool.
37 | %% @end
38 | %% ===================================================================
39 | -spec(create_pool(PoolName::atom(), Size::integer()) ->
40 | {ok, pid()} | {error,{already_started, pid()}}).
41 |
42 | create_pool(PoolName, Size) ->
43 | eredis_pool_sup:create_pool(PoolName, Size, []).
44 |
45 | -spec(create_pool(PoolName::atom(), Size::integer(), Host::string()) ->
46 | {ok, pid()} | {error,{already_started, pid()}}).
47 |
48 | create_pool(PoolName, Size, Host) ->
49 | eredis_pool_sup:create_pool(PoolName, Size, [{host, Host}]).
50 |
51 | -spec(create_pool(PoolName::atom(), Size::integer(),
52 | Host::string(), Port::integer()) ->
53 | {ok, pid()} | {error,{already_started, pid()}}).
54 |
55 | create_pool(PoolName, Size, Host, Port) ->
56 | eredis_pool_sup:create_pool(PoolName, Size, [{host, Host}, {port, Port}]).
57 |
58 | -spec(create_pool(PoolName::atom(), Size::integer(),
59 | Host::string(), Port::integer(), Database::string()) ->
60 | {ok, pid()} | {error,{already_started, pid()}}).
61 |
62 | create_pool(PoolName, Size, Host, Port, Database) ->
63 | eredis_pool_sup:create_pool(PoolName, Size, [{host, Host}, {port, Port},
64 | {database, Database}]).
65 |
66 | -spec(create_pool(PoolName::atom(), Size::integer(),
67 | Host::string(), Port::integer(),
68 | Database::string(), Password::string()) ->
69 | {ok, pid()} | {error,{already_started, pid()}}).
70 |
71 | create_pool(PoolName, Size, Host, Port, Database, Password) ->
72 | eredis_pool_sup:create_pool(PoolName, Size, [{host, Host}, {port, Port},
73 | {database, Database},
74 | {password, Password}]).
75 |
76 | -spec(create_pool(PoolName::atom(), Size::integer(),
77 | Host::string(), Port::integer(),
78 | Database::string(), Password::string(),
79 | ReconnectSleep::integer()) ->
80 | {ok, pid()} | {error,{already_started, pid()}}).
81 |
82 | create_pool(PoolName, Size, Host, Port, Database, Password, ReconnectSleep) ->
83 | eredis_pool_sup:create_pool(PoolName, Size, [{host, Host}, {port, Port},
84 | {database, Database},
85 | {password, Password},
86 | {reconnect_sleep, ReconnectSleep}]).
87 |
88 |
89 | %% ===================================================================
90 | %% @doc delet pool and disconnected to Redis.
91 | %% @end
92 | %% ===================================================================
93 | -spec(delete_pool(PoolName::atom()) -> ok | {error,not_found}).
94 |
95 | delete_pool(PoolName) ->
96 | eredis_pool_sup:delete_pool(PoolName).
97 |
98 | %%--------------------------------------------------------------------
99 | %% @doc
100 | %% Executes the given command in the specified connection. The
101 | %% command must be a valid Redis command and may contain arbitrary
102 | %% data which will be converted to binaries. The returned values will
103 | %% always be binaries.
104 | %% @end
105 | %%--------------------------------------------------------------------
106 | -spec q(PoolName::atom(), Command::iolist()) ->
107 | {ok, binary() | [binary()]} | {error, Reason::binary()}.
108 |
109 | q(PoolName, Command) ->
110 | q(PoolName, Command, ?TIMEOUT).
111 |
112 | -spec q(PoolName::atom(), Command::iolist(), Timeout::integer()) ->
113 | {ok, binary() | [binary()]} | {error, Reason::binary()}.
114 |
115 | q(PoolName, Command, Timeout) ->
116 | poolboy:transaction(PoolName, fun(Worker) ->
117 | eredis:q(Worker, Command, Timeout)
118 | end).
119 |
120 | -spec qp(PoolName::atom(), Command::iolist(), Timeout::integer()) ->
121 | {ok, binary() | [binary()]} | {error, Reason::binary()}.
122 |
123 | qp(PoolName, Pipeline) ->
124 | qp(PoolName, Pipeline, ?TIMEOUT).
125 |
126 | qp(PoolName, Pipeline, Timeout) ->
127 | poolboy:transaction(PoolName, fun(Worker) ->
128 | eredis:qp(Worker, Pipeline, Timeout)
129 | end).
130 |
131 |
132 | transaction(PoolName, Fun) when is_function(Fun) ->
133 | F = fun(C) ->
134 | try
135 | {ok, <<"OK">>} = eredis:q(C, ["MULTI"]),
136 | Fun(C),
137 | eredis:q(C, ["EXEC"])
138 | catch Klass:Reason ->
139 | {ok, <<"OK">>} = eredis:q(C, ["DISCARD"]),
140 | io:format("Error in redis transaction. ~p:~p",
141 | [Klass, Reason]),
142 | {Klass, Reason}
143 | end
144 | end,
145 |
146 | poolboy:transaction(PoolName, F).
147 |
--------------------------------------------------------------------------------
/src/eredis_pool_app.erl:
--------------------------------------------------------------------------------
1 | -module(eredis_pool_app).
2 |
3 | -behaviour(application).
4 |
5 | %% Application callbacks
6 | -export([start/2, stop/1]).
7 |
8 | %% ===================================================================
9 | %% Application callbacks
10 | %% ===================================================================
11 |
12 | start(_StartType, _StartArgs) ->
13 | eredis_pool_sup:start_link().
14 |
15 | stop(_State) ->
16 | ok.
17 |
--------------------------------------------------------------------------------
/src/eredis_pool_sup.erl:
--------------------------------------------------------------------------------
1 | -module(eredis_pool_sup).
2 |
3 | -behaviour(supervisor).
4 |
5 | %% Include
6 | -include_lib("eunit/include/eunit.hrl").
7 |
8 | %% API
9 | -export([start_link/0, start_link/2]).
10 | -export([create_pool/3, delete_pool/1]).
11 |
12 | %% Supervisor callbacks
13 | -export([init/1]).
14 |
15 | %% Helper macro for declaring children of supervisor
16 | -define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
17 |
18 | %% ===================================================================
19 | %% API functions
20 | %% ===================================================================
21 |
22 | start_link() ->
23 | {ok, Pools} = application:get_env(eredis_pool, pools),
24 | {ok, GlobalOrLocal} = application:get_env(eredis_pool, global_or_local),
25 | start_link(Pools, GlobalOrLocal).
26 |
27 | start_link(Pools, GlobalOrLocal) ->
28 | supervisor:start_link({local, ?MODULE}, ?MODULE, [Pools, GlobalOrLocal]).
29 |
30 | %% ===================================================================
31 | %% @doc create new pool.
32 | %% @end
33 | %% ===================================================================
34 | -spec(create_pool(PoolName::atom(), Size::integer(), Options::[tuple()]) ->
35 | {ok, pid()} | {error,{already_started, pid()}}).
36 |
37 | create_pool(PoolName, Size, Options) ->
38 | create_pool(local, PoolName, Size, Options).
39 |
40 | %% ===================================================================
41 | %% @doc create new pool, selectable name zone global or local.
42 | %% @end
43 | %% ===================================================================
44 | -spec(create_pool(GlobalOrLocal::atom(), PoolName::atom(), Size::integer(), Options::[tuple()]) ->
45 | {ok, pid()} | {error,{already_started, pid()}}).
46 |
47 | create_pool(GlobalOrLocal, PoolName, Size, Options)
48 | when GlobalOrLocal =:= local;
49 | GlobalOrLocal =:= global ->
50 |
51 | SizeArgs = [{size, Size}, {max_overflow, 10}],
52 | PoolArgs = [{name, {GlobalOrLocal, PoolName}}, {worker_module, eredis}],
53 | PoolSpec = poolboy:child_spec(PoolName, PoolArgs ++ SizeArgs, Options),
54 |
55 | supervisor:start_child(?MODULE, PoolSpec).
56 |
57 | %% ===================================================================
58 | %% @doc delet pool and disconnected to Redis.
59 | %% @end
60 | %% ===================================================================
61 | -spec(delete_pool(PoolName::atom()) -> ok | {error,not_found}).
62 |
63 | delete_pool(PoolName) ->
64 | supervisor:terminate_child(?MODULE, PoolName),
65 | supervisor:delete_child(?MODULE, PoolName).
66 |
67 | %% ===================================================================
68 | %% Supervisor callbacks
69 | %% ===================================================================
70 |
71 | init([Pools, GlobalOrLocal]) ->
72 | RestartStrategy = one_for_one,
73 | MaxRestarts = 10,
74 | MaxSecondsBetweenRestarts = 10,
75 |
76 | SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
77 |
78 | PoolSpecs = lists:map(fun({Name, SizeArgs, WorkerArgs}) ->
79 | PoolArgs = [{name, {GlobalOrLocal, Name}},
80 | {worker_module, eredis}] ++ SizeArgs,
81 | poolboy:child_spec(Name, PoolArgs, WorkerArgs)
82 | end, Pools),
83 |
84 | {ok, {SupFlags, PoolSpecs}}.
85 |
--------------------------------------------------------------------------------
/test.config:
--------------------------------------------------------------------------------
1 | %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
2 | %% ex: ts=4 sw=4 ft=erlang et
3 |
4 | [{eredis_pool,
5 | [
6 | {global_or_local, local},
7 | {pools, [{dbsrv, [
8 | {size, 10},
9 | {max_overflow, 30}
10 | ],[] }
11 | ]}
12 |
13 | ]
14 | }].
15 |
--------------------------------------------------------------------------------
/test/eredis_pool_tests.erl:
--------------------------------------------------------------------------------
1 | -module(eredis_pool_tests).
2 |
3 | -include_lib("eunit/include/eunit.hrl").
4 |
5 | -import(eredis, [create_multibulk/1]).
6 |
7 | -define(Setup, fun() -> application:start(eredis_pool) end).
8 | -define(Clearnup, fun(_) -> application:stop(eredis_pool) end).
9 | -define(DEFAULT, dbsrv).
10 |
11 | transaction_test_() ->
12 | {inparallel,
13 | {setup, ?Setup, ?Clearnup,
14 | [
15 |
16 | { "transaction",
17 | fun() ->
18 | eredis_pool:q(?DEFAULT, ["DEL", queue1, bar]),
19 | eredis_pool:q(?DEFAULT, ["DEL", queue2, bar]),
20 |
21 | {ok, _} =
22 | eredis_pool:q(?DEFAULT, ["RPUSH", queue1, bar]),
23 |
24 | Fun =
25 | fun(C) ->
26 | {ok, <<"QUEUED">>} = eredis:q(C, ["LREM",
27 | queue1, 1,
28 | bar]),
29 |
30 | {ok, <<"QUEUED">>} = eredis:q(C, ["RPUSH",
31 | queue2,
32 | bar])
33 | end,
34 |
35 | {ok, [<<"1">>, <<"1">>]} =
36 | eredis_pool:transaction(?DEFAULT, Fun),
37 |
38 | ?assertEqual({ok, <<"0">>},
39 | eredis_pool:q(?DEFAULT, ["LLEN", queue1])),
40 | ?assertEqual({ok, <<"1">>},
41 | eredis_pool:q(?DEFAULT, ["LLEN", queue2]))
42 | end
43 | },
44 |
45 | { "rollback",
46 | fun() ->
47 | eredis_pool:q(?DEFAULT, ["DEL", queue3, bar]),
48 | eredis_pool:q(?DEFAULT, ["DEL", queue4, bar]),
49 |
50 | {ok, _} =
51 | eredis_pool:q(?DEFAULT, ["RPUSH", queue3, bar]),
52 |
53 | Fun =
54 | fun(C) ->
55 | {ok, <<"QUEUED">>} = eredis:q(C, ["LREM",
56 | queue3, 1,
57 | bar]),
58 | throw(normal)
59 | end,
60 |
61 | {throw, normal} = eredis_pool:transaction(?DEFAULT, Fun),
62 |
63 | ?assertEqual({ok, <<"1">>},
64 | eredis_pool:q(?DEFAULT, ["LLEN", queue3])),
65 | ?assertEqual({ok, <<"0">>},
66 | eredis_pool:q(?DEFAULT, ["LLEN", queue4]))
67 | end
68 | }
69 |
70 | ]
71 | }
72 | }.
73 |
74 | basic_test_() ->
75 | {inparallel,
76 |
77 | {setup, ?Setup, ?Clearnup,
78 | [
79 |
80 | { "get and set",
81 | fun() ->
82 | ?assertMatch({ok, _}, eredis_pool:q(?DEFAULT, ["DEL", foo1])),
83 |
84 | ?assertEqual({ok, undefined},
85 | eredis_pool:q(?DEFAULT, ["GET", foo1])),
86 |
87 | ?assertEqual({ok, <<"OK">>},
88 | eredis_pool:q(?DEFAULT, ["SET", foo1, bar])),
89 |
90 | ?assertEqual({ok, <<"bar">>},
91 | eredis_pool:q(?DEFAULT, ["GET", foo1]))
92 | end
93 | },
94 |
95 | { "delete test",
96 | fun() ->
97 | ?assertMatch({ok, _}, eredis_pool:q(?DEFAULT, ["DEL", foo2])),
98 |
99 | ?assertEqual({ok, <<"OK">>},
100 | eredis_pool:q(?DEFAULT, ["SET", foo2, bar])),
101 |
102 | ?assertEqual({ok, <<"1">>},
103 | eredis_pool:q(?DEFAULT, ["DEL", foo2])),
104 |
105 | ?assertEqual({ok, undefined},
106 | eredis_pool:q(?DEFAULT, ["GET", foo2]))
107 | end
108 | },
109 |
110 | { "mset and mget",
111 | fun() ->
112 | Keys = lists:seq(1, 1000),
113 |
114 | ?assertMatch({ok, _}, eredis_pool:q(?DEFAULT, ["DEL" | Keys])),
115 |
116 | KeyValuePairs = [[K, K*2] || K <- Keys],
117 | ExpectedResult =
118 | [list_to_binary(integer_to_list(K * 2)) || K <- Keys],
119 |
120 | ?assertEqual({ok, <<"OK">>},
121 | eredis_pool:q(?DEFAULT,
122 | ["MSET" | lists:flatten(KeyValuePairs)])),
123 |
124 | ?assertEqual({ok, ExpectedResult},
125 | eredis_pool:q(?DEFAULT, ["MGET" | Keys])),
126 |
127 | ?assertMatch({ok, _}, eredis_pool:q(?DEFAULT, ["DEL" | Keys]))
128 | end
129 | },
130 |
131 | { "new pool create and delete",
132 | fun() ->
133 | ?assertMatch({ok, _},
134 | eredis_pool:create_pool(pool1, 10)),
135 |
136 | ?assertMatch({ok, _}, eredis_pool:q(pool1, ["DEL", foo1])),
137 |
138 | ?assertEqual({ok, undefined},
139 | eredis_pool:q(pool1, ["GET", foo1])),
140 |
141 | ?assertEqual({ok, <<"OK">>},
142 | eredis_pool:q(pool1, ["SET", foo1, bar])),
143 |
144 | ?assertEqual({ok, <<"bar">>},
145 | eredis_pool:q(pool1, ["GET", foo1])),
146 |
147 | ?assertEqual(ok, eredis_pool:delete_pool(pool1))
148 | end
149 | }
150 |
151 | ]
152 | }
153 | }.
154 |
--------------------------------------------------------------------------------