Files
edx-platform/common/djangoapps/entitlements/tasks.py
Kyle McCormick 151bd13666 Use full names for common.djangoapps imports; warn when using old style (#25477)
* Generate common/djangoapps import shims for LMS
* Generate common/djangoapps import shims for Studio
* Stop appending project root to sys.path
* Stop appending common/djangoapps to sys.path
* Import from common.djangoapps.course_action_state instead of course_action_state
* Import from common.djangoapps.course_modes instead of course_modes
* Import from common.djangoapps.database_fixups instead of database_fixups
* Import from common.djangoapps.edxmako instead of edxmako
* Import from common.djangoapps.entitlements instead of entitlements
* Import from common.djangoapps.pipline_mako instead of pipeline_mako
* Import from common.djangoapps.static_replace instead of static_replace
* Import from common.djangoapps.student instead of student
* Import from common.djangoapps.terrain instead of terrain
* Import from common.djangoapps.third_party_auth instead of third_party_auth
* Import from common.djangoapps.track instead of track
* Import from common.djangoapps.util instead of util
* Import from common.djangoapps.xblock_django instead of xblock_django
* Add empty common/djangoapps/__init__.py to fix pytest collection
* Fix pylint formatting violations
* Exclude import_shims/ directory tree from linting
2020-11-10 07:02:01 -05:00

64 lines
2.7 KiB
Python

"""
This file contains celery tasks for entitlements-related functionality.
"""
from celery import task
from celery.utils.log import get_task_logger
from django.conf import settings
from common.djangoapps.entitlements.models import CourseEntitlement
LOGGER = get_task_logger(__name__)
# Under cms the following setting is not defined, leading to errors during tests.
ROUTING_KEY = getattr(settings, 'ENTITLEMENTS_EXPIRATION_ROUTING_KEY', None)
# Maximum number of retries before giving up on awarding credentials.
# For reference, 11 retries with exponential backoff yields a maximum waiting
# time of 2047 seconds (about 30 minutes). Setting this to None could yield
# unwanted behavior: infinite retries.
MAX_RETRIES = 11
@task(bind=True, ignore_result=True, routing_key=ROUTING_KEY)
def expire_old_entitlements(self, start, end, logid='...'):
"""
This task is designed to be called to process a bundle of entitlements
that might be expired and confirm if we can do so. This is useful when
checking if an entitlement has just been abandoned by the learner and needs
to be expired. (In the normal course of a learner using the platform, the
entitlement will expire itself. But if a learner doesn't log in... So we
run this task every now and then to clear the backlog.)
Args:
start (int): The beginning id in the database to examine
end (int): The id in the database to stop examining at (i.e. range is exclusive)
logid (str): A string to identify this task in the logs
Returns:
None
"""
LOGGER.info('Running task expire_old_entitlements %d:%d [%s]', start, end, logid)
# This query could be optimized to return a more narrow set, but at a
# complexity cost. See bug LEARNER-3451 about improving it.
entitlements = CourseEntitlement.objects.filter(expired_at__isnull=True, id__gte=start, id__lte=end)
countdown = 2 ** self.request.retries
try:
for entitlement in entitlements:
# This property request will update the expiration if necessary as
# a side effect. We could manually call update_expired_at(), but
# let's use the same API the rest of the LMS does, to mimic normal
# usage and allow the update call to be an internal detail.
if entitlement.expired_at_datetime:
LOGGER.info('Expired entitlement with id %d [%s]', entitlement.id, logid)
except Exception as exc:
LOGGER.exception('Failed to expire entitlements [%s]', logid)
# The call above is idempotent, so retry at will
raise self.retry(exc=exc, countdown=countdown, max_retries=MAX_RETRIES)
LOGGER.info('Successfully completed the task expire_old_entitlements after examining %d entries [%s]', entitlements.count(), logid)