import logging from celery import shared_task from django.utils import timezone from labs.models import ExamAttempt as DBExamAttempt from labs.exams.attempt import ExamAttempt logger = logging.getLogger(__name__) AUTO_SUBMIT_EXPIRED_EXAM_ATTEMPTS_BATCH_SIZE = 1000 @shared_task() def auto_submit_expired_exam_attempts(): now = timezone.now() expired_attempt_ids = list( DBExamAttempt.objects.filter( submitted_at__isnull=True, expires_at__lt=now, ) .order_by("expires_at", "id") .values_list("id", flat=True)[:AUTO_SUBMIT_EXPIRED_EXAM_ATTEMPTS_BATCH_SIZE] ) for attempt_id in expired_attempt_ids: try: db_attempt = DBExamAttempt.objects.filter( id=attempt_id, submitted_at__isnull=True, expires_at__lt=now, ).first() if db_attempt is None: continue attempt = ExamAttempt(db_attempt) attempt.submit_exam() logger.info(f"Auto-submitted expired exam attempt {attempt_id}") except Exception as e: logger.error(f"Failed to auto-submit exam attempt {attempt_id}: {e}")