Skip to content

Commit

Permalink
Retry upload requests on network errors
Browse files Browse the repository at this point in the history
  • Loading branch information
lest committed Aug 31, 2020
1 parent 5844160 commit ed27916
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 35 deletions.
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class BookFusionPlugin(InterfaceActionBase):
description = 'Provides synchronization of your eBooks and metadata from Calibre to your devices via the BookFusion iOS, Android & Web reader.'
supported_platforms = ['windows', 'osx', 'linux']
author = 'BookFusion'
version = (0, 5, 0)
version = (0, 5, 1)
minimum_calibre_version = (3, 16, 0)

actual_plugin = 'calibre_plugins.bookfusion.ui:InterfacePlugin'
Expand Down
115 changes: 81 additions & 34 deletions upload_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def __init__(self, index, db, logger):
self.reply = None
self.canceled = False

self.retries = 0

def start(self):
self.network = QNetworkAccessManager()
self.network.authenticationRequired.connect(self.auth)
Expand Down Expand Up @@ -146,16 +148,22 @@ def init_upload(self):
self.reply.finished.connect(self.complete_init_upload)

def complete_init_upload(self):
resp = self.complete_req('Upload init')

if not self.abort:
if resp is not None:
data = json.loads(resp.data())
self.upload_url = data['url']
self.upload_params = data['params']
self.upload()
else:
self.readyForNext.emit(self.index)
resp, retry, abort = self.complete_req('Upload init')

if retry:
self.init_upload()
return

if abort:
return

if resp is not None:
data = json.loads(resp.data())
self.upload_url = data['url']
self.upload_params = data['params']
self.upload()
else:
self.readyForNext.emit(self.index)

def upload(self):
self.file = QFile(self.file_path)
Expand All @@ -177,13 +185,19 @@ def complete_upload(self):
if self.file:
self.file.close()

resp = self.complete_req('Upload')
resp, retry, abort = self.complete_req('Upload')

if not self.abort:
if resp is not None:
self.finalize_upload()
else:
self.readyForNext.emit(self.index)
if retry:
self.upload()
return

if abort:
return

if resp is not None:
self.finalize_upload()
else:
self.readyForNext.emit(self.index)

def finalize_upload(self):
self.req = api.build_request('/uploads/finalize')
Expand All @@ -199,14 +213,20 @@ def finalize_upload(self):
def complete_finalize_upload(self):
self.clean_metadata_req()

resp = self.complete_req('Upload finalize')
resp, retry, abort = self.complete_req('Upload finalize')

if not self.abort:
if resp is not None:
self.set_bookfusion_id(json.loads(resp.data())['id'])
self.uploaded.emit(self.book_id)
if retry:
self.finalize_upload()
return

self.readyForNext.emit(self.index)
if abort:
return

if resp is not None:
self.set_bookfusion_id(json.loads(resp.data())['id'])
self.uploaded.emit(self.book_id)

self.readyForNext.emit(self.index)

def update(self):
if not prefs['update_metadata']:
Expand All @@ -230,13 +250,19 @@ def update(self):
def complete_update(self):
self.clean_metadata_req()

resp = self.complete_req('Update')
resp, retry, abort = self.complete_req('Update')

if not self.abort:
if resp is not None:
self.updated.emit(self.book_id)
if retry:
self.update()
return

self.readyForNext.emit(self.index)
if abort:
return

if resp is not None:
self.updated.emit(self.book_id)

self.readyForNext.emit(self.index)

def upload_progress(self, sent, total):
self.uploadProgress.emit(self.book_id, sent, total)
Expand Down Expand Up @@ -349,21 +375,21 @@ def build_req_part(self, name, value):
return part

def complete_req(self, tag):
self.abort = False
retry = False
abort = False

if self.canceled:
self.abort = True
abort = True

error = self.reply.error()
resp = None
if error == QNetworkReply.AuthenticationRequiredError:
self.abort = True
abort = True
self.aborted.emit('Invalid API key.')
self.log_info('{}: AuthenticationRequiredError'.format(tag))
elif error == QNetworkReply.NoError:
resp = self.reply.readAll()
self.log_info('{} response: {}'.format(tag, resp))

return resp
elif error == QNetworkReply.UnknownContentError:
if self.reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 422:
resp = self.reply.readAll()
Expand All @@ -380,17 +406,38 @@ def complete_req(self, tag):
self.log_info('{}: UnknownServerError'.format(tag))
resp = self.reply.readAll()
self.log_info('{} response: {}'.format(tag, resp))
elif error == QNetworkReply.ConnectionRefusedError or \
error == QNetworkReply.RemoteHostClosedError or \
error == QNetworkReply.HostNotFoundError or \
error == QNetworkReply.TimeoutError or \
error == QNetworkReply.TemporaryNetworkFailureError:
retry = True
self.log_info('{}: {}'.format(tag, error))
elif error == QNetworkReply.OperationCanceledError:
self.abort = True
abort = True
self.log_info('{}: OperationCanceledError'.format(tag))
else:
self.abort = True
abort = True
self.aborted.emit('Error {}.'.format(error))
self.log_info('{} error: {}'.format(tag, error))

self.reply.deleteLater()
self.reply = None

if retry:
self.retries += 1

if self.retries > 2:
self.retries = 0
self.aborted.emit('Error {}.'.format(error))
retry = False
else:
abort = False
else:
self.retries = 0

return (resp, retry, abort)

def calculate_digest(self):
if self.digest is not None:
return
Expand Down

0 comments on commit ed27916

Please sign in to comment.