Browse Source

Changed names on function to better reflect what they do. Also solved issue with mysql transaction not really working.
Added execute/3,4, child_spec/3 and with/2. There are multiple way using this project, check the readme. Fixes #2 #3 #4 #5

Raoul Hess 10 years ago
parent
commit
3df1072d1a
3 changed files with 131 additions and 25 deletions
  1. 71 25
      src/mysql_poolboy.erl
  2. 28 0
      src/mysql_poolboy_app.erl
  3. 32 0
      src/mysql_poolboy_sup.erl

+ 71 - 25
src/mysql_poolboy.erl

@@ -16,31 +16,49 @@
 %% You should have received a copy of the GNU Lesser General Public License
 %% along with this program. If not, see <https://www.gnu.org/licenses/>.
 
+%% @doc Only add_pool/3 needs mysql_poolboy_app started to be able to add
+%% pools to the supvervisor.
 -module(mysql_poolboy).
 
--export([add_pools/1, add_pool/1, checkout_connection/1, checkin_connection/2,
-         query/2, query/3, query/4, transaction/2, transaction/3]).
+-export([add_pool/3,
+         checkin/2, checkout/1,
+         child_spec/3,
+         execute/3, execute/4,
+         query/2, query/3, query/4,
+         transaction/2, transaction/3, transaction/4,
+         with/2]).
 
-%% @doc Creates pools from a list and returns a list of supervisor:child_spec().
-%%      If needed, each application should itself supervise these specifications.
-add_pools(Pools) ->
-    lists:map(fun (PoolData) -> add_pool(PoolData) end, Pools).
+%% @doc Adds a pool to the started mysql_poolboy application.
+add_pool(PoolName, PoolArgs, MysqlArgs) ->
+    PoolSpec = child_spec(PoolName, PoolArgs, MysqlArgs),
+    supervisor:add_child(mysql_poolboy_sup, PoolSpec).
 
-%% @doc Creates a pool with the given arguments and returns a supervisor:child_spec()
-%%      If needed, each application should itself supervise these specifications.
-add_pool({PoolName, PoolSizeArgs, MysqlArgs}) ->
-    PoolArgs = [{name, {local, PoolName}}, {worker_module, mysql}] ++ PoolSizeArgs,
-    poolboy:child_spec(PoolName, PoolArgs, MysqlArgs).
-
-%% Shorthand/convenience functions.
+%% @doc Returns a mysql connection to the given pool.
+checkin(PoolName, Connection) ->
+    poolboy:checkin(PoolName, Connection).
 
 %% @doc Checks out a mysql connection from a given pool.
-checkout_connection(PoolName) ->
+checkout(PoolName) ->
     poolboy:checkout(PoolName).
 
-%% @doc Returns a mysql connection to a pool when done with it.
-checkin_connection(PoolName, Connection) ->
-    poolboy:checkin(PoolName, Connection).
+%% @doc Creates a supvervisor:child_spec. When the need to
+%% supervise the pools in another way.
+child_spec(PoolName, PoolArgs, MysqlArgs) ->
+    PoolArgs1 =
+        [{name, {local, PoolName}}, {worker_module, mysql}] ++ PoolArgs,
+    poolboy:child_spec(PoolName, PoolArgs1, MysqlArgs).
+
+%% @doc Execute a mysql prepared statement with given params.
+execute(PoolName, StatementRef, Params) ->
+    poolboy:transaction(PoolName, fun(MysqlConn) ->
+        mysql:execute(MysqlConn, StatementRef, Params)
+    end).
+
+%% @doc Execute a mysql prepared statement with given params and timeout
+execute(PoolName, StatementRef, Params, Timeout) ->
+    poolboy:transaction(PoolName, fun(MysqlConn) ->
+        mysql:execute(MysqlConn, StatementRef, Params, Timeout)
+    end).
 
 %% @doc Executes a query to a mysql connection in a given pool.
 query(PoolName, Query) ->
@@ -48,26 +66,54 @@ query(PoolName, Query) ->
         mysql:query(MysqlConn, Query)
     end).
 
-%% @doc Executes a query to a mysql connection in a given pool.
+%% @doc Executes a query to a mysql connection in a given pool with either
+%% list of query parameters or a timeout value.
 query(PoolName, Query, ParamsOrTimeout) ->
     poolboy:transaction(PoolName, fun(MysqlConn) ->
         mysql:query(MysqlConn, Query, ParamsOrTimeout)
     end).
 
-%% @doc Executes a query to a mysql connection in a given pool.
+%% @doc Executes a query to a mysql connection in a given pool with both
+%% a list of query parameters and a timeout value.
 query(PoolName, Query, Params, Timeout) ->
     poolboy:transaction(PoolName, fun(MysqlConn) ->
         mysql:query(MysqlConn, Query, Params, Timeout)
     end).
 
-%% @doc Executes a transaction fun. A connection will be supplied by the pool.
-transaction(PoolName, TransactionFun) ->
+%% @doc Wrapper to poolboy:transaction/2. Since it is not a mysql transaction.
+%% Example instead of:
+%% Conn = mysql_poolboy:checkout(mypool),
+%% try
+%%     mysql:query(Conn, "SELECT...")
+%%  after
+%%     mysql_poolboy:checkin(mypool, Conn)
+%%  end.
+%%
+%% mysql_poolboy:with(mypool, fun (Conn) -> mysql:query(Conn, "SELECT...") end).
+with(PoolName, Fun) when is_function(Fun, 1) ->
+    poolboy:transaction(PoolName, Fun).
+
+%% @doc Executes a mysql transaction fun. The fun needs to take one argument
+%% which is the mysql connection.
+transaction(PoolName, TransactionFun) when is_function(TransactionFun, 1) ->
+    poolboy:transaction(PoolName, fun(MysqlConn) ->
+        mysql:transaction(MysqlConn, TransactionFun, [MysqlConn], infinity)
+    end).
+
+%% @doc Executes a transaction fun. Args list needs be the same length as
+%% TransactionFun arity - 1.
+transaction(PoolName, TransactionFun, Args)
+    when is_function(TransactionFun, length(Args) + 1) ->
     poolboy:transaction(PoolName, fun(MysqlConn) ->
-        mysql:transaction(MysqlConn, TransactionFun)
+        mysql:transaction(MysqlConn, TransactionFun, [MysqlConn | Args],
+                          infinity)
     end).
 
-%% @doc Executes a transaction fun. A connection will be supplied by the pool.
-transaction(PoolName, TransactionFun, Args) ->
+%% @doc Same as transaction/3 but with the number of retries the mysql
+%% transaction should try to execute.
+transaction(PoolName, TransactionFun, Args, Retries)
+    when is_function(TransactionFun, length(Args) + 1) ->
     poolboy:transaction(PoolName, fun(MysqlConn) ->
-        mysql:transaction(MysqlConn, TransactionFun, Args)
+        mysql:transaction(MysqlConn, TransactionFun, [MysqlConn | Args],
+                          Retries)
     end).

+ 28 - 0
src/mysql_poolboy_app.erl

@@ -0,0 +1,28 @@
+%% MySQL/OTP + Poolboy
+%% Copyright (C) 2015 Raoul Hess
+%%
+%% This file is part of MySQL/OTP + Poolboy.
+%%
+%% MySQL/OTP + Poolboy is free software: you can redistribute it and/or modify it under
+%% the terms of the GNU Lesser General Public License as published by the Free
+%% Software Foundation, either version 3 of the License, or (at your option)
+%% any later version.
+%%
+%% This program is distributed in the hope that it will be useful, but WITHOUT
+%% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+%% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+%% more details.
+%%
+%% You should have received a copy of the GNU Lesser General Public License
+%% along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+-module(mysql_pooboy_app).
+
+-behaviour(application).
+-export([start/2, stop/1]).
+
+start(_Type, _Args) ->
+    supervisor:start_link({local, mysql_poolboy_sup}, ?MODULE, []).
+
+stop(_State) ->
+    ok.

+ 32 - 0
src/mysql_poolboy_sup.erl

@@ -0,0 +1,32 @@
+%% MySQL/OTP + Poolboy
+%% Copyright (C) 2015 Raoul Hess
+%%
+%% This file is part of MySQL/OTP + Poolboy.
+%%
+%% MySQL/OTP + Poolboy is free software: you can redistribute it and/or modify it under
+%% the terms of the GNU Lesser General Public License as published by the Free
+%% Software Foundation, either version 3 of the License, or (at your option)
+%% any later version.
+%%
+%% This program is distributed in the hope that it will be useful, but WITHOUT
+%% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+%% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+%% more details.
+%%
+%% You should have received a copy of the GNU Lesser General Public License
+%% along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+-module(mysql_poolboy_sup).
+
+-behaviour(supervisor).
+-export([init/1]).
+
+init([]) ->
+    Pools = application:get_all_env(mysql_poolboy),
+    PoolSpec = lists:map(
+        fun ({PoolName, {PoolArgs, MysqlArgs}}) ->
+            mysqp_poolboy:child_spec(PoolName, PoolArgs, MysqlArgs)
+        end,
+        Pools
+    ),
+    {ok, {{one_for_one, 10, 10}, PoolSpec}}.