Exemple #1
0
def submit_bulk_course_email(request, course_key, email_id, schedule=None):
    """
    Request to have bulk email sent as a background task.

    The specified CourseEmail object will be sent be updated for all students who have enrolled
    in a course.  Parameters are the `course_key` and the `email_id`, the id of the CourseEmail object.

    AlreadyRunningError is raised if the same recipients are already being emailed with the same
    CourseEmail object.
    """
    # Assume that the course is defined, and that the user has already been verified to have
    # appropriate access to the course. But make sure that the email exists.
    # We also pull out the targets argument here, so that is displayed in
    # the InstructorTask status.
    email_obj = CourseEmail.objects.get(id=email_id)
    # task_input has a limit to the size it can store, so any target_type with count > 1 is combined and counted
    targets = Counter([target.target_type for target in email_obj.targets.all()])
    targets = [
        target if count <= 1 else
        f"{count} {target}"
        for target, count in targets.items()
    ]

    task_type = 'bulk_course_email'
    task_class = send_bulk_course_email
    task_input = {'email_id': email_id, 'to_option': targets}
    task_key_stub = str(email_id)
    # create the key value by using MD5 hash:
    task_key = hashlib.md5(task_key_stub.encode('utf-8')).hexdigest()

    if schedule:
        return schedule_task(request, task_type, course_key, task_input, task_key, schedule)

    return submit_task(request, task_type, task_class, course_key, task_input, task_key)
    def test_create_scheduled_instructor_task(self):
        """
        Happy path test for the `schedule_task` function. Verifies that we create an InstructorTask instance and an
        associated InstructorTaskSchedule instance as expected.
        """
        with LogCapture() as log:
            schedule_task(self.request, self.task_type, self.course.id,
                          self.task_input, self.task_key, self.schedule)

        # get the task instance and its associated schedule for verifications
        task = InstructorTask.objects.get(course_id=self.course.id,
                                          task_key=self.task_key)
        task_schedule = InstructorTaskSchedule.objects.get(task=task)
        expected_task_args = {
            "request_info": {
                "username": self.instructor.username,
                "user_id": self.instructor.id,
                "ip": "127.0.0.1",
                "agent": "test_agent",
                "host": "test_server_name",
            },
            "task_id": task.task_id
        }
        expected_messages = [
            f"Creating a scheduled instructor task of type '{self.task_type}' for course '{self.course.id}' requested "
            f"by user with id '{self.request.user.id}'",
            f"Creating a task schedule associated with instructor task '{task.id}' and due after '{self.schedule}'",
            f"Updating task state of instructor task '{task.id}' to '{SCHEDULED}'"
        ]
        # convert from text back to JSON before comparison
        actual_task_args = json.loads(task_schedule.task_args)

        # verify the task has the correct state
        assert task.task_state == SCHEDULED
        # verify that the schedule is associated with the correct task_id (UUID)
        assert task_schedule.task_id == task.id
        # verify that the schedule is the expected date and time
        assert task_schedule.task_due == self.schedule
        # verify the task_arguments are as expected
        assert expected_task_args == actual_task_args
        self._verify_log_messages(expected_messages, log)
    def test_create_scheduled_instructor_task_expect_failure(
            self, mock_get_xmodule_instance_args):
        """
        A test to verify that we will mark a task as `FAILED` if a failure occurs during the creation of the task
        schedule.
        """
        expected_messages = [
            f"Creating a scheduled instructor task of type '{self.task_type}' for course '{self.course.id}' requested "
            f"by user with id '{self.request.user.id}'",
            "Error occurred during task or schedule creation: boom!",
        ]

        with self.assertRaises(QueueConnectionError):
            with LogCapture() as log:
                schedule_task(self.request, self.task_type, self.course.id,
                              self.task_input, self.task_key, self.schedule)

        task = InstructorTask.objects.get(course_id=self.course.id,
                                          task_key=self.task_key)
        assert task.task_state == FAILURE
        self._verify_log_messages(expected_messages, log)