From 1ce0dbde0ee7ed203f994664fdb5926ca8c8d293 Mon Sep 17 00:00:00 2001 From: Aaron Kable Date: Mon, 16 Mar 2020 02:09:24 +0000 Subject: [PATCH 1/2] stop the notification context profider from hitting the database for each menu hook --- allianceauth/notifications/context_processors.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/allianceauth/notifications/context_processors.py b/allianceauth/notifications/context_processors.py index 75726acb..d151fceb 100644 --- a/allianceauth/notifications/context_processors.py +++ b/allianceauth/notifications/context_processors.py @@ -1,5 +1,10 @@ from .models import Notification - +from django.core.cache import cache def user_notification_count(request): - return {'notifications': len(Notification.objects.filter(user__id=request.user.id).filter(viewed=False))} + notification_count = cache.get("u-note:{}".format(request.user.id), -1) + if notification_count<0: + notification_count = Notification.objects.filter(user__id=request.user.id).filter(viewed=False).count() + cache.set("u-note:{}".format(request.user.id),notification_count,5) + + return {'notifications': notification_count} From 3ae5ffa3f6a784c4000390e0007ad4f558429984 Mon Sep 17 00:00:00 2001 From: AaronKable Date: Sat, 23 May 2020 12:04:06 +0800 Subject: [PATCH 2/2] tests --- .../notifications/context_processors.py | 7 +- allianceauth/notifications/tests.py | 1 - allianceauth/notifications/tests/__init__.py | 0 .../notifications/tests/test_processors.py | 72 +++++++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) delete mode 100644 allianceauth/notifications/tests.py create mode 100644 allianceauth/notifications/tests/__init__.py create mode 100644 allianceauth/notifications/tests/test_processors.py diff --git a/allianceauth/notifications/context_processors.py b/allianceauth/notifications/context_processors.py index d151fceb..12a7e685 100644 --- a/allianceauth/notifications/context_processors.py +++ b/allianceauth/notifications/context_processors.py @@ -2,9 +2,10 @@ from .models import Notification from django.core.cache import cache def user_notification_count(request): - notification_count = cache.get("u-note:{}".format(request.user.id), -1) + user_id = request.user.id + notification_count = cache.get("u-note:{}".format(user_id), -1) if notification_count<0: - notification_count = Notification.objects.filter(user__id=request.user.id).filter(viewed=False).count() - cache.set("u-note:{}".format(request.user.id),notification_count,5) + notification_count = Notification.objects.filter(user__id=user_id).filter(viewed=False).count() + cache.set("u-note:{}".format(user_id),notification_count,5) return {'notifications': notification_count} diff --git a/allianceauth/notifications/tests.py b/allianceauth/notifications/tests.py deleted file mode 100644 index a39b155a..00000000 --- a/allianceauth/notifications/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/allianceauth/notifications/tests/__init__.py b/allianceauth/notifications/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/allianceauth/notifications/tests/test_processors.py b/allianceauth/notifications/tests/test_processors.py new file mode 100644 index 00000000..d3365c14 --- /dev/null +++ b/allianceauth/notifications/tests/test_processors.py @@ -0,0 +1,72 @@ +from unittest import mock +from django.test import TestCase +from allianceauth.notifications.context_processors import user_notification_count +from allianceauth.tests.auth_utils import AuthUtils +from django.core.cache import cache +from allianceauth.notifications.models import Notification + +class TestNotificationCount(TestCase): + def setUp(self): + self.user = AuthUtils.create_user('magic_mike') + AuthUtils.add_main_character(self.user, 'Magic Mike', '1', corp_id='2', corp_name='Pole Riders', corp_ticker='PRIDE', alliance_id='3', alliance_name='RIDERS') + self.user.profile.refresh_from_db() + + ### test notifications for mike + + Notification.objects.create(user_id=1, + level="INFO", + title="Job 1 Failed", + message="Because it was broken", + viewed=True) + Notification.objects.create(user_id=1, + level="INFO", + title="Job 2 Failed", + message="Because it was broken") + Notification.objects.create(user_id=1, + level="INFO", + title="Job 3 Failed", + message="Because it was broken") + Notification.objects.create(user_id=1, + level="INFO", + title="Job 4 Failed", + message="Because it was broken") + Notification.objects.create(user_id=1, + level="INFO", + title="Job 5 Failed", + message="Because it was broken") + Notification.objects.create(user_id=1, + level="INFO", + title="Job 6 Failed", + message="Because it was broken") + + self.user2 = AuthUtils.create_user('teh_kid') + AuthUtils.add_main_character(self.user, 'The Kid', '2', corp_id='2', corp_name='Pole Riders', corp_ticker='PRIDE', alliance_id='3', alliance_name='RIDERS') + self.user2.profile.refresh_from_db() + + # Noitification for kid + + Notification.objects.create(user_id=2, + level="INFO", + title="Job 6 Failed", + message="Because it was broken") + + mock_req = mock.MagicMock() + mock_req.user.id = 1 + self.req_mock = mock_req + + def test_no_cache(self): + context_dict = user_notification_count(self.req_mock) + self.assertIsInstance(context_dict, dict) + self.assertEqual(context_dict.get('notifications'), 5) # 5 only + + + @mock.patch('allianceauth.notifications.models.Notification.objects') + def test_cache(self, mock_foo): + mock_foo.filter.return_value = mock_foo + mock_foo.count.return_value = 5 + + cache.set("u-note:{}".format(1),10,5) + context_dict = user_notification_count(self.req_mock) + self.assertIsInstance(context_dict, dict) + self.assertEqual(context_dict.get('notifications'), 10) # cached value + self.assertEqual(mock_foo.called, 0) # ensure the DB was not hit