|
79 | 79 | num_failed_connecting :: non_neg_integer(), |
80 | 80 |
|
81 | 81 | reconnect_wait_time :: non_neg_integer(), |
| 82 | + min_connection_interval_ms :: non_neg_integer() | undefined, |
82 | 83 | worker_module :: atom(), |
83 | 84 | callback_info :: mfargs(), |
84 | | - pool :: term()}). |
| 85 | + pool :: term(), |
| 86 | + last_connection_attempt :: non_neg_integer()}). |
85 | 87 |
|
86 | 88 | -callback transaction(client(), atom(), [term()]) -> {error, term()} | {client(), {ok, any()}}. |
87 | 89 | -callback close(client(), Reason :: term()) -> _. |
@@ -190,7 +192,8 @@ init(Parent, ClusterName, Host, Port, PoolName, WrkModule) -> |
190 | 192 | reconnect_wait_time = ?RECONNECT_WAIT_TIME, |
191 | 193 | pool = PoolName, |
192 | 194 | callback_info = CallBackInfo, |
193 | | - worker_module = WrkModule}, |
| 195 | + worker_module = WrkModule, |
| 196 | + last_connection_attempt = 0}, |
194 | 197 | timer:send_interval(5000, reload_pool_min_max_settings), |
195 | 198 | pool_loop(schedule_expiration(reload_pool_min_max_settings(State)), Parent, Deb) |
196 | 199 | end. |
@@ -250,7 +253,9 @@ pool_loop(State, Parent, Deb) -> |
250 | 253 | State#pool_st.host, |
251 | 254 | State#pool_st.port, |
252 | 255 | State#pool_st.callback_info), |
253 | | - ?MODULE:pool_loop(State, Parent, Deb) |
| 256 | + ?MODULE:pool_loop(State#pool_st{ |
| 257 | + last_connection_attempt = erlang:system_time(millisecond)}, |
| 258 | + Parent, Deb) |
254 | 259 | end; |
255 | 260 | reload_pool_min_max_settings -> |
256 | 261 | ?MODULE:pool_loop(reload_pool_min_max_settings(State), Parent, Deb); |
@@ -289,43 +294,50 @@ get_connection(State, {Pid, Ref} = _From) -> |
289 | 294 |
|
290 | 295 |
|
291 | 296 | maybe_spawn_connect(#pool_st{ |
292 | | - cluster = ClusterName, |
293 | 297 | free = Free, |
| 298 | + num_connecting = Connecting, |
294 | 299 | num_connected = Connected, |
295 | 300 | max_connections = MaxConn, |
296 | | - min_connections = MinConn, |
297 | | - num_connecting = Connecting, |
298 | | - num_failed_connecting = NumFailed, |
299 | | - worker_module = WrkModule, |
300 | | - callback_info = CallbackInfo, |
301 | | - reconnect_wait_time = WaitTime, |
302 | | - pool = Pool, |
303 | | - host = Host, |
304 | | - port = Port} = State) -> |
| 301 | + min_connections = MinConn} = State) -> |
305 | 302 | %% Length could be big.. better to not have more than a few dozens of sockets |
306 | 303 | %% May be worth to keep track of the length of the free in a counter. |
307 | 304 |
|
308 | 305 | FreeSockets = length(Free), |
309 | | - Needed = calculate_needed(FreeSockets, Connected, Connecting, MaxConn, MinConn), |
310 | | - case {Needed, NumFailed, Connecting} of |
311 | | - %% Need sockets and no failed connections are reported.. |
312 | | - %% we create new ones |
313 | | - {Needed, NumFailed, _} when Needed > 0, NumFailed < 1 -> |
314 | | - spawn_connections(ClusterName, Pool, WrkModule, Host, Port, CallbackInfo, Needed), |
315 | | - State#pool_st{num_connecting = Connecting + Needed}; |
316 | | - |
317 | | - %% Wait before reconnection if more than one successive |
318 | | - %% connection attempt has failed. Don't open more than |
319 | | - %% one connection until an attempt has succeeded again. |
320 | | - {Needed, _, 0} when Needed > 0 -> |
321 | | - erlang:send_after(WaitTime, self(), connect), |
322 | | - State#pool_st{num_connecting = Connecting + 1}; |
323 | | - |
324 | | - %% We dont need sockets or we have failed connections |
325 | | - %% we wait before reconnecting. |
326 | | - {_, _, _} -> |
327 | | - State |
328 | | - end. |
| 306 | + Needed = max(0, calculate_needed(FreeSockets, Connected, Connecting, MaxConn, MinConn)), |
| 307 | + maybe_spawn_connect(State, Needed, erlang:system_time(millisecond)). |
| 308 | + |
| 309 | +%% Do not spawn new connections if |
| 310 | +%% - There is no need for new connection |
| 311 | +%% - There is minimum interval between connections, and that hasn't elapsed yet since the last |
| 312 | +%% connection |
| 313 | +%% - There are in-flight connection attempts |
| 314 | +maybe_spawn_connect(State = #pool_st{min_connection_interval_ms = Min, |
| 315 | + last_connection_attempt = Last, |
| 316 | + num_connecting = Connecting}, |
| 317 | + Needed, |
| 318 | + Now) when Min /= undefined, (Now - Last) < Min; |
| 319 | + Connecting > 0; |
| 320 | + Needed == 0-> |
| 321 | + State; |
| 322 | +maybe_spawn_connect(State = #pool_st{num_failed_connecting = NumFailed, |
| 323 | + reconnect_wait_time = WaitTime, |
| 324 | + num_connecting = Connecting}, _Needed, _Now) |
| 325 | + when NumFailed > 0 -> |
| 326 | + %% Wait before reconnection if more than one successive |
| 327 | + %% connection attempt has failed. Don't open more than |
| 328 | + %% one connection until an attempt has succeeded again. |
| 329 | + erlang:send_after(WaitTime, self(), connect), |
| 330 | + State#pool_st{num_connecting = Connecting + 1}; |
| 331 | +maybe_spawn_connect(State = #pool_st{num_connecting = Connecting, |
| 332 | + pool = Pool, |
| 333 | + worker_module = WrkModule, |
| 334 | + cluster = ClusterName, |
| 335 | + host = Host, |
| 336 | + port = Port, |
| 337 | + callback_info = CallbackInfo}, Needed, Now) -> |
| 338 | + spawn_connections(ClusterName, Pool, WrkModule, Host, Port, CallbackInfo, Needed), |
| 339 | + State#pool_st{num_connecting = Connecting + Needed, last_connection_attempt = Now}. |
| 340 | + |
329 | 341 |
|
330 | 342 | calculate_needed(FreeSockets, Connected, Connecting, MaxConn, MinConn) -> |
331 | 343 | TotalSockets = Connected + Connecting, |
@@ -503,7 +515,8 @@ filter_expired(#conn{updated = Updated} = Conn, {Now, TTL, ExpConns, ActConns}) |
503 | 515 | %% terminate by themselves (because of timeouts, errors, inactivity, etc) |
504 | 516 | reload_pool_min_max_settings(State = #pool_st{cluster = ClusterName}) -> |
505 | 517 | State#pool_st{min_connections = mero_conf:pool_min_free_connections(ClusterName), |
506 | | - max_connections = mero_conf:pool_max_connections(ClusterName)}. |
| 518 | + max_connections = mero_conf:pool_max_connections(ClusterName), |
| 519 | + min_connection_interval_ms = mero_conf:pool_min_connection_interval(ClusterName)}. |
507 | 520 |
|
508 | 521 | safe_send(PoolName, Cmd) -> |
509 | 522 | catch PoolName ! Cmd. |
|
0 commit comments