Fix: Add timeout for mysql driver

The issue with current one is we try to use blocking as timeout
provider.
That make the timeout setting in mysql bound with blocking.
And the lock can't served with scenario that when we don't need timeout
blocking but still timeout required.

Change-Id: I36c80f882a91cd1c63d5a3bc2d1d8cb50f6637c6
This commit is contained in:
ricolin 2023-07-06 23:01:35 +08:00
parent d5bf20cbcc
commit bed303e9b4
2 changed files with 17 additions and 5 deletions

View File

@ -37,7 +37,7 @@ class MySQLLock(locking.Lock):
self.acquired = False self.acquired = False
self._conn = MySQLDriver.get_connection(parsed_url, options, True) self._conn = MySQLDriver.get_connection(parsed_url, options, True)
def acquire(self, blocking=True, shared=False): def acquire(self, blocking=True, shared=False, timeout=0):
if shared: if shared:
raise tooz.NotImplemented raise tooz.NotImplemented
@ -58,14 +58,12 @@ class MySQLLock(locking.Lock):
raise _retry.TryAgain raise _retry.TryAgain
return False return False
_, timeout = utils.convert_blocking(blocking)
try: try:
if not self._conn.open: if not self._conn.open:
self._conn.connect() self._conn.connect()
cur = self._conn.cursor() cur = self._conn.cursor()
cur.execute( cur.execute(
("SELECT GET_LOCK(%s, " (f"SELECT GET_LOCK(%s, {timeout});"),
f"{timeout if timeout is not None else '0'});"),
self.name self.name
) )
# Can return NULL on error # Can return NULL on error

View File

@ -92,7 +92,21 @@ class TestMySQLDriver(testcase.TestCase):
c.start() c.start()
name = tests.get_random_uuid() name = tests.get_random_uuid()
blocking_value = 10.12 blocking_value = False
timeout = 10.1
lock = c.get_lock(name)
with mock.patch.object(lock, 'acquire', wraps=True, autospec=True) as \
mock_acquire:
with lock(blocking_value, timeout):
mock_acquire.assert_called_once_with(blocking_value, timeout)
@mock.patch("pymysql.Connect")
def test_parsing_blocking_settings(self, sql_mock):
c = self._create_coordinator("mysql://localhost:3306/test")
c.start()
name = tests.get_random_uuid()
blocking_value = True
lock = c.get_lock(name) lock = c.get_lock(name)
with mock.patch.object(lock, 'acquire', wraps=True, autospec=True) as \ with mock.patch.object(lock, 'acquire', wraps=True, autospec=True) as \
mock_acquire: mock_acquire: