diff --git a/aiohttp/connector.py b/aiohttp/connector.py index 5e47ce597ab..99f319824e6 100644 --- a/aiohttp/connector.py +++ b/aiohttp/connector.py @@ -161,15 +161,21 @@ def _cleanup(self): now = self._loop.time() connections = {} + timeout = self._keepalive_timeout + for key, conns in self._conns.items(): alive = [] for transport, proto, t0 in conns: if transport is not None: if proto and not proto.is_connected(): transport = None - elif (now - t0) > self._keepalive_timeout: - transport.close() - transport = None + else: + delta = t0 + self._keepalive_timeout - now + if delta < 0: + transport.close() + transport = None + elif delta < timeout: + timeout = delta if transport is not None: alive.append((transport, proto, t0)) @@ -178,7 +184,7 @@ def _cleanup(self): if connections: self._cleanup_handle = self._loop.call_at( - ceil(now + self._keepalive_timeout), self._cleanup) + ceil(now + timeout), self._cleanup) self._conns = connections diff --git a/tests/test_connector.py b/tests/test_connector.py index 7a6380d5507..061bbeafafa 100644 --- a/tests/test_connector.py +++ b/tests/test_connector.py @@ -417,7 +417,26 @@ def test_cleanup2(self): self.assertIsNotNone(conn._cleanup_handle) loop.call_at.assert_called_with( - 311, conn._cleanup) + 310, conn._cleanup) + conn.close() + + def test_cleanup3(self): + testset = {1: [(unittest.mock.Mock(), unittest.mock.Mock(), 290.1), + (unittest.mock.Mock(), unittest.mock.Mock(), 305.1)]} + testset[1][0][1].is_connected.return_value = True + + loop = unittest.mock.Mock() + loop.time.return_value = 308.5 + + conn = aiohttp.BaseConnector(loop=loop, keepalive_timeout=10) + conn._conns = testset + + conn._cleanup() + self.assertEqual(conn._conns, {1: [testset[1][1]]}) + + self.assertIsNotNone(conn._cleanup_handle) + loop.call_at.assert_called_with( + 316, conn._cleanup) conn.close() def test_tcp_connector_ctor(self):