Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/fix download hander failed #9476

Merged
merged 11 commits into from
Apr 27, 2021
3 changes: 3 additions & 0 deletions medusa/clients/torrent/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ def test_authentication(self):
except (requests.exceptions.MissingSchema, requests.exceptions.InvalidURL):
return False, 'Error: Invalid {name} host'.format(name=self.name)

if not self.response:
return False, 'Unable to connect to {name}'.format(name=self.name)

if self.response.status_code == 401:
return False, 'Error: Invalid {name} Username or Password, check your config!'.format(name=self.name)

Expand Down
70 changes: 40 additions & 30 deletions medusa/process_tv.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ def update_resource(self, status):
"""
main_db_con = db.DBConnection()
main_db_con.action(
'UPDATE history set client_status = ? '
'WHERE date = (select max(date) from history where info_hash = ?)',
'UPDATE history set client_status = ? WHERE info_hash = ?',
[status.status, self.info_hash]
)
log.info('Updated history with resource path: {path} and resource: {resource} with new status {status}', {
Expand All @@ -87,8 +86,8 @@ def update_resource(self, status):
'status': status
})

def update_history(self, process_results):
"""Update main.history table with process results."""
def update_history_processed(self, process_results):
"""Update the history table when we have a processed path + resource."""
from medusa.schedulers.download_handler import ClientStatus
status = ClientStatus()

Expand All @@ -99,7 +98,7 @@ def update_history(self, process_results):

# If succeeded store Postprocessed + Completed. (384)
# If failed store Postprocessed + Failed. (272)
if process_results.result:
if process_results.result and not process_results.failed:
status.add_status_string('Completed')
self.success = True
else:
Expand All @@ -112,44 +111,55 @@ def update_history(self, process_results):
'resource': self.resource_name
})

def process_path(self):
"""Process for when we have a valid path."""
process_method = self.process_method or app.PROCESS_METHOD

process_results = ProcessResult(self.path, process_method, failed=self.failed)
process_results.process(
resource_name=self.resource_name,
force=self.force,
is_priority=self.is_priority,
delete_on=self.delete_on,
proc_type=self.proc_type,
ignore_subs=self.ignore_subs
)

# A user might want to use advanced post-processing, but opt-out of failed download handling.
if (app.USE_FAILED_DOWNLOADS and (process_results.failed or (not process_results.succeeded and self.resource_name))):
process_results.process_failed(self.path)

# In case we have an info_hash or (nzbid), update the history table with the pp results.
if self.info_hash:
self.update_history_processed(process_results)

return process_results

def run(self):
"""Run postprocess queueitem thread."""
generic_queue.QueueItem.run(self)
self.started = True

try:
log.info('Beginning postprocessing for path {path}', {'path': self.path})
log.info('Beginning postprocessing for path {path} and resource {resource}', {
'path': self.path, 'resource': self.resource_name
})

# Push an update to any open Web UIs through the WebSocket
ws.Message('QueueItemUpdate', self.to_json).push()

path = self.path or app.TV_DOWNLOAD_DIR
process_method = self.process_method or app.PROCESS_METHOD

process_results = ProcessResult(path, process_method, failed=self.failed)
process_results.process(
resource_name=self.resource_name,
force=self.force,
is_priority=self.is_priority,
delete_on=self.delete_on,
proc_type=self.proc_type,
ignore_subs=self.ignore_subs
)
if not self.path and self.resource_name:
# We don't have a path, but do have a resource name. If this is a failed download.
# Let's use the TV_DOWNLOAD_DIR as path combined with the resource_name.
self.path = app.TV_DOWNLOAD_DIR

# A user might want to use advanced post-processing, but opt-out of failed download handling.
if app.USE_FAILED_DOWNLOADS \
and (process_results.failed or (not process_results.succeeded and self.resource_name)):
process_results.process_failed(path)

# In case we have an info_hash or (nzbid), update the history table with the pp results.
if self.info_hash:
self.update_history(process_results)
if self.path:
process_results = self.process_path()
if process_results._output:
self.to_json.update({'output': process_results._output})

log.info('Completed Postproccessing')

if process_results._output:
self.to_json.update({'output': process_results._output})

# Use success as a flag for a finished PP. PP it self can be succeeded or failed.
self.success = True

Expand Down Expand Up @@ -460,7 +470,7 @@ def _get_files(self, path):
# If resource_name is a file and not an NZB, process it directly
def walk_path(path_name):
topdown = True if self.directory == path_name else False
for root, dirs, files in os.walk(path, topdown=topdown):
for root, dirs, files in os.walk(path_name, topdown=topdown):
if files:
yield root, sorted(files)
if topdown:
Expand Down
22 changes: 19 additions & 3 deletions medusa/schedulers/download_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,30 @@ def _check_postprocess(self, client):
continue

log.debug(
'Found {client_type} (status {status}) on {client} with info_hash {info_hash}',
'Sending postprocess job for {client_type} with info_hash: {info_hash}'
'\nstatus: {status}\nclient: {client}'
'\ndestination: {destination}\nresource: {resource}',
{
'client_type': client_type,
'info_hash': history_result['info_hash'],
'status': status,
'client': app.TORRENT_METHOD if client_type == 'torrent' else app.NZB_METHOD,
'info_hash': history_result['info_hash']
'destination': status.destination,
'resource': status.resource or history_result['resource']
}
)

if not status.destination and not status.resource and history_result['resource']:
# We didn't get a destination, because probably it failed to start a download.
# For example when it already failed to get the nzb. But we have a resource name from the snatch.
# We'll use this, so that we can finish the postprocessing and possible failed download handling.
status.resource = history_result['resource']

if not status.destination and not status.resource:
log.warning('Not starting postprocessing for info_hash {info_hash}, need a destination path.',
{'info_hash': history_result['info_hash']})
continue

self._postprocess(
status.destination, history_result['info_hash'], status.resource,
failed=str(status) == 'Failed'
Expand Down Expand Up @@ -311,7 +327,7 @@ def _clean(self, client):
"""Update status in the history table for torrents/nzb's that can't be located anymore."""
client_type = 'torrent' if isinstance(client, GenericClient) else 'nzb'

# Make sure the client can be reached. As we don't want to change the state for downlaods
# Make sure the client can be reached. As we don't want to change the state for downloads
# because the client is temporary unavailable.
if not self._test_connection(client, client_type):
log.warning('The client cannot be reached or authentication is failing. Abandon cleanup.')
Expand Down
2 changes: 1 addition & 1 deletion medusa/server/api/v2/postprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def post(self, identifier=None):
is_priority = bool(data.get('is_priority', False))
delete_on = bool(data.get('delete_on', False))
failed = bool(data.get('failed', False))
proc_type = bool(data.get('proc_type', False))
proc_type = data.get('proc_type', '')
ignore_subs = bool(data.get('is_priority', False))

if not proc_dir:
Expand Down
6 changes: 5 additions & 1 deletion themes-default/slim/src/components/manual-post-process.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<div class="col-xs-12 col-lg-9">
<config-template label="Process Method to be used" label-for="process_method">
<select id="process_method" name="process_method" v-model="processMethod" class="form-control input-sm">
<select id="process_method" name="process_method" :value="postprocessing.processMethod" @update="processMethod = $event" class="form-control input-sm">
<option v-for="option in availableMethods" :value="option.value" :key="option.value">
{{option.text}}
</option>
Expand Down Expand Up @@ -69,6 +69,10 @@ export default {
ConfigTemplate,
ConfigToggleSlider
},
mounted() {
this.processMethod = this.postprocessing.processMethod;
this.path = this.postprocessing.showDownloadDir;
},
data() {
return {
processMethod: null,
Expand Down
Loading