Commit 36b0c593 by Calen Pennington

Retry failed Programs tasks using exponential backoff and a configurable retry limit

parent 3940b1ba
...@@ -136,11 +136,14 @@ def award_program_certificates(self, username): ...@@ -136,11 +136,14 @@ def award_program_certificates(self, username):
""" """
LOGGER.info('Running task award_program_certificates for username %s', username) LOGGER.info('Running task award_program_certificates for username %s', username)
config = ProgramsApiConfig.current()
countdown = 2 ** self.request.retries
# If either programs or credentials config models are disabled for this # If either programs or credentials config models are disabled for this
# feature, this task should not have been invoked in the first place, and # feature, this task should not have been invoked in the first place, and
# an error somewhere is likely (though a race condition is also possible). # an error somewhere is likely (though a race condition is also possible).
# In either case, the task should not be executed nor should it be retried. # In either case, the task should not be executed nor should it be retried.
if not ProgramsApiConfig.current().is_certification_enabled: if not config.is_certification_enabled:
LOGGER.warning( LOGGER.warning(
'Task award_program_certificates cannot be executed when program certification is disabled in API config', 'Task award_program_certificates cannot be executed when program certification is disabled in API config',
) )
...@@ -179,7 +182,7 @@ def award_program_certificates(self, username): ...@@ -179,7 +182,7 @@ def award_program_certificates(self, username):
# Invoke the Programs API completion check endpoint to identify any # Invoke the Programs API completion check endpoint to identify any
# programs that are satisfied by these course completions. # programs that are satisfied by these course completions.
programs_client = get_api_client(ProgramsApiConfig.current(), student) programs_client = get_api_client(config, student)
program_ids = get_completed_programs(programs_client, course_certs) program_ids = get_completed_programs(programs_client, course_certs)
if not program_ids: if not program_ids:
# Again, no reason to continue beyond this point unless/until this # Again, no reason to continue beyond this point unless/until this
...@@ -192,7 +195,7 @@ def award_program_certificates(self, username): ...@@ -192,7 +195,7 @@ def award_program_certificates(self, username):
except Exception as exc: # pylint: disable=broad-except except Exception as exc: # pylint: disable=broad-except
LOGGER.exception('Failed to determine program certificates to be awarded for user %s', username) LOGGER.exception('Failed to determine program certificates to be awarded for user %s', username)
raise self.retry(exc=exc) raise self.retry(exc=exc, countdown=countdown, max_retries=config.max_retries)
# For each completed program for which the student doesn't already have a # For each completed program for which the student doesn't already have a
# certificate, award one now. # certificate, award one now.
...@@ -208,7 +211,7 @@ def award_program_certificates(self, username): ...@@ -208,7 +211,7 @@ def award_program_certificates(self, username):
except Exception as exc: # pylint: disable=broad-except except Exception as exc: # pylint: disable=broad-except
LOGGER.exception('Failed to create a credentials API client to award program certificates') LOGGER.exception('Failed to create a credentials API client to award program certificates')
# Retry because a misconfiguration could be fixed # Retry because a misconfiguration could be fixed
raise self.retry(exc=exc) raise self.retry(exc=exc, countdown=countdown, max_retries=config.max_retries)
for program_id in new_program_ids: for program_id in new_program_ids:
try: try:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment