diff --git a/engine/apps/alerts/tasks/check_escalation_finished.py b/engine/apps/alerts/tasks/check_escalation_finished.py index 2e2e01ee..fefd3a90 100644 --- a/engine/apps/alerts/tasks/check_escalation_finished.py +++ b/engine/apps/alerts/tasks/check_escalation_finished.py @@ -7,6 +7,8 @@ from django.db.models import Avg, F, Max, Q from django.utils import timezone from apps.alerts.tasks.task_logger import task_logger +from apps.phone_notifications.models import SMSRecord +from apps.twilioapp.models import TwilioSMSstatuses from common.custom_celery_tasks.log_exception_on_failure_task import shared_log_exception_on_failure_task from common.database import get_random_readonly_database_key_if_present_otherwise_default @@ -106,10 +108,17 @@ def check_alert_group_personal_notifications_task(alert_group_id) -> None: notification_step=UserNotificationPolicy.Step.NOTIFY, ).count() + # sent SMS messages are considered completed for our purpose here + # (ie. do not wait for Twilio delivered confirmation) + sent_but_not_delivered_sms = SMSRecord.objects.filter( + represents_alert_group_id=alert_group_id, + twilioapp_twiliosmss__status=TwilioSMSstatuses.SENT, + ).count() + base_msg = f"Alert group {alert_group_id}" + completed += sent_but_not_delivered_sms delta = triggered - completed if delta > 0: - # TODO: when success notifications are setup for every backend, raise exception here task_logger.info(f"{base_msg} has ({delta}) uncompleted personal notifications") else: task_logger.info(f"{base_msg} personal notifications check passed") diff --git a/engine/apps/alerts/tests/test_check_escalation_finished_task.py b/engine/apps/alerts/tests/test_check_escalation_finished_task.py index 3b57061d..05c93fb8 100644 --- a/engine/apps/alerts/tests/test_check_escalation_finished_task.py +++ b/engine/apps/alerts/tests/test_check_escalation_finished_task.py @@ -15,6 +15,7 @@ from apps.alerts.tasks.check_escalation_finished import ( send_alert_group_escalation_auditor_task_heartbeat, ) from apps.base.models import UserNotificationPolicy, UserNotificationPolicyLogRecord +from apps.twilioapp.models import TwilioSMS, TwilioSMSstatuses MOCKED_HEARTBEAT_URL = "https://hello.com/lsdjjkf" @@ -407,6 +408,7 @@ def test_check_escalation_finished_task_calls_audit_alert_group_personal_notific make_alert_receive_channel, make_alert_group_that_started_at_specific_date, make_user_notification_policy_log_record, + make_sms_record, caplog, ): organization, user = make_organization_and_user() @@ -461,7 +463,7 @@ def test_check_escalation_finished_task_calls_audit_alert_group_personal_notific # records created > 5 mins ago alert_group1.personal_log_records.update(created_at=now - timezone.timedelta(minutes=7)) - # alert_group2: notify user, notification failed + # alert_group2: notify user, notification failed; triggered sms, sent status make_user_notification_policy_log_record( author=user, alert_group=alert_group2, @@ -476,8 +478,24 @@ def test_check_escalation_finished_task_calls_audit_alert_group_personal_notific notification_step=UserNotificationPolicy.Step.NOTIFY, type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED, ) + make_user_notification_policy_log_record( + author=user, + alert_group=alert_group2, + notification_policy=user_notification_policy, + notification_step=UserNotificationPolicy.Step.NOTIFY, + type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_TRIGGERED, + ) + # no failed or succeed record, but SMS was sent (without Twilio delivered confirmation yet) + sms_record = make_sms_record( + receiver=user, + represents_alert_group=alert_group2, + notification_policy=user_notification_policy, + ) + sent_sms = TwilioSMS.objects.create(sid="someid", sms_record=sms_record, status=TwilioSMSstatuses.SENT) # records created > 5 mins ago alert_group2.personal_log_records.update(created_at=now - timezone.timedelta(minutes=7)) + sent_sms.created_at = now - timezone.timedelta(minutes=6) + sent_sms.save() # alert_group3: notify user, missing completion make_user_notification_policy_log_record( @@ -521,4 +539,4 @@ def test_check_escalation_finished_task_calls_audit_alert_group_personal_notific # also trigger the general personal notification checker check_personal_notifications_task() - assert "personal_notifications_triggered=4 personal_notifications_completed=2" in caplog.text + assert "personal_notifications_triggered=5 personal_notifications_completed=2" in caplog.text