1
0
Fork 0

terrasync.py: improve retry logic and error handling

- Add method assembleUrl() to HTTPGetter.

- Raise a NetworkError exception with the particular URL and number of
  retries when it has been exhausted.

- Number of retries is now trivial to expose as a parameter, and set to
  5 in HTTPGetter.

- Sleep for one second between self.httpConnection.close() and
  self.httpConnection.connect() when retrying a failed HTTP request.

- Apply DRY principle.
This commit is contained in:
Florent Rougon 2018-01-26 14:49:02 +01:00
parent c27ae92c73
commit 2c6f93aa46

View file

@ -28,6 +28,7 @@ from os.path import isfile, isdir, join
import re import re
import argparse import argparse
import shutil import shutil
import time
# Generic exception class for terrasync.py, to be subclassed for each specific # Generic exception class for terrasync.py, to be subclassed for each specific
@ -90,9 +91,12 @@ class HTTPGetter:
self.httpConnection = HTTPConnection(self.parsedBaseUrl.netloc) self.httpConnection = HTTPConnection(self.parsedBaseUrl.netloc)
self.httpRequestHeaders = headers = {'Host':self.parsedBaseUrl.netloc,'Content-Length':0,'Connection':'Keep-Alive','User-Agent':'FlightGear terrasync.py'} self.httpRequestHeaders = headers = {'Host':self.parsedBaseUrl.netloc,'Content-Length':0,'Connection':'Keep-Alive','User-Agent':'FlightGear terrasync.py'}
def assembleUrl(self, httpGetCallback):
return self.parsedBaseUrl.path + httpGetCallback.src
def doGet(self, httpGetCallback): def doGet(self, httpGetCallback):
conn = self.httpConnection conn = self.httpConnection
url = self.parsedBaseUrl.path + httpGetCallback.src url = self.assembleUrl(httpGetCallback)
self.httpConnection.request("GET", url, None, self.httpRequestHeaders) self.httpConnection.request("GET", url, None, self.httpRequestHeaders)
httpResponse = self.httpConnection.getresponse() httpResponse = self.httpConnection.getresponse()
@ -100,16 +104,24 @@ class HTTPGetter:
return httpGetCallback.callback(url, httpResponse) return httpGetCallback.callback(url, httpResponse)
def get(self, httpGetCallback): def get(self, httpGetCallback):
try: nbRetries = nbRetriesLeft = 5
res = self.doGet(httpGetCallback)
except HTTPException:
# try to reconnect once
#print("reconnect")
self.httpConnection.close()
self.httpConnection.connect()
res = self.doGet(httpGetCallback)
return res while True:
try:
return self.doGet(httpGetCallback)
except HTTPException as exc:
if nbRetriesLeft == 0:
raise NetworkError(
"after {nbRetries} retries for URL {url}: {errMsg}"
.format(nbRetries=nbRetries,
url=self.assembleUrl(httpGetCallback),
errMsg=exc)) from exc
# Try to reconnect
self.httpConnection.close()
time.sleep(1)
self.httpConnection.connect()
nbRetriesLeft -= 1
################################################################################################################################# #################################################################################################################################
@ -176,8 +188,12 @@ class HTTPDownloadRequest(HTTPGetCallback):
raise NetworkError("HTTP callback got status {status} for URL {url}" raise NetworkError("HTTP callback got status {status} for URL {url}"
.format(status=httpResponse.status, url=url)) .format(status=httpResponse.status, url=url))
try:
with open(self.dst, 'wb') as f: with open(self.dst, 'wb') as f:
f.write(httpResponse.read()) f.write(httpResponse.read())
except HTTPException as exc:
raise NetworkError("for URL {url}: {error}"
.format(url=url, error=exc)) from exc
if self.mycallback != None: if self.mycallback != None:
self.mycallback(self) self.mycallback(self)