Expand retry handling on ratelimit response

We have seen middlewares that return ratelimit responses as 498 or 429,
so tolerate either.

Closes-Bug: #1879572
Change-Id: I027222157f6c2ad7882a0508302c9de097baae4c
This commit is contained in:
Clay Gerrard 2022-08-10 12:38:54 -05:00 committed by Tim Burke
parent a1d2f31131
commit 653cbcb686
2 changed files with 31 additions and 25 deletions
swiftclient
test/unit

@ -1833,7 +1833,7 @@ class Connection:
self.http_conn = None self.http_conn = None
elif 500 <= err.http_status <= 599: elif 500 <= err.http_status <= 599:
pass pass
elif self.retry_on_ratelimit and err.http_status == 498: elif self.retry_on_ratelimit and err.http_status in (498, 429):
pass pass
else: else:
raise raise

@ -2130,31 +2130,37 @@ class TestConnection(MockHttpTest):
pass pass
c.sleep = quick_sleep c.sleep = quick_sleep
# test retries def test_status_code(code):
conn = c.Connection('http://www.test.com/auth/v1.0', 'asdf', 'asdf', # test retries
retry_on_ratelimit=True) conn = c.Connection('http://www.test.com/auth/v1.0',
code_iter = [200] + [498] * (conn.retries + 1) 'asdf', 'asdf', retry_on_ratelimit=True)
auth_resp_headers = { code_iter = [200] + [code] * (conn.retries + 1)
'x-auth-token': 'asdf', auth_resp_headers = {
'x-storage-url': 'http://storage/v1/test', 'x-auth-token': 'asdf',
} 'x-storage-url': 'http://storage/v1/test',
c.http_connection = self.fake_http_connection( }
*code_iter, headers=auth_resp_headers) c.http_connection = self.fake_http_connection(
with self.assertRaises(c.ClientException) as exc_context: *code_iter, headers=auth_resp_headers)
conn.head_account() with self.assertRaises(c.ClientException) as exc_context:
self.assertIn('Account HEAD failed', str(exc_context.exception)) conn.head_account()
self.assertEqual(conn.attempts, conn.retries + 1) self.assertIn('Account HEAD failed', str(exc_context.exception))
self.assertEqual(code, exc_context.exception.http_status)
self.assertEqual(conn.attempts, conn.retries + 1)
# test default no-retry # test default no-retry
c.http_connection = self.fake_http_connection( c.http_connection = self.fake_http_connection(
200, 498, 200, code,
headers=auth_resp_headers) headers=auth_resp_headers)
conn = c.Connection('http://www.test.com/auth/v1.0', 'asdf', 'asdf', conn = c.Connection('http://www.test.com/auth/v1.0',
retry_on_ratelimit=False) 'asdf', 'asdf', retry_on_ratelimit=False)
with self.assertRaises(c.ClientException) as exc_context: with self.assertRaises(c.ClientException) as exc_context:
conn.head_account() conn.head_account()
self.assertIn('Account HEAD failed', str(exc_context.exception)) self.assertIn('Account HEAD failed', str(exc_context.exception))
self.assertEqual(conn.attempts, 1) self.assertEqual(code, exc_context.exception.http_status)
self.assertEqual(conn.attempts, 1)
test_status_code(498)
test_status_code(429)
def test_retry_with_socket_error(self): def test_retry_with_socket_error(self):
def quick_sleep(*args): def quick_sleep(*args):