Example #1
0
 def test_percolate_failure_user_unenroll_program(self, mock_on_commit):
     """
     If search_percolate fails we should raise an Exception with some useful information for Sentry
     Case when there is not program enrollment.
     """
     with mute_signals(post_save):
         profile = ProfileFactory.create(filled_out=True)
     program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
     program_enrollment_id = program_enrollment.id
     program_enrollment.delete()
     with self.assertRaises(ProgramEnrollment.DoesNotExist):
         search_percolate_queries(program_enrollment_id, "doesnt_matter")
Example #2
0
 def test_percolate_failure_user_unenroll_program(self, mock_on_commit):
     """
     If search_percolate fails we should raise an Exception with some useful information for Sentry
     Case when there is not program enrollment.
     """
     with mute_signals(post_save):
         profile = ProfileFactory.create(filled_out=True)
     program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
     program_enrollment_id = program_enrollment.id
     program_enrollment.delete()
     with self.assertRaises(ProgramEnrollment.DoesNotExist):
         search_percolate_queries(program_enrollment_id, "doesnt_matter")
Example #3
0
def send_automatic_emails(program_enrollment):
    """
    Send all automatic emails which match the search criteria for a program enrollment

    Args:
        program_enrollment (ProgramEnrollment): A ProgramEnrollment
    """
    percolate_queries = search_percolate_queries(program_enrollment.id, PercolateQuery.AUTOMATIC_EMAIL_TYPE)
    automatic_emails = AutomaticEmail.objects.filter(
        query__in=percolate_queries,
        enabled=True,
    ).exclude(sentautomaticemail__user__programenrollment=program_enrollment)
    user = program_enrollment.user
    for automatic_email in automatic_emails:
        try:
            with mark_emails_as_sent(automatic_email, [user.email]) as user_ids:
                # user_ids should just contain user.id except when we already sent the user the email
                # in a separate process
                recipient_emails = User.objects.filter(id__in=user_ids).values_list('email', flat=True)
                MailgunClient.send_batch(
                    automatic_email.email_subject,
                    automatic_email.email_body,
                    [(context['email'], context) for context in get_mail_vars(list(recipient_emails))],
                    sender_name=automatic_email.sender_name,
                )
        except:  # pylint: disable=bare-except
            log.exception("Error sending mailgun mail for automatic email %s", automatic_email)
Example #4
0
def send_automatic_emails(program_enrollment):
    """
    Send all automatic emails which match the search criteria for a program enrollment

    Args:
        program_enrollment (ProgramEnrollment): A ProgramEnrollment
    """
    percolate_queries = search_percolate_queries(
        program_enrollment.id, PercolateQuery.AUTOMATIC_EMAIL_TYPE)
    automatic_emails = AutomaticEmail.objects.filter(
        query__in=percolate_queries,
        enabled=True,
    ).exclude(sentautomaticemail__user__programenrollment=program_enrollment)
    user = program_enrollment.user
    for automatic_email in automatic_emails:
        try:
            with mark_emails_as_sent(automatic_email,
                                     [user.email]) as user_ids:
                # user_ids should just contain user.id except when we already sent the user the email
                # in a separate process
                recipient_emails = User.objects.filter(
                    id__in=user_ids).values_list('email', flat=True)
                MailgunClient.send_batch(
                    automatic_email.email_subject,
                    automatic_email.email_body,
                    [(context['email'], context)
                     for context in get_mail_vars(list(recipient_emails))],
                    sender_name=automatic_email.sender_name,
                )
        except:  # pylint: disable=bare-except
            log.exception("Error sending mailgun mail for automatic email %s",
                          automatic_email)
Example #5
0
 def test_not_percolated(self, mock_on_commit):
     """If there are no percolated queries we should return an empty queryset"""
     with mute_signals(post_save):
         profile = ProfileFactory.create(filled_out=True)
     program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
     assert list(
         search_percolate_queries(
             program_enrollment.id,
             PercolateQuery.AUTOMATIC_EMAIL_TYPE)) == []
Example #6
0
 def test_percolate_failure(self, mock_on_commit):
     """
     If search_percolate fails we should raise an Exception with some useful information for Sentry
     """
     failures = [{
         "shard": 0,
         "index": "index",
         "status": "BAD_REQUEST",
         "reason": {
             "type": "parse_exception",
             "reason": "failed to parse request",
             "caused_by": {
                 "type":
                 "mapper_parsing_exception",
                 "reason":
                 "Cannot generate dynamic mappings of type [_id] for [_id]"
             }
         }
     }]
     failure_payload = {
         "took": 1,
         "_shards": {
             "total": 5,
             "successful": 0,
             "failed": 5,
             "failures": failures
         },
         "total": 0,
         "matches": []
     }
     with mute_signals(post_save):
         profile = ProfileFactory.create(filled_out=True)
     program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
     with self.assertRaises(PercolateException) as ex, patch(
             'search.api.get_conn',
             return_value=Mock(percolate=Mock(
                 return_value=failure_payload))):
         search_percolate_queries(program_enrollment.id, "doesnt_matter")
     assert ex.exception.args[0] == "Failed to percolate: {}".format(
         failures)
Example #7
0
 def test_percolate_failure(self, mock_on_commit):
     """
     If search_percolate fails we should raise an Exception with some useful information for Sentry
     """
     failures = [
         {
             "shard": 0,
             "index": "index",
             "status": "BAD_REQUEST",
             "reason": {
                 "type": "parse_exception",
                 "reason": "failed to parse request",
                 "caused_by": {
                     "type": "mapper_parsing_exception",
                     "reason": "Cannot generate dynamic mappings of type [_id] for [_id]"
                 }
             }
         }
     ]
     failure_payload = {
         "took": 1,
         "_shards": {
             "total": 5,
             "successful": 0,
             "failed": 5,
             "failures": failures
         },
         "total": 0,
         "matches": []
     }
     with mute_signals(post_save):
         profile = ProfileFactory.create(filled_out=True)
     program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
     with self.assertRaises(PercolateException) as ex, patch(
         'search.api.get_conn', return_value=Mock(percolate=Mock(return_value=failure_payload))
     ):
         search_percolate_queries(program_enrollment.id, "doesnt_matter")
     assert ex.exception.args[0] == "Failed to percolate: {}".format(failures)
Example #8
0
    def test_search_percolate_queries(self, mock_on_commit):
        """search_percolate_queries should find all PercolateQuery which match the given ProgramEnrollment"""
        with mute_signals(post_save):
            profile = ProfileFactory.create(filled_out=True)
        program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
        matching_query = {
            "query": {
                "match": {
                    "profile.first_name": profile.first_name,
                }
            }
        }
        query = PercolateQuery.objects.create(
            query=matching_query,
            original_query={},
            source_type=PercolateQuery.AUTOMATIC_EMAIL_TYPE,
        )

        # Another query which matches but has a different source_type
        PercolateQuery.objects.create(
            query=matching_query,
            original_query={},
            source_type=PercolateQuery.DISCUSSION_CHANNEL_TYPE,
        )

        # Another query that doesn't match
        PercolateQuery.objects.create(
            query={"query": {
                "match": {
                    "profile.first_name": "missing",
                }
            }},
            original_query={},
            source_type=PercolateQuery.AUTOMATIC_EMAIL_TYPE)

        # Only the first appears in the results
        assert list(
            search_percolate_queries(
                program_enrollment.id,
                PercolateQuery.AUTOMATIC_EMAIL_TYPE,
            ).values_list("id", flat=True)) == [query.id]
Example #9
0
    def test_search_percolate_queries(self, mock_on_commit):
        """search_percolate_queries should find all PercolateQuery which match the given ProgramEnrollment"""
        with mute_signals(post_save):
            profile = ProfileFactory.create(filled_out=True)
        program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
        matching_query = {
            "query": {
                "match": {
                    "profile.first_name": profile.first_name,
                }
            }
        }
        query = PercolateQuery.objects.create(
            query=matching_query,
            original_query={},
            source_type=PercolateQuery.AUTOMATIC_EMAIL_TYPE,
        )

        # Another query which matches but has a different source_type
        PercolateQuery.objects.create(
            query=matching_query,
            original_query={},
            source_type=PercolateQuery.DISCUSSION_CHANNEL_TYPE,
        )

        # Another query that doesn't match
        PercolateQuery.objects.create(query={
            "query": {
                "match": {
                    "profile.first_name": "missing",
                }
            }
        }, original_query={}, source_type=PercolateQuery.AUTOMATIC_EMAIL_TYPE)

        # Only the first appears in the results
        assert list(
            search_percolate_queries(
                program_enrollment.id,
                PercolateQuery.AUTOMATIC_EMAIL_TYPE,
            ).values_list("id", flat=True)
        ) == [query.id]
Example #10
0
 def test_not_percolated(self, mock_on_commit):
     """If there are no percolated queries we should return an empty queryset"""
     with mute_signals(post_save):
         profile = ProfileFactory.create(filled_out=True)
     program_enrollment = ProgramEnrollmentFactory.create(user=profile.user)
     assert list(search_percolate_queries(program_enrollment.id, PercolateQuery.AUTOMATIC_EMAIL_TYPE)) == []