Some more graceful error handling for the rhbz sync script.
This commit is contained in:
parent
2c245cf7c2
commit
b1ac1a3f55
1 changed files with 36 additions and 6 deletions
|
@ -41,7 +41,6 @@ import codecs
|
||||||
import smtplib
|
import smtplib
|
||||||
import multiprocessing.pool
|
import multiprocessing.pool
|
||||||
from math import ceil
|
from math import ceil
|
||||||
from functools import partial
|
|
||||||
try:
|
try:
|
||||||
from email.Message import Message
|
from email.Message import Message
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -184,6 +183,28 @@ The Fedora admins.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def resilient_partial(fn, *initial):
|
||||||
|
""" A decorator that partially applies arguments.
|
||||||
|
|
||||||
|
It additionally catches all raised exceptions, prints them, but then returns
|
||||||
|
None instead of propagating the failures.
|
||||||
|
|
||||||
|
This is used to protect functions used in a threadpool. If one fails, we
|
||||||
|
want to know about it, but we don't want it to kill the whole program. So
|
||||||
|
catch its error, log it, but proceed.
|
||||||
|
"""
|
||||||
|
def wrapper(*additional):
|
||||||
|
try:
|
||||||
|
full = initial + additional
|
||||||
|
return fn(*full)
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
return None
|
||||||
|
wrapper.__name__ = fn.__name__
|
||||||
|
wrapper.__doc__ = fn.__doc__
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class DataChangedError(Exception):
|
class DataChangedError(Exception):
|
||||||
'''Raised when data we are manipulating changes while we're modifying it.'''
|
'''Raised when data we are manipulating changes while we're modifying it.'''
|
||||||
pass
|
pass
|
||||||
|
@ -713,10 +734,13 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
# Since we are going to multi-thread, we need to make a partial
|
# Since we are going to multi-thread, we need to make a partial
|
||||||
# function call so that all the function needs is an iterable to run
|
# function call so that all the function needs is an iterable to run
|
||||||
p_get_pagure_projects_from_page = partial(
|
p_get_pagure_projects_from_page = resilient_partial(
|
||||||
_get_pagure_projects_from_page, session, namespace)
|
_get_pagure_projects_from_page, session, namespace)
|
||||||
pagure_namespace_to_project_lists[namespace] = pool.map(
|
pagure_namespace_to_project_lists[namespace] = pool.map(
|
||||||
p_get_pagure_projects_from_page, range(1, num_pages + 1))
|
p_get_pagure_projects_from_page, range(1, num_pages + 1))
|
||||||
|
# Filter out failures.
|
||||||
|
pagure_namespace_to_project_lists[namespace] = [
|
||||||
|
i for i in pagure_namespace_to_project_lists[namespace] if i]
|
||||||
|
|
||||||
# Flatten the list of lists (each page is a list of a projects)
|
# Flatten the list of lists (each page is a list of a projects)
|
||||||
pagure_namespace_to_projects = {}
|
pagure_namespace_to_projects = {}
|
||||||
|
@ -732,10 +756,14 @@ if __name__ == '__main__':
|
||||||
# {'python-requests': 'master', 'f27', 'f26'}
|
# {'python-requests': 'master', 'f27', 'f26'}
|
||||||
pagure_rpm_project_names = [project['name'] for project in
|
pagure_rpm_project_names = [project['name'] for project in
|
||||||
pagure_namespace_to_projects['rpms']]
|
pagure_namespace_to_projects['rpms']]
|
||||||
p_get_pdc_project_name_and_branches = partial(
|
p_get_pdc_project_name_and_branches = resilient_partial(
|
||||||
_get_pdc_project_name_and_branches, session, 'rpms')
|
_get_pdc_project_name_and_branches, session, 'rpms')
|
||||||
pagure_rpm_project_branches = dict(pool.map(
|
pagure_rpm_project_branches = pool.map(
|
||||||
p_get_pdc_project_name_and_branches, pagure_rpm_project_names))
|
p_get_pdc_project_name_and_branches, pagure_rpm_project_names)
|
||||||
|
# Filter out failures.
|
||||||
|
pagure_rpm_project_branches = [i for i in pagure_rpm_project_branches if i]
|
||||||
|
# Transform
|
||||||
|
pagure_rpm_project_branches = dict(pagure_rpm_project_branches)
|
||||||
# This is no longer needed, so we can save some RAM
|
# This is no longer needed, so we can save some RAM
|
||||||
del pagure_rpm_project_names
|
del pagure_rpm_project_names
|
||||||
|
|
||||||
|
@ -770,11 +798,13 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
# Now, we must transform the data we collected into something that PkgDB
|
# Now, we must transform the data we collected into something that PkgDB
|
||||||
# would have returned
|
# would have returned
|
||||||
p_pagure_project_to_acl_schema = partial(
|
p_pagure_project_to_acl_schema = resilient_partial(
|
||||||
_pagure_project_to_acl_schema, session=session)
|
_pagure_project_to_acl_schema, session=session)
|
||||||
project_to_acl_schemas = pool.map(
|
project_to_acl_schemas = pool.map(
|
||||||
p_pagure_project_to_acl_schema, pagure_rpms_project_products)
|
p_pagure_project_to_acl_schema, pagure_rpms_project_products)
|
||||||
pool.close()
|
pool.close()
|
||||||
|
# Filter out failures.
|
||||||
|
project_to_acl_schemas = [i for i in project_to_acl_schemas if i]
|
||||||
|
|
||||||
# Transform the data returned in project_to_acl_schemas to be an orderly
|
# Transform the data returned in project_to_acl_schemas to be an orderly
|
||||||
# dictionary for ease of use later on.
|
# dictionary for ease of use later on.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue