From bbd742adfb2a57353ce88bcc5e840cacf4d7dcc0 Mon Sep 17 00:00:00 2001 From: Hanne Moa Date: Tue, 25 Apr 2023 09:18:23 +0200 Subject: [PATCH] Send notifications via django-q2 --- src/argus/incident/apps.py | 5 +-- src/argus/incident/signals.py | 37 ++++++++++++++----- src/argus/incident/views.py | 4 -- .../notificationprofile/media/__init__.py | 21 +++++------ src/argus/notificationprofile/models.py | 6 ++- src/argus/util/testing.py | 15 +++----- 6 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/argus/incident/apps.py b/src/argus/incident/apps.py index 88c243710..861f61c53 100644 --- a/src/argus/incident/apps.py +++ b/src/argus/incident/apps.py @@ -11,12 +11,11 @@ def ready(self): close_token_incident, delete_associated_user, delete_associated_event, - task_send_notification, # noqa - task_background_send_notification, + enqueue_event_for_notification, ) post_delete.connect(delete_associated_user, "argus_incident.SourceSystem") post_delete.connect(delete_associated_event, "argus_incident.Acknowledgement") post_delete.connect(close_token_incident, "authtoken.Token") post_save.connect(close_token_incident, "authtoken.Token") - post_save.connect(task_background_send_notification, "argus_incident.Event", dispatch_uid="send_notification") + post_save.connect(enqueue_event_for_notification, "argus_incident.Event", dispatch_uid="send_notification") diff --git a/src/argus/incident/signals.py b/src/argus/incident/signals.py index 69cf9ef15..b7137a48a 100644 --- a/src/argus/incident/signals.py +++ b/src/argus/incident/signals.py @@ -1,35 +1,52 @@ +import logging + from django.db.models import Q from django.utils import timezone + from rest_framework.authtoken.models import Token +from django_q.tasks import async_task -from argus.notificationprofile.media import send_notifications_to_users -from argus.notificationprofile.media import background_send_notification +from argus.notificationprofile.media import find_destinations_for_event from argus.notificationprofile.media import send_notification +from argus.notificationprofile.media import are_notifications_turned_on + from .models import ( - Acknowledgement, ChangeEvent, Event, Incident, SourceSystem, Tag, + Acknowledgement, + ChangeEvent, + Event, + Incident, + SourceSystem, + Tag, get_or_create_default_instances, ) __all__ = [ + "enqueue_event_for_notification", "delete_associated_user", "send_notification", "delete_associated_event", "close_token_incident", ] +LOG = logging.getLogger(__name__) -def delete_associated_user(sender, instance: SourceSystem, *args, **kwargs): - if hasattr(instance, "user") and instance.user: - instance.user.delete() +def enqueue_event_for_notification(sender, instance: Event, *args, **kwargs): + if not are_notifications_turned_on(): + return -def task_send_notification(sender, instance: Event, *args, **kwargs): - send_notifications_to_users(instance) + destinations = find_destinations_for_event(instance) + if destinations: + LOG.info('Notification: will be sending notification for "%s"', instance) + async_task(send_notification, destinations, instance, group="notifications") + else: + LOG.debug("Notification: no destinations to send notification to") -def task_background_send_notification(sender, instance: Event, *args, **kwargs): - send_notifications_to_users(instance, send=background_send_notification) +def delete_associated_user(sender, instance: SourceSystem, *args, **kwargs): + if hasattr(instance, "user") and instance.user: + instance.user.delete() def delete_associated_event(sender, instance: Acknowledgement, *args, **kwargs): diff --git a/src/argus/incident/views.py b/src/argus/incident/views.py index dccae0896..c99f057a6 100644 --- a/src/argus/incident/views.py +++ b/src/argus/incident/views.py @@ -28,10 +28,6 @@ TicketPluginException, TicketSettingsException, ) -from argus.notificationprofile.media import ( - send_notifications_to_users, - background_send_notification, -) from argus.util.datetime_utils import INFINITY_REPR from argus.util.signals import bulk_changed from argus.util.utils import import_class_from_dotted_path diff --git a/src/argus/notificationprofile/media/__init__.py b/src/argus/notificationprofile/media/__init__.py index 87271d164..27a4f496c 100644 --- a/src/argus/notificationprofile/media/__init__.py +++ b/src/argus/notificationprofile/media/__init__.py @@ -1,11 +1,9 @@ from __future__ import annotations import logging -from multiprocessing import Process from typing import TYPE_CHECKING from django.conf import settings -from django.db import connections from rest_framework.exceptions import ValidationError from ..models import DestinationConfig, Media, NotificationProfile @@ -25,6 +23,7 @@ __all__ = [ + "are_notifications_turned_on", "api_safely_get_medium_object", "send_notification", "background_send_notification", @@ -41,6 +40,13 @@ MEDIA_CLASSES_DICT = {media_class.MEDIA_SLUG: media_class for media_class in MEDIA_CLASSES} +def are_notifications_turned_on(): + if not getattr(settings, "SEND_NOTIFICATIONS", False): + LOG.info("Notification: turned off sitewide, not sending any") + return False + return True + + def api_safely_get_medium_object(media_slug): try: obj = MEDIA_CLASSES_DICT[media_slug] @@ -65,14 +71,6 @@ def send_notification(destinations: Iterable[DestinationConfig], *events: Iterab LOG.info('Notification: sent event "%s" to "%s"', event, medium.MEDIA_SLUG) -def background_send_notification(destinations: Iterable[DestinationConfig], *events: Event): - connections.close_all() - LOG.info("Notification: backgrounded: about to send %i events", len(events)) - p = Process(target=send_notification, args=(destinations, *events)) - p.start() - return p - - def find_destinations_for_event(event: Event): destinations = set() incident = event.incident @@ -96,8 +94,7 @@ def send_notifications_to_users(*events: Iterable[Event], send=send_notification if not events: LOG.warn("Notification: no events to send, programming error?") return - if not getattr(settings, "SEND_NOTIFICATIONS", False): - LOG.info("Notification: turned off sitewide, not sending any") + if not are_notifications_turned_on(): return # TODO: only send one notification per medium per user LOG.debug('Fallback filter set to "%s"', getattr(settings, "ARGUS_FALLBACK_FILTER", {})) diff --git a/src/argus/notificationprofile/models.py b/src/argus/notificationprofile/models.py index 046429807..a2a6eb7a6 100644 --- a/src/argus/notificationprofile/models.py +++ b/src/argus/notificationprofile/models.py @@ -101,9 +101,10 @@ def save(self, *args, **kwargs): class FilterWrapper: TRINARY_FILTERS = ("open", "acked", "stateful") - def __init__(self, filterblob): + def __init__(self, filterblob, user=None): self.fallback_filter = getattr(settings, "ARGUS_FALLBACK_FILTER", {}) self.filter = filterblob + self.user = user # simplifies debugging, set breakpoint for specific user def _get_tristate(self, tristate): fallback_filter = self.fallback_filter.get(tristate, None) @@ -178,7 +179,8 @@ class Meta: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.filter_wrapper = FilterWrapper(self.filter) + user = getattr(self, "user", None) + self.filter_wrapper = FilterWrapper(self.filter, user) def __str__(self): return f"{self.name} [{self.filter}]" diff --git a/src/argus/util/testing.py b/src/argus/util/testing.py index 12eb6488d..ff4f71995 100644 --- a/src/argus/util/testing.py +++ b/src/argus/util/testing.py @@ -1,9 +1,6 @@ -from django.db.models.signals import post_save - -from argus.incident.signals import send_notification -from argus.incident.signals import background_send_notification -from argus.incident.models import Event +# import the signal sender (aka. post_save) +# import the signal receivers __all__ = [ "disconnect_signals", @@ -15,10 +12,10 @@ def disconnect_signals(): - post_save.disconnect(send_notification, Event, dispatch_uid="send_notification") - post_save.disconnect(background_send_notification, Event, dispatch_uid="send_notification") + # signal.disconnect(receiver) + pass def connect_signals(): - post_save.connect(send_notification, Event, dispatch_uid="send_notification") - post_save.connect(background_send_notification, Event, dispatch_uid="send_notification") + # signal.connect(receiver) + pass