Skip to content

Commit fbe39b4

Browse files
committed
update connection management for connection pool
If the connection belongs to a connection pool, it must be returned to the pool when calling "close" without actually closing the connection. All connections will be closed when poll:close() will be called. The same behavior is used in JDBC connection pool. With this change, an attempt to "put" an unusable connection is no longer valid. Code that doesn't test anything has been removed from the tests. Fixed tarantool#33
1 parent abaad1e commit fbe39b4

File tree

2 files changed

+74
-49
lines changed

2 files changed

+74
-49
lines changed

mysql/init.lua

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ local conn_mt
99

1010
-- The marker for empty slots in a connection pool.
1111
--
12-
-- When a user puts a connection that is in an unusable state to a
13-
-- pool, we put this marker to a pool's internal connection queue.
14-
--
1512
-- Note: It should not be equal to `nil`, because fiber channel's
1613
-- `get` method returns `nil` when a timeout is reached.
1714
local POOL_EMPTY_SLOT = true
@@ -52,6 +49,17 @@ local function conn_get(pool, timeout)
5249
mysql_conn:close()
5350
pool.queue:put(POOL_EMPTY_SLOT)
5451
end)
52+
-- If the connection belongs to a connection pool, it must be returned to
53+
-- the pool when calling "close" without actually closing the connection.
54+
-- In the case of a double "close", the behavior is the same as with a
55+
-- simple connection.
56+
conn.close = function(self)
57+
if not self.usable then
58+
error('Connection is not usable')
59+
end
60+
pool:put(self)
61+
return true
62+
end
5563
return conn
5664
end
5765

@@ -217,7 +225,7 @@ local function pool_put(self, conn)
217225
if conn.usable then
218226
self.queue:put(conn_put(conn))
219227
else
220-
self.queue:put(POOL_EMPTY_SLOT)
228+
error('Connection is not usable')
221229
end
222230
end
223231

test/mysql.test.lua

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ local function test_mysql_int64(t, p)
171171
end
172172

173173
local function test_connection_pool(test, pool)
174-
test:plan(6)
174+
test:plan(11)
175175

176176
-- {{{ Case group: all connections are consumed initially.
177177

@@ -302,13 +302,13 @@ local function test_connection_pool(test, pool)
302302

303303
-- Put the connection back and verify that the pool is full.
304304
pool:put(conn)
305-
test:ok(pool.queue:is_full(), 'a broken connection was given back')
305+
test:ok(pool.queue:is_full(), 'a connection was given back')
306306
end)
307307

308308
-- Case: the same, but loss and collect a connection after
309309
-- put.
310310
test:test('get, put and loss a connection', function(test)
311-
test:plan(2)
311+
test:plan(1)
312312

313313
assert(pool.size >= 1, 'test case precondition fails')
314314

@@ -321,14 +321,7 @@ local function test_connection_pool(test, pool)
321321
collectgarbage('collect')
322322

323323
-- Verify that the pool is full.
324-
test:ok(pool.queue:is_full(), 'a broken connection was given back')
325-
326-
-- Verify the pool will not be populated by a connection's
327-
-- GC callback. Otherwise :put() will hang.
328-
local item = pool.queue:get()
329-
pool.queue:put(item)
330-
test:ok(true, 'GC callback does not put back a connection that was ' ..
331-
'put manually')
324+
test:ok(pool.queue:is_full(), 'a connection was given back')
332325
end)
333326

334327
-- Case: get a connection, broke it and put back.
@@ -350,7 +343,7 @@ local function test_connection_pool(test, pool)
350343
-- Case: the same, but loss and collect a connection after
351344
-- put.
352345
test:test('get, broke, put and loss a connection', function(test)
353-
test:plan(3)
346+
test:plan(2)
354347

355348
assert(pool.size >= 1, 'test case precondition fails')
356349

@@ -366,24 +359,10 @@ local function test_connection_pool(test, pool)
366359

367360
-- Verify that the pool is full
368361
test:ok(pool.queue:is_full(), 'a broken connection was given back')
369-
370-
-- Verify the pool will not be populated by a connection's
371-
-- GC callback. Otherwise :put() will hang.
372-
local item = pool.queue:get()
373-
pool.queue:put(item)
374-
test:ok(true, 'GC callback does not put back a connection that was ' ..
375-
'put manually')
376362
end)
377363

378-
--[[
379-
380-
-- It is unclear for now whether putting of closed connection
381-
-- should be allowed. The second case, where GC collects lost
382-
-- connection after :put(), does not work at the moment. See
383-
-- gh-33.
384-
385-
-- Case: get a connection, close it and put back.
386-
test:test('get, close and put a connection', function(test)
364+
-- Case: get a connection and close it.
365+
test:test('get and close a connection', function(test)
387366
test:plan(1)
388367

389368
assert(pool.size >= 1, 'test case precondition fails')
@@ -392,39 +371,78 @@ local function test_connection_pool(test, pool)
392371
local conn = pool:get()
393372
conn:close()
394373

395-
-- Put a connection back and verify that the pool is full.
396-
pool:put(conn)
397-
test:ok(pool.queue:is_full(), 'a broken connection was given back')
374+
test:ok(pool.queue:is_full(), 'a connection was given back')
398375
end)
399376

400377
-- Case: the same, but loss and collect a connection after
401-
-- put.
402-
test:test('get, close, put and loss a connection', function(test)
403-
test:plan(2)
378+
-- close.
379+
test:test('get, close and loss a connection', function(test)
380+
test:plan(1)
404381

405382
assert(pool.size >= 1, 'test case precondition fails')
406383

407384
-- Get a connection and close it.
408385
local conn = pool:get()
409386
conn:close()
410387

411-
-- Put the connection back, loss it and trigger GC.
412-
pool:put(conn)
413-
conn = nil
388+
conn = nil -- luacheck: no unused
414389
collectgarbage('collect')
415390

416391
-- Verify that the pool is full
417392
test:ok(pool.queue:is_full(), 'a broken connection was given back')
393+
end)
394+
395+
-- Case: get a connection, close and put it back.
396+
test:test('get, close and put a connection', function(test)
397+
test:plan(2)
418398

419-
-- Verify the pool will not be populated by a connection's
420-
-- GC callback. Otherwise :put() will hang.
421-
local item = pool.queue:get()
422-
pool.queue:put(item)
423-
test:ok(true, 'GC callback does not put back a connection that was ' ..
424-
'put manually')
399+
assert(pool.size >= 1, 'test case precondition fails')
400+
401+
-- Get a connection.
402+
local conn = pool:get()
403+
404+
conn:close()
405+
test:ok(pool.queue:is_full(), 'a connection was given back')
406+
407+
-- Put must throw an error.
408+
local res = pcall(pool.put, pool, conn)
409+
test:ok(not res, 'an error is thrown on "put" after "close"')
410+
end)
411+
412+
-- Case: close the same connection twice.
413+
test:test('close a connection twice', function(test)
414+
test:plan(2)
415+
416+
assert(pool.size >= 1, 'test case precondition fails')
417+
418+
local conn = pool:get()
419+
conn:close()
420+
test:ok(pool.queue:is_full(), 'a connection was given back')
421+
422+
local res = pcall(conn.close, conn)
423+
test:ok(not res, 'an error is thrown on double "close"')
425424
end)
426425

427-
--]]
426+
-- Case: put the same connection twice.
427+
test:test('put a connection twice', function(test)
428+
test:plan(3)
429+
430+
assert(pool.size >= 2, 'test case precondition fails')
431+
432+
local conn_1 = pool:get()
433+
local conn_2 = pool:get()
434+
pool:put(conn_1)
435+
436+
test:ok(not pool.queue:is_full(),
437+
'the same connection has not been "put" twice')
438+
439+
local res = pcall(pool.put, pool, conn_1)
440+
test:ok(not res, 'an error is thrown on double "put"')
441+
442+
pool:put(conn_2)
443+
test:ok(pool.queue:is_full(),
444+
'all connections were returned to the pool')
445+
end)
428446

429447
assert(pool.queue:is_full(), 'case group postcondition fails')
430448

@@ -469,7 +487,6 @@ test:plan(7)
469487
test:test('connection old api', test_old_api, conn)
470488
local pool_conn = p:get()
471489
test:test('connection old api via pool', test_old_api, pool_conn)
472-
p:put(pool_conn)
473490
test:test('garbage collection', test_gc, p)
474491
test:test('concurrent connections', test_conn_concurrent, p)
475492
test:test('int64', test_mysql_int64, p)

0 commit comments

Comments
 (0)