Skip to content

Commit ae0954c

Browse files
committed
throw exception when download of first diff encounters client error
1 parent c1f367b commit ae0954c

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

src/osmium/replication/server.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,14 @@ def collect_diffs(self, start_id: int, max_size: Optional[int] = None,
144144
contains the MergeInputReader with the data and `newest` is a
145145
sequence id of the most recent diff available.
146146
147-
Returns None if there was an error during download or no new
148-
data was available.
147+
Returns None if there was no new data was available.
148+
149+
If there is an error during the download, then the function will
150+
simply return the already downloaded data. If the reported
151+
error is a client error (HTTP 4xx) and happens during the download
152+
of the first diff, then a ::request.HTTPError:: is raised: this
153+
condition is likely to be permanent and the caller should not
154+
simply retry without investigating the cause.
149155
"""
150156
# must not read data newer than the published sequence id
151157
# or we might end up reading partial data
@@ -168,8 +174,19 @@ def collect_diffs(self, start_id: int, max_size: Optional[int] = None,
168174
and current_id <= newest.sequence:
169175
try:
170176
diffdata = self.get_diff_block(current_id)
171-
except: # noqa: E722
172-
LOG.error("Error during diff download. Bailing out.")
177+
except requests.RequestException as ex:
178+
if start_id == current_id \
179+
and ex.response is not None \
180+
and (ex.response.status_code % 100 == 4):
181+
# If server directly responds with a client error,
182+
# reraise the exception to signal a potentially permanent
183+
# error.
184+
LOG.error("Permanent server error: %s", ex.response)
185+
raise ex
186+
# In all other cases, process whatever diffs we have and
187+
# encourage a retry.
188+
LOG.error("Error during diff download: %s", ex)
189+
LOG.error("Bailing out.")
173190
diffdata = ''
174191
if len(diffdata) == 0:
175192
if start_id == current_id:

test/test_replication.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import uuid
1111

1212
import pytest
13+
import requests
1314

1415
from werkzeug.wrappers import Response
1516

@@ -391,6 +392,23 @@ def test_apply_diffs_permanent_error(httpserver, caplog):
391392
httpserver.expect_ordered_request('/000/000/100.opl')\
392393
.respond_with_data('not a file', status=404)
393394

395+
with caplog.at_level(logging.ERROR):
396+
with rserv.ReplicationServer(httpserver.url_for(''), "opl") as svr:
397+
h = CountingHandler()
398+
with pytest.raises(requests.HTTPError, match='404'):
399+
svr.apply_diffs(h, 100, 10000)
400+
401+
assert 'Permanent server error' in caplog.text
402+
403+
404+
def test_apply_diffs_transient_error_first_diff(httpserver, caplog):
405+
httpserver.expect_ordered_request('/state.txt').respond_with_data("""\
406+
sequenceNumber=100
407+
timestamp=2017-08-26T11\\:04\\:02Z
408+
""")
409+
httpserver.expect_request('/000/000/100.opl')\
410+
.respond_with_data('not a file', status=503)
411+
394412
with caplog.at_level(logging.ERROR):
395413
with rserv.ReplicationServer(httpserver.url_for(''), "opl") as svr:
396414
h = CountingHandler()
@@ -421,7 +439,7 @@ def test_apply_diffs_permanent_error_later_diff(httpserver, caplog):
421439
assert 'Error during diff download' in caplog.text
422440

423441

424-
def test_apply_diffs_transient_error(httpserver, caplog):
442+
def test_apply_diffs_transient_error_later_diff(httpserver, caplog):
425443
httpserver.expect_ordered_request('/state.txt').respond_with_data("""\
426444
sequenceNumber=101
427445
timestamp=2017-08-26T11\\:04\\:02Z

0 commit comments

Comments
 (0)