Skip to content

Commit 17eb52b

Browse files
committed
Revert "[ECO-5305] fix: rest retry logic"
This reverts commit b09264d.
1 parent b09264d commit 17eb52b

File tree

3 files changed

+17
-120
lines changed

3 files changed

+17
-120
lines changed

ably/http/http.py

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,6 @@ async def make_request(self, method, path, version=None, headers=None, body=None
188188

189189
hosts = self.get_rest_hosts()
190190
for retry_count, host in enumerate(hosts):
191-
def should_stop_retrying():
192-
time_passed = time.time() - requested_at
193-
# if it's the last try or cumulative timeout is done, we stop retrying
194-
return retry_count == len(hosts) - 1 or time_passed > http_max_retry_duration
195-
196191
base_url = "%s://%s:%d" % (self.preferred_scheme,
197192
host,
198193
self.preferred_port)
@@ -209,22 +204,12 @@ def should_stop_retrying():
209204
try:
210205
response = await self.__client.send(request)
211206
except Exception as e:
212-
if should_stop_retrying():
207+
# if last try or cumulative timeout is done, throw exception up
208+
time_passed = time.time() - requested_at
209+
if retry_count == len(hosts) - 1 or time_passed > http_max_retry_duration:
213210
raise e
214211
else:
215-
# RSC15l4
216-
cloud_front_error = (response.headers.get('Server', '').lower() == 'cloudfront'
217-
and response.status_code >= 400)
218-
# RSC15l3
219-
retryable_server_error = response.status_code >= 500 and response.status_code <= 504
220-
# Resending requests that have failed for other failure conditions will not fix the problem
221-
# and will simply increase the load on other datacenters unnecessarily
222-
response_is_retryable = cloud_front_error or retryable_server_error
223-
224212
try:
225-
if response_is_retryable and not should_stop_retrying():
226-
continue
227-
228213
if raise_on_error:
229214
AblyException.raise_for_response(response)
230215

@@ -235,7 +220,12 @@ def should_stop_retrying():
235220

236221
return Response(response)
237222
except AblyException as e:
238-
if should_stop_retrying() or not response_is_retryable:
223+
if not e.is_server_error:
224+
raise e
225+
226+
# if last try or cumulative timeout is done, throw exception up
227+
time_passed = time.time() - requested_at
228+
if retry_count == len(hosts) - 1 or time_passed > http_max_retry_duration:
239229
raise e
240230

241231
async def delete(self, url, headers=None, skip_auth=False, timeout=None):

test/ably/rest/resthttp_test.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ async def test_no_retry_if_not_500_to_599_http_code(self):
151151

152152
await ably.close()
153153

154-
@respx.mock
155154
async def test_500_errors(self):
156155
"""
157156
Raise error if all the servers reply with a 5xx error.
@@ -160,13 +159,16 @@ async def test_500_errors(self):
160159

161160
ably = AblyRest(token="foo")
162161

163-
mock_request = respx.route().mock(return_value=httpx.Response(500, text="Internal Server Error"))
162+
def raise_ably_exception(*args, **kwargs):
163+
raise AblyException(message="", status_code=500, code=50000)
164164

165-
with pytest.raises(AblyException):
166-
await ably.http.make_request('GET', '/', skip_auth=True)
167-
168-
assert mock_request.call_count == 3
165+
with mock.patch('httpx.Request', wraps=httpx.Request):
166+
with mock.patch('ably.util.exceptions.AblyException.raise_for_response',
167+
side_effect=raise_ably_exception) as send_mock:
168+
with pytest.raises(AblyException):
169+
await ably.http.make_request('GET', '/', skip_auth=True)
169170

171+
assert send_mock.call_count == 3
170172
await ably.close()
171173

172174
def test_custom_http_timeouts(self):

test/ably/rest/restrequest_test.py

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -126,101 +126,6 @@ async def test_timeout(self):
126126
await ably.request('GET', '/time', version=Defaults.protocol_version)
127127
await ably.close()
128128

129-
# RSC15l3
130-
@dont_vary_protocol
131-
async def test_503_status_fallback(self):
132-
default_endpoint = 'https://sandbox-rest.ably.io/time'
133-
fallback_host = 'sandbox-a-fallback.ably-realtime.com'
134-
fallback_endpoint = f'https://{fallback_host}/time'
135-
ably = await TestApp.get_ably_rest(fallback_hosts=[fallback_host])
136-
with respx.mock:
137-
default_route = respx.get(default_endpoint)
138-
fallback_route = respx.get(fallback_endpoint)
139-
headers = {
140-
"Content-Type": "application/json"
141-
}
142-
default_route.return_value = httpx.Response(503, headers=headers)
143-
fallback_route.return_value = httpx.Response(200, headers=headers, text='[123]')
144-
result = await ably.request('GET', '/time', version=Defaults.protocol_version)
145-
assert default_route.called
146-
assert result.status_code == 200
147-
assert result.items[0] == 123
148-
await ably.close()
149-
150-
# RSC15l2
151-
@dont_vary_protocol
152-
async def test_httpx_timeout_fallback(self):
153-
default_endpoint = 'https://sandbox-rest.ably.io/time'
154-
fallback_host = 'sandbox-a-fallback.ably-realtime.com'
155-
fallback_endpoint = f'https://{fallback_host}/time'
156-
ably = await TestApp.get_ably_rest(fallback_hosts=[fallback_host])
157-
with respx.mock:
158-
default_route = respx.get(default_endpoint)
159-
fallback_route = respx.get(fallback_endpoint)
160-
headers = {
161-
"Content-Type": "application/json"
162-
}
163-
default_route.side_effect = httpx.ReadTimeout
164-
fallback_route.return_value = httpx.Response(200, headers=headers, text='[123]')
165-
result = await ably.request('GET', '/time', version=Defaults.protocol_version)
166-
assert default_route.called
167-
assert result.status_code == 200
168-
assert result.items[0] == 123
169-
await ably.close()
170-
171-
# RSC15l3
172-
@dont_vary_protocol
173-
async def test_503_status_fallback_on_publish(self):
174-
default_endpoint = 'https://sandbox-rest.ably.io/channels/test/messages'
175-
fallback_host = 'sandbox-a-fallback.ably-realtime.com'
176-
fallback_endpoint = f'https://{fallback_host}/channels/test/messages'
177-
178-
fallback_response_text = (
179-
'{"id": "unique_id:0", "channel": "test", "name": "test", "data": "data", '
180-
'"clientId": null, "connectionId": "connection_id", "timestamp": 1696944145000, '
181-
'"encoding": null}'
182-
)
183-
184-
ably = await TestApp.get_ably_rest(fallback_hosts=[fallback_host])
185-
with respx.mock:
186-
default_route = respx.post(default_endpoint)
187-
fallback_route = respx.post(fallback_endpoint)
188-
headers = {
189-
"Content-Type": "application/json"
190-
}
191-
default_route.return_value = httpx.Response(503, headers=headers)
192-
fallback_route.return_value = httpx.Response(
193-
200,
194-
headers=headers,
195-
text=fallback_response_text,
196-
)
197-
message_response = await ably.channels['test'].publish('test', 'data')
198-
assert default_route.called
199-
assert message_response.to_native()['data'] == 'data'
200-
await ably.close()
201-
202-
# RSC15l4
203-
@dont_vary_protocol
204-
async def test_400_cloudfront_fallback(self):
205-
default_endpoint = 'https://sandbox-rest.ably.io/time'
206-
fallback_host = 'sandbox-a-fallback.ably-realtime.com'
207-
fallback_endpoint = f'https://{fallback_host}/time'
208-
ably = await TestApp.get_ably_rest(fallback_hosts=[fallback_host])
209-
with respx.mock:
210-
default_route = respx.get(default_endpoint)
211-
fallback_route = respx.get(fallback_endpoint)
212-
headers = {
213-
"Server": "CloudFront",
214-
"Content-Type": "application/json",
215-
}
216-
default_route.return_value = httpx.Response(400, headers=headers, text='[456]')
217-
fallback_route.return_value = httpx.Response(200, headers=headers, text='[123]')
218-
result = await ably.request('GET', '/time', version=Defaults.protocol_version)
219-
assert default_route.called
220-
assert result.status_code == 200
221-
assert result.items[0] == 123
222-
await ably.close()
223-
224129
async def test_version(self):
225130
version = "150" # chosen arbitrarily
226131
result = await self.ably.request('GET', '/time', "150")

0 commit comments

Comments
 (0)