Skip to content

Commit cbc29cc

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 merge an unusable connection is no longer valid. But before it was valid, so now it's just a NOP. Fixed #33
1 parent fdaac30 commit cbc29cc

File tree

2 files changed

+67
-46
lines changed

2 files changed

+67
-46
lines changed

mysql/init.lua

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ local function conn_get(pool, timeout)
5252
mysql_conn:close()
5353
pool.queue:put(POOL_EMPTY_SLOT)
5454
end)
55+
-- If the connection belongs to a connection pool, it must be returned to
56+
-- the pool when calling "close" without actually closing the connection.
57+
-- In the case of a double "close", the behavior is the same as with a
58+
-- simple connection.
59+
conn.close = function(self)
60+
if not self.usable then
61+
error('Connection is not usable')
62+
end
63+
pool:put(self)
64+
return true
65+
end
5566
return conn
5667
end
5768

@@ -209,8 +220,6 @@ end
209220
local function pool_put(self, conn)
210221
if conn.usable then
211222
self.queue:put(conn_put(conn))
212-
else
213-
self.queue:put(POOL_EMPTY_SLOT)
214223
end
215224
end
216225

test/mysql.test.lua

Lines changed: 56 additions & 44 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

@@ -322,13 +322,6 @@ local function test_connection_pool(test, pool)
322322

323323
-- Verify that the pool is full.
324324
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')
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,73 @@ 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(1)
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+
-- Put must be a NOP in this case.
406+
pool:put(conn)
407+
test:ok(pool.queue:is_full(), 'a connection was given back')
408+
end)
409+
410+
-- Case: close the same connection twice.
411+
test:test('close a connection twice', function(test)
412+
test:plan(2)
413+
414+
assert(pool.size >= 1, 'test case precondition fails')
415+
416+
local conn = pool:get()
417+
conn:close()
418+
test:ok(pool.queue:is_full(), 'a connection was given back')
419+
420+
local res = pcall(conn.close, conn)
421+
test:ok(not res, 'an error is thrown on double "close"')
425422
end)
426423

427-
--]]
424+
-- Case: put the same connection twice.
425+
test:test('put a connection twice', function(test)
426+
test:plan(2)
427+
428+
assert(pool.size >= 2, 'test case precondition fails')
429+
430+
local conn_1 = pool:get()
431+
local conn_2 = pool:get()
432+
pool:put(conn_1)
433+
pool:put(conn_1)
434+
test:ok(not pool.queue:is_full(),
435+
'the same connection has not been "put" twice')
436+
437+
pool:put(conn_2)
438+
test:ok(pool.queue:is_full(),
439+
'all connections were returned to the pool')
440+
end)
428441

429442
assert(pool.queue:is_full(), 'case group postcondition fails')
430443

@@ -437,7 +450,6 @@ test:plan(6)
437450
test:test('connection old api', test_old_api, conn)
438451
local pool_conn = p:get()
439452
test:test('connection old api via pool', test_old_api, pool_conn)
440-
p:put(pool_conn)
441453
test:test('garbage collection', test_gc, p)
442454
test:test('concurrent connections', test_conn_concurrent, p)
443455
test:test('int64', test_mysql_int64, p)

0 commit comments

Comments
 (0)