Commit d2788ff2 by Christina Roberts Committed by GitHub

Merge pull request #13207 from edx/christina/tnl-5181

Silence expected IntegrityErrors.
parents 5fac6fb1 9d861137
...@@ -49,7 +49,11 @@ def move_to_verified_cohort(sender, instance, **kwargs): # pylint: disable=unus ...@@ -49,7 +49,11 @@ def move_to_verified_cohort(sender, instance, **kwargs): # pylint: disable=unus
'verified_cohort_name': verified_cohort_name, 'verified_cohort_name': verified_cohort_name,
'default_cohort_name': random_cohort.name 'default_cohort_name': random_cohort.name
} }
log.info("Queuing automatic cohorting for user '%s' in course '%s'", instance.user.username, course_key) log.info(
"Queuing automatic cohorting for user '%s' in course '%s' "
"due to change in enrollment mode from '%s' to '%s'.",
instance.user.id, course_key, instance._old_mode, instance.mode # pylint: disable=protected-access
)
# Do the update with a 3-second delay in hopes that the CourseEnrollment transaction has been # Do the update with a 3-second delay in hopes that the CourseEnrollment transaction has been
# completed before the celery task runs. We want a reasonably short delay in case the learner # completed before the celery task runs. We want a reasonably short delay in case the learner
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
Celery task for Automatic Verifed Track Cohorting MVP feature. Celery task for Automatic Verifed Track Cohorting MVP feature.
""" """
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db.utils import IntegrityError
from celery.task import task from celery.task import task
from celery.utils.log import get_task_logger from celery.utils.log import get_task_logger
...@@ -30,31 +31,43 @@ def sync_cohort_with_mode(self, course_id, user_id, verified_cohort_name, defaul ...@@ -30,31 +31,43 @@ def sync_cohort_with_mode(self, course_id, user_id, verified_cohort_name, defaul
enrollment = CourseEnrollment.get_enrollment(user, course_key) enrollment = CourseEnrollment.get_enrollment(user, course_key)
# Note that this will enroll the user in the default cohort on initial enrollment. # Note that this will enroll the user in the default cohort on initial enrollment.
# That's good because it will force creation of the default cohort if necessary. # That's good because it will force creation of the default cohort if necessary.
current_cohort = get_cohort(user, course_key) try:
current_cohort = get_cohort(user, course_key)
except IntegrityError as integrity_error:
# It is quite common that get_cohort will throw an IntegrityError. This happens
# when 2 celery workers are both handling enrollment change events for the same user
# (for example, if the enrollment mode goes from None -> Audit -> Honor); if the user
# was not previously in a cohort, calling get_cohort will result in a cohort assignment.
LOGGER.info(
"HANDLING_INTEGRITY_ERROR: IntegrityError encountered for course '%s' and user '%s': %s",
course_id, user.id, unicode(integrity_error)
)
current_cohort = get_cohort(user, course_key)
verified_cohort = get_cohort_by_name(course_key, verified_cohort_name) verified_cohort = get_cohort_by_name(course_key, verified_cohort_name)
if enrollment.mode == CourseMode.VERIFIED and (current_cohort.id != verified_cohort.id): if enrollment.mode == CourseMode.VERIFIED and (current_cohort.id != verified_cohort.id):
LOGGER.info( LOGGER.info(
"MOVING_TO_VERIFIED: Moving user '%s' to the verified cohort '%s' for course '%s'", "MOVING_TO_VERIFIED: Moving user '%s' to the verified cohort '%s' for course '%s'",
user.username, verified_cohort.name, course_id user.id, verified_cohort.name, course_id
) )
add_user_to_cohort(verified_cohort, user.username) add_user_to_cohort(verified_cohort, user.username)
elif enrollment.mode != CourseMode.VERIFIED and current_cohort.id == verified_cohort.id: elif enrollment.mode != CourseMode.VERIFIED and current_cohort.id == verified_cohort.id:
default_cohort = get_cohort_by_name(course_key, default_cohort_name) default_cohort = get_cohort_by_name(course_key, default_cohort_name)
LOGGER.info( LOGGER.info(
"MOVING_TO_DEFAULT: Moving user '%s' to the default cohort '%s' for course '%s'", "MOVING_TO_DEFAULT: Moving user '%s' to the default cohort '%s' for course '%s'",
user.username, default_cohort.name, course_id user.id, default_cohort.name, course_id
) )
add_user_to_cohort(default_cohort, user.username) add_user_to_cohort(default_cohort, user.username)
else: else:
LOGGER.info( LOGGER.info(
"NO_ACTION_NECESSARY: No action necessary for user '%s' in course '%s' and enrollment mode '%s'. " "NO_ACTION_NECESSARY: No action necessary for user '%s' in course '%s' and enrollment mode '%s'. "
"The user is already in cohort '%s'.", "The user is already in cohort '%s'.",
user.username, course_id, enrollment.mode, current_cohort.name user.id, course_id, enrollment.mode, current_cohort.name
) )
except Exception as exc: except Exception as exc:
LOGGER.warning( LOGGER.warning(
"SYNC_COHORT_WITH_MODE_RETRY: Exception encountered for course '%s' and user '%s': %s", "SYNC_COHORT_WITH_MODE_RETRY: Exception encountered for course '%s' and user '%s': %s",
course_id, user.username, unicode(exc) course_id, user.id, unicode(exc)
) )
raise self.retry(exc=exc) raise self.retry(exc=exc)
...@@ -90,7 +90,7 @@ class CohortMembership(models.Model): ...@@ -90,7 +90,7 @@ class CohortMembership(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.full_clean(validate_unique=False) self.full_clean(validate_unique=False)
log.info("Saving CohortMembership for '%s' (id=%s) in '%s'", self.user.username, self.user.id, self.course_id) log.info("Saving CohortMembership for user '%s' in '%s'", self.user.id, self.course_id)
# Avoid infinite recursion if creating from get_or_create() call below. # Avoid infinite recursion if creating from get_or_create() call below.
# This block also allows middleware to use CohortMembership.get_or_create without worrying about outer_atomic # This block also allows middleware to use CohortMembership.get_or_create without worrying about outer_atomic
......
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