diff mbox

[01/13] utils: Rework how notifications are selected

Message ID 1457698097-3264-2-git-send-email-stephen.finucane@intel.com
State Superseded
Headers show

Commit Message

Stephen Finucane March 11, 2016, 12:08 p.m. UTC
The current method of filtering valid patches from invalid ones is
effective, but incompatible with forthcoming rework that splits
the 'Patch' model into two models. Rework this, removing the
soon-to-be non-existant 'User.patch' reference.

Signed-off-by: Stephen Finucane <stephen.finucane@intel.com>
---
 patchwork/utils.py | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)
diff mbox

Patch

diff --git a/patchwork/utils.py b/patchwork/utils.py
index 62ffc3a..4ca5642 100644
--- a/patchwork/utils.py
+++ b/patchwork/utils.py
@@ -26,7 +26,7 @@  from django.conf import settings
 from django.contrib.auth.models import User
 from django.contrib.sites.models import Site
 from django.core.mail import EmailMessage
-from django.db.models import Max, Q, F
+from django.db.models import Count, Q, F
 from django.template.loader import render_to_string
 
 from patchwork.models import (PatchChangeNotification, EmailOptout,
@@ -37,14 +37,16 @@  def send_notifications():
     date_limit = datetime.datetime.now() - datetime.timedelta(
         minutes=settings.NOTIFICATION_DELAY_MINUTES)
 
-    # This gets funky: we want to filter out any notifications that should
-    # be grouped with other notifications that aren't ready to go out yet. To
-    # do that, we join back onto PatchChangeNotification (PCN -> Patch ->
-    # Person -> Patch -> max(PCN.last_modified)), filtering out any maxima
-    # that are with the date_limit.
-    qs = PatchChangeNotification.objects.annotate(
-        m=Max('patch__submitter__patch__patchchangenotification'
-              '__last_modified')).filter(m__lt=date_limit)
+    # We delay sending notifications to a user if they have other
+    # notifications that are still in the "pending" state. To do this,
+    # we compare the total number of patch change notifications queued
+    # for each user against the number of "ready" notifications.
+    qs = PatchChangeNotification.objects.all()
+    qs2 = PatchChangeNotification.objects\
+        .filter(last_modified__lt=date_limit)\
+        .values('patch__submitter')\
+        .annotate(count=Count('patch__submitter'))
+    qs2 = {elem['patch__submitter']: elem['count'] for elem in qs2}
 
     groups = itertools.groupby(qs.order_by('patch__submitter'),
                                lambda n: n.patch.submitter)
@@ -53,6 +55,10 @@  def send_notifications():
 
     for (recipient, notifications) in groups:
         notifications = list(notifications)
+
+        if recipient.id not in qs2 or qs2[recipient.id] < len(notifications):
+            continue
+
         projects = set([n.patch.project.linkname for n in notifications])
 
         def delete_notifications():