Просмотр исходного кода

optimize open_connection and reconnect

Yuriy Zhloba 9 лет назад
Родитель
Сommit
06776975fb
4 измененных файлов с 31 добавлено и 73 удалено
  1. 6 18
      src/epgsql_pool_app.erl
  2. 9 8
      src/epgsql_pool_utils.erl
  3. 7 8
      src/epgsql_pool_worker.erl
  4. 9 39
      test/epgsql_pool_SUITE.erl

+ 6 - 18
src/epgsql_pool_app.erl

@@ -20,24 +20,12 @@ stop(_State) ->
 -spec test_run() -> ok.
 test_run() ->
     application:ensure_all_started(epgsql_pool),
-    Params = #epgsql_connection_params{host = "localhost", port = 5432, username = "test", password = "test", database = "testdb"},
+    Params = #epgsql_connection_params{host = "localhost",
+                                       port = 5432,
+                                       username = "test",
+                                       password = "invalidpass",
+                                       database = "testdb"},
     epgsql_pool_settings:set_connection_params(my_pool, Params),
-    {ok, _} = epgsql_pool:start(my_pool, 5, 10),
+    {ok, _} = epgsql_pool:start(my_pool, 1, 2),
 
-    Worker = pooler:take_member(my_pool, 1000) ,
-    {state, my_pool, #epgsql_connection{sock = Sock}} = sys:get_state(Worker),
-    error_logger:info_msg("Worker: ~p, sock: ~p", [Worker, Sock]),
-
-    {ok, _, R1} = epgsql_pool:equery(Worker, "select * from item"),
-    error_logger:info_msg("R1: ~p", [R1]),
-
-    error_logger:info_msg("close connection ~p", [Sock]),
-    exit(Sock, close_connection),
-
-    error_logger:info_msg("call second query"),
-    R2 = epgsql_pool:equery(Worker, "select * from item"),
-    error_logger:info_msg("R2: ~p", [R2]),
-
-    {state, my_pool, #epgsql_connection{sock = Sock2}} = sys:get_state(Worker),
-    error_logger:info_msg("Worker: ~p, sock: ~p", [Worker, Sock2]),
     ok.

+ 9 - 8
src/epgsql_pool_utils.erl

@@ -1,6 +1,6 @@
 -module(epgsql_pool_utils).
 
--export([open_connection/1,
+-export([open_connection/2,
          close_connection/1,
          reconnect/1,
          pool_name_to_atom/1
@@ -9,19 +9,20 @@
 -include("epgsql_pool.hrl").
 
 
--spec open_connection(#epgsql_connection_params{}) -> {ok, #epgsql_connection{}} | {error, term(), #epgsql_connection{}}.
-open_connection(#epgsql_connection_params{host = Host, port = Port,
-                                          username = Username,
-                                          password = Password,
-                                          database = Database} = ConnectionParams) ->
-    Connection0 = #epgsql_connection{params = ConnectionParams, reconnect_attempt = 0},
+-spec open_connection(atom(), #epgsql_connection{} | undefined) -> {ok, #epgsql_connection{}} | {error, term(), #epgsql_connection{}}.
+open_connection(PoolName, undefined) ->
+    open_connection(PoolName, #epgsql_connection{});
+open_connection(PoolName, Connection0) ->
+    Params = epgsql_pool_settings:get_connection_params(PoolName),
+    #epgsql_connection_params{host = Host, port = Port, username = Username,
+                              password = Password, database = Database} = Params,
     ConnectionTimeout = epgsql_pool_settings:get(connection_timeout),
     Res = epgsql:connect(Host, Username, Password,
                          [{port, Port},
                           {database, Database},
                           {timeout, ConnectionTimeout}]),
     case Res of
-        {ok, Sock} -> {ok, Connection0#epgsql_connection{sock = Sock}};
+        {ok, Sock} -> {ok, Connection0#epgsql_connection{sock = Sock, params = Params}};
         {error, Reason} -> {error, Reason, Connection0}
     end.
 

+ 7 - 8
src/epgsql_pool_worker.erl

@@ -60,14 +60,13 @@ handle_cast(Message, State) ->
 
 
 -spec handle_info(gs_request(), gs_state()) -> gs_info_reply().
-handle_info(open_connection, #state{pool_name = PoolName} = State) ->
-    ConnectionParams = epgsql_pool_settings:get_connection_params(PoolName),
-    case epgsql_pool_utils:open_connection(ConnectionParams) of
-        {ok, Connection} -> {noreply, State#state{connection = Connection}};
-        {error, Reason, Connection} ->
-            error_logger:error_msg("Pool ~p could not to connect to DB:~p", [PoolName, Reason]),
-            Connection2 = epgsql_pool_utils:reconnect(Connection),
-            {noreply, State#state{connection = Connection2}}
+handle_info(open_connection, #state{pool_name = PoolName, connection = Connection} = State) ->
+    case epgsql_pool_utils:open_connection(PoolName, Connection) of
+        {ok, Connection2} -> {noreply, State#state{connection = Connection2}};
+        {error, Reason, Connection3} ->
+            error_logger:error_msg("Pool:~p, Worker:~p could not to connect to DB:~p", [PoolName, self(), Reason]),
+            Connection4 = epgsql_pool_utils:reconnect(Connection3),
+            {noreply, State#state{connection = Connection4}}
     end;
 
 handle_info({'EXIT', Sock, Reason},

+ 9 - 39
test/epgsql_pool_SUITE.erl

@@ -10,15 +10,14 @@
 
 -export([all/0,
          init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2,
-         start_stop_test/1, equery_test/1, transaction_test/1, reconnect_test/1
+         equery_test/1, transaction_test/1, reconnect_test/1
         ]).
 
 -define(SELECT_ITEMS_QUERY, "SELECT id, category_id, title, num FROM item ORDER by id ASC").
 
 
 all() ->
-    [start_stop_test,
-     equery_test,
+    [equery_test,
      transaction_test,
      reconnect_test
     ].
@@ -36,34 +35,19 @@ end_per_suite(Config) ->
 
 init_per_testcase(_, Config) ->
     Params = #epgsql_connection_params{host = "localhost", port = 5432, username = "test", password = "test", database = "testdb"},
-    {ok, Connection} = epgsql_pool_utils:open_connection(Params),
-    #epgsql_connection{sock = Sock} = Connection,
-    epgsql:equery(Sock, "TRUNCATE TABLE item"),
-    epgsql:equery(Sock, "TRUNCATE TABLE category CASCADE"),
-    [{connection, Connection} | proplists:delete(connection, Config)].
+    epgsql_pool_settings:set_connection_params(my_pool, Params),
+    {ok, _} = epgsql_pool:start(my_pool, 5, 10),
+    epgsql_pool:equery(my_pool, "TRUNCATE TABLE item"),
+    epgsql_pool:equery(my_pool, "TRUNCATE TABLE category CASCADE"),
+    Config.
 
 
 end_per_testcase(_, Config) ->
-    Connection = proplists:get_value(connection, Config),
-    Connection2 = epgsql_pool_utils:close_connection(Connection),
-    #epgsql_connection{sock = undefined} = Connection2,
-    [{connection, Connection2} | proplists:delete(connection, Config)].
-
-
-start_stop_test(Config) ->
-    Params = #epgsql_connection_params{host = "localhost", port = 5432,
-                                       username="test", password="test",
-                                       database="testdb"},
-    epgsql_pool_settings:set_connection_params(my_pool, Params),
-    {ok, _} = epgsql_pool:start(my_pool, 5, 10),
     ok = epgsql_pool:stop(my_pool),
-    ok.
+    Config.
 
-equery_test(Config) ->
-    Connection = proplists:get_value(connection, Config),
-    epgsql_pool_settings:set_connection_params(my_pool, Connection#epgsql_connection.params),
-    {ok, _} = epgsql_pool:start(my_pool, 5, 10),
 
+equery_test(Config) ->
     {ok, 3, _, Ids} = epgsql_pool:equery(my_pool,
                                          "INSERT INTO category (title) "
                                          "VALUES ('cat 1'), ('cat 2'), ('cat 3') "
@@ -73,16 +57,10 @@ equery_test(Config) ->
     {ok, _, Rows} = epgsql_pool:equery(my_pool, "SELECT id, title FROM category ORDER by id ASC"),
     ct:pal("Rows ~p", [Rows]),
     ?assertEqual(WaitForRows, Rows),
-
-    ok = epgsql_pool:stop(my_pool),
     ok.
 
 
 transaction_test(Config) ->
-    Connection = proplists:get_value(connection, Config),
-    epgsql_pool_settings:set_connection_params(my_pool, Connection#epgsql_connection.params),
-    {ok, _} = epgsql_pool:start(my_pool, 5, 10),
-
     {FirstCatId, CatIds2, ItemIds2} =
         epgsql_pool:transaction(my_pool,
                                 fun(Worker) ->
@@ -137,16 +115,10 @@ transaction_test(Config) ->
 
     %% items not changes after calcelled transaction
     {ok, _, ItemRows} = epgsql_pool:equery(my_pool, ?SELECT_ITEMS_QUERY),
-
-    ok = epgsql_pool:stop(my_pool),
     ok.
 
 
 reconnect_test(Config) ->
-    Connection = proplists:get_value(connection, Config),
-    epgsql_pool_settings:set_connection_params(my_pool, Connection#epgsql_connection.params),
-    {ok, _} = epgsql_pool:start(my_pool, 5, 10),
-
     Worker = pooler:take_member(my_pool, 1000) ,
     {state, my_pool, #epgsql_connection{sock = Sock1}} = sys:get_state(Worker),
     ct:pal("Worker: ~p, sock: ~p", [Worker, Sock1]),
@@ -178,6 +150,4 @@ reconnect_test(Config) ->
     ct:pal("Worker: ~p, sock: ~p", [Worker, Sock2]),
 
     ?assertNotEqual(Sock1, Sock2),
-
-    ok = epgsql_pool:stop(my_pool),
     ok.