tasks.py 3.52 KB
Newer Older
1 2 3 4
"""
Celery task for Automatic Verifed Track Cohorting MVP feature.
"""
from django.contrib.auth.models import User
5
from django.db.utils import IntegrityError
6 7 8 9 10 11 12

from celery.task import task
from celery.utils.log import get_task_logger

from opaque_keys.edx.keys import CourseKey
from student.models import CourseEnrollment, CourseMode
from openedx.core.djangoapps.course_groups.cohorts import (
13
    get_cohort_by_name, get_cohort, add_user_to_cohort
14 15 16 17 18
)

LOGGER = get_task_logger(__name__)


19
@task(bind=True, default_retry_delay=60, max_retries=2)
20
def sync_cohort_with_mode(self, course_id, user_id, verified_cohort_name, default_cohort_name):
21 22 23 24 25 26 27 28 29
    """
    If the learner's mode does not match their assigned cohort, move the learner into the correct cohort.
    It is assumed that this task is only initiated for courses that are using the
    Automatic Verified Track Cohorting MVP feature. It is also assumed that before
    initiating this task, verification has been done to ensure that the course is
    cohorted and has an appropriately named "verified" cohort.
    """
    course_key = CourseKey.from_string(course_id)
    user = User.objects.get(id=user_id)
30 31 32 33
    try:
        enrollment = CourseEnrollment.get_enrollment(user, course_key)
        # 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.
34 35 36 37 38 39 40 41 42 43 44 45 46
        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)

47
        verified_cohort = get_cohort_by_name(course_key, verified_cohort_name)
48

49 50 51
        if enrollment.mode == CourseMode.VERIFIED and (current_cohort.id != verified_cohort.id):
            LOGGER.info(
                "MOVING_TO_VERIFIED: Moving user '%s' to the verified cohort '%s' for course '%s'",
52
                user.id, verified_cohort.name, course_id
53 54 55 56 57 58
            )
            add_user_to_cohort(verified_cohort, user.username)
        elif enrollment.mode != CourseMode.VERIFIED and current_cohort.id == verified_cohort.id:
            default_cohort = get_cohort_by_name(course_key, default_cohort_name)
            LOGGER.info(
                "MOVING_TO_DEFAULT: Moving user '%s' to the default cohort '%s' for course '%s'",
59
                user.id, default_cohort.name, course_id
60 61 62 63 64 65
            )
            add_user_to_cohort(default_cohort, user.username)
        else:
            LOGGER.info(
                "NO_ACTION_NECESSARY: No action necessary for user '%s' in course '%s' and enrollment mode '%s'. "
                "The user is already in cohort '%s'.",
66
                user.id, course_id, enrollment.mode, current_cohort.name
67 68 69 70
            )
    except Exception as exc:
        LOGGER.warning(
            "SYNC_COHORT_WITH_MODE_RETRY: Exception encountered for course '%s' and user '%s': %s",
71
            course_id, user.id, unicode(exc)
72
        )
73
        raise self.retry(exc=exc)