mysql_poolboy.erl 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. %% MySQL/OTP + Poolboy
  2. %% Copyright (C) 2014 Raoul Hess
  3. %%
  4. %% This file is part of MySQL/OTP + Poolboy.
  5. %%
  6. %% MySQL/OTP + Poolboy is free software: you can redistribute it and/or modify it under
  7. %% the terms of the GNU Lesser General Public License as published by the Free
  8. %% Software Foundation, either version 3 of the License, or (at your option)
  9. %% any later version.
  10. %%
  11. %% This program is distributed in the hope that it will be useful, but WITHOUT
  12. %% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. %% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  14. %% more details.
  15. %%
  16. %% You should have received a copy of the GNU Lesser General Public License
  17. %% along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. %% @doc Only add_pool/3 needs mysql_poolboy_app started to be able to add
  19. %% pools to the supvervisor.
  20. -module(mysql_poolboy).
  21. -export([add_pool/3,
  22. checkin/2, checkout/1,
  23. child_spec/3,
  24. execute/3, execute/4,
  25. query/2, query/3, query/4,
  26. transaction/2, transaction/3, transaction/4,
  27. with/2]).
  28. %% @doc Adds a pool to the started mysql_poolboy application.
  29. add_pool(PoolName, PoolArgs, MysqlArgs) ->
  30. %% We want strategy fifo as default instead of lifo.
  31. PoolSpec = child_spec(PoolName, PoolArgs, MysqlArgs),
  32. supervisor:start_child(mysql_poolboy_sup, PoolSpec).
  33. %% @doc Returns a mysql connection to the given pool.
  34. checkin(PoolName, Connection) ->
  35. poolboy:checkin(PoolName, Connection).
  36. %% @doc Checks out a mysql connection from a given pool.
  37. checkout(PoolName) ->
  38. poolboy:checkout(PoolName).
  39. %% @doc Creates a supvervisor:child_spec. When the need to
  40. %% supervise the pools in another way.
  41. child_spec(PoolName, PoolArgs, MysqlArgs) ->
  42. PoolArgs1 = case proplists:is_defined(strategy, PoolArgs) of
  43. true ->
  44. [{name, {local, PoolName}}, {worker_module, mysql} | PoolArgs];
  45. false ->
  46. %% Use fifo by default. MySQL closes unused connections after a certain time.
  47. %% Fifo causes all connections to be regularily used which prevents them from
  48. %% being closed.,
  49. [{strategy, fifo}, {name, {local, PoolName}}, {worker_module, mysql} | PoolArgs]
  50. end,
  51. poolboy:child_spec(PoolName, PoolArgs1, MysqlArgs).
  52. %% @doc Execute a mysql prepared statement with given params.
  53. execute(PoolName, StatementRef, Params) ->
  54. poolboy:transaction(PoolName, fun(MysqlConn) ->
  55. mysql:execute(MysqlConn, StatementRef, Params)
  56. end).
  57. %% @doc Execute a mysql prepared statement with given params and timeout
  58. execute(PoolName, StatementRef, Params, Timeout) ->
  59. poolboy:transaction(PoolName, fun(MysqlConn) ->
  60. mysql:execute(MysqlConn, StatementRef, Params, Timeout)
  61. end).
  62. %% @doc Executes a query to a mysql connection in a given pool.
  63. query(PoolName, Query) ->
  64. poolboy:transaction(PoolName, fun(MysqlConn) ->
  65. mysql:query(MysqlConn, Query)
  66. end).
  67. %% @doc Executes a query to a mysql connection in a given pool with either
  68. %% list of query parameters or a timeout value.
  69. query(PoolName, Query, ParamsOrTimeout) ->
  70. poolboy:transaction(PoolName, fun(MysqlConn) ->
  71. mysql:query(MysqlConn, Query, ParamsOrTimeout)
  72. end).
  73. %% @doc Executes a query to a mysql connection in a given pool with both
  74. %% a list of query parameters and a timeout value.
  75. query(PoolName, Query, Params, Timeout) ->
  76. poolboy:transaction(PoolName, fun(MysqlConn) ->
  77. mysql:query(MysqlConn, Query, Params, Timeout)
  78. end).
  79. %% @doc Wrapper to poolboy:transaction/2. Since it is not a mysql transaction.
  80. %% Example instead of:
  81. %% Conn = mysql_poolboy:checkout(mypool),
  82. %% try
  83. %% mysql:query(Conn, "SELECT...")
  84. %% after
  85. %% mysql_poolboy:checkin(mypool, Conn)
  86. %% end.
  87. %%
  88. %% mysql_poolboy:with(mypool, fun (Conn) -> mysql:query(Conn, "SELECT...") end).
  89. with(PoolName, Fun) when is_function(Fun, 1) ->
  90. poolboy:transaction(PoolName, Fun).
  91. %% @doc Executes a mysql transaction fun. The fun needs to take one argument
  92. %% which is the mysql connection.
  93. transaction(PoolName, TransactionFun) when is_function(TransactionFun, 1) ->
  94. poolboy:transaction(PoolName, fun(MysqlConn) ->
  95. mysql:transaction(MysqlConn, TransactionFun, [MysqlConn], infinity)
  96. end).
  97. %% @doc Executes a transaction fun. Args list needs be the same length as
  98. %% TransactionFun arity - 1.
  99. transaction(PoolName, TransactionFun, Args)
  100. when is_function(TransactionFun, length(Args) + 1) ->
  101. poolboy:transaction(PoolName, fun(MysqlConn) ->
  102. mysql:transaction(MysqlConn, TransactionFun, [MysqlConn | Args],
  103. infinity)
  104. end).
  105. %% @doc Same as transaction/3 but with the number of retries the mysql
  106. %% transaction should try to execute.
  107. transaction(PoolName, TransactionFun, Args, Retries)
  108. when is_function(TransactionFun, length(Args) + 1) ->
  109. poolboy:transaction(PoolName, fun(MysqlConn) ->
  110. mysql:transaction(MysqlConn, TransactionFun, [MysqlConn | Args],
  111. Retries)
  112. end).