def __init__(self, _xmodule_instance_args, _entry_id, course_id, _task_input, action_name): self.task_info_string = ( u'Task: {task_id}, ' u'InstructorTask ID: {entry_id}, ' u'Course: {course_id}, ' u'Input: {task_input}' ).format( task_id=_xmodule_instance_args.get('task_id') if _xmodule_instance_args is not None else None, entry_id=_entry_id, course_id=course_id, task_input=_task_input, ) self.action_name = action_name self.course_id = course_id self.task_progress = TaskProgress(self.action_name, total=None, start_time=time()) self.report_for_verified_only = course_grade_report_verified_only(self.course_id)
def _batch_users(self, context): """ Returns a generator of batches of users. """ def grouper(iterable, chunk_size=self.USER_BATCH_SIZE, fillvalue=None): args = [iter(iterable)] * chunk_size return zip_longest(*args, fillvalue=fillvalue) def get_enrolled_learners_for_course(course_id, verified_only=False): """ Get enrolled learners in a course. verified_only(bool): It indicates if we need only the verified enrollments or all enrollments. """ if optimize_get_learners_switch_enabled(): TASK_LOG.info(u'%s, Creating Course Grade with optimization', task_log_message) return users_for_course_v2(course_id, verified_only=verified_only) TASK_LOG.info(u'%s, Creating Course Grade without optimization', task_log_message) return users_for_course(course_id, verified_only=verified_only) def users_for_course(course_id, verified_only=False): """ Get all the enrolled users in a course. This method fetches & loads the enrolled user objects at once which may cause out-of-memory errors in large courses. This method will be removed when `OPTIMIZE_GET_LEARNERS_FOR_COURSE` waffle flag is removed. """ users = CourseEnrollment.objects.users_enrolled_in( course_id, include_inactive=True, verified_only=verified_only, ) users = users.select_related('profile') return grouper(users) def users_for_course_v2(course_id, verified_only=False): """ Get all the enrolled users in a course chunk by chunk. This generator method fetches & loads the enrolled user objects on demand which in chunk size defined. This method is a workaround to avoid out-of-memory errors. """ filter_kwargs = { 'courseenrollment__course_id': course_id, } if verified_only: filter_kwargs['courseenrollment__mode'] = CourseMode.VERIFIED user_ids_list = get_user_model().objects.filter( **filter_kwargs).values_list('id', flat=True).order_by('id') user_chunks = grouper(user_ids_list) for user_ids in user_chunks: user_ids = [ user_id for user_id in user_ids if user_id is not None ] min_id = min(user_ids) max_id = max(user_ids) users = get_user_model().objects.filter( id__gte=min_id, id__lte=max_id, **filter_kwargs).select_related('profile') yield users course_id = context.course_id task_log_message = u'{}, Task type: {}'.format( context.task_info_string, context.action_name) verified_users_only = course_grade_report_verified_only(course_id) return get_enrolled_learners_for_course(course_id, verified_users_only)