Fix a possible receive timeout
This patch fixes a possible receive timeout caused by a slow response from the driver agent. For example if the database is very slow. Closes-Bug: #2032890 Change-Id: I9079030a5fef9dc44da242adab3c568666777451
This commit is contained in:
parent
bad19004b0
commit
2a84a218ef
|
@ -58,11 +58,19 @@ class DriverLibrary():
|
||||||
|
|
||||||
def _recv(self, sock):
|
def _recv(self, sock):
|
||||||
size_str = b''
|
size_str = b''
|
||||||
char = sock.recv(1)
|
|
||||||
begin = time.time()
|
begin = time.time()
|
||||||
while char != b'\n':
|
while True:
|
||||||
size_str += char
|
try:
|
||||||
char = sock.recv(1)
|
char = sock.recv(1)
|
||||||
|
except socket.timeout:
|
||||||
|
# We could have an overloaded DB and the query may take too
|
||||||
|
# long, so as long as DRIVER_AGENT_TIMEOUT hasn't expired,
|
||||||
|
# let's keep trying while not blocking everything.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if char == b'\n':
|
||||||
|
break
|
||||||
|
size_str += char
|
||||||
if time.time() - begin > DRIVER_AGENT_TIMEOUT:
|
if time.time() - begin > DRIVER_AGENT_TIMEOUT:
|
||||||
raise driver_exceptions.DriverAgentTimeout(
|
raise driver_exceptions.DriverAgentTimeout(
|
||||||
fault_string=('The driver agent did not respond in {} '
|
fault_string=('The driver agent did not respond in {} '
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import socket
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from octavia_lib.api.drivers import driver_lib
|
from octavia_lib.api.drivers import driver_lib
|
||||||
|
@ -45,7 +46,7 @@ class TestDriverLib(base.TestCase):
|
||||||
@mock.patch('builtins.memoryview')
|
@mock.patch('builtins.memoryview')
|
||||||
def test_recv(self, mock_memoryview):
|
def test_recv(self, mock_memoryview):
|
||||||
mock_socket = mock.MagicMock()
|
mock_socket = mock.MagicMock()
|
||||||
mock_socket.recv.side_effect = [b'1', b'\n', b'2', b'\n', b'3', b'\n']
|
mock_socket.recv.side_effect = [b'1', b'\n', b'2', b'3', b'\n']
|
||||||
mock_socket.recv_into.return_value = 1
|
mock_socket.recv_into.return_value = 1
|
||||||
mv_mock = mock.MagicMock()
|
mv_mock = mock.MagicMock()
|
||||||
mock_memoryview.return_value = mv_mock
|
mock_memoryview.return_value = mv_mock
|
||||||
|
@ -71,6 +72,25 @@ class TestDriverLib(base.TestCase):
|
||||||
self.assertRaises(driver_exceptions.DriverAgentTimeout,
|
self.assertRaises(driver_exceptions.DriverAgentTimeout,
|
||||||
self.driver_lib._recv, mock_socket)
|
self.driver_lib._recv, mock_socket)
|
||||||
|
|
||||||
|
@mock.patch('builtins.memoryview')
|
||||||
|
def test_recv_with_timeout(self, mock_memoryview):
|
||||||
|
mock_socket = mock.MagicMock()
|
||||||
|
mock_socket.recv.side_effect = [socket.timeout, b'1', b'\n', b'2',
|
||||||
|
b'3', b'\n']
|
||||||
|
mock_socket.recv_into.return_value = 1
|
||||||
|
mv_mock = mock.MagicMock()
|
||||||
|
mock_memoryview.return_value = mv_mock
|
||||||
|
mv_mock.tobytes.return_value = b'"test data"'
|
||||||
|
|
||||||
|
response = self.driver_lib._recv(mock_socket)
|
||||||
|
|
||||||
|
calls = [mock.call(1), mock.call(1)]
|
||||||
|
|
||||||
|
mock_socket.recv.assert_has_calls(calls)
|
||||||
|
mock_socket.recv_into.assert_called_once_with(
|
||||||
|
mv_mock.__getitem__(), 1)
|
||||||
|
self.assertEqual('test data', response)
|
||||||
|
|
||||||
@mock.patch('octavia_lib.api.drivers.driver_lib.DriverLibrary._recv')
|
@mock.patch('octavia_lib.api.drivers.driver_lib.DriverLibrary._recv')
|
||||||
def test_send(self, mock_recv):
|
def test_send(self, mock_recv):
|
||||||
mock_socket = mock.MagicMock()
|
mock_socket = mock.MagicMock()
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixed a possible receive timeout if the driver agent didn't respond inside
|
||||||
|
five seconds. For example if you have a very slow database.
|
Loading…
Reference in New Issue