From 3a332aee0b23786f15101876d97821e09d19497c Mon Sep 17 00:00:00 2001 From: Steve Howell Date: Sun, 19 Feb 2017 07:43:32 -0800 Subject: [PATCH] Exclude dormant users from buddy list queries. If a user has not shown activity in two weeks, we exclude them from the buddy list. This should help performance for large realms and mobile clients. --- zerver/models.py | 12 +++++++++++- zerver/tests/test_presence.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/zerver/models.py b/zerver/models.py index c5b4fba34e..eac9d0b93e 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -1430,6 +1430,12 @@ class UserPresence(models.Model): return UserPresence.get_status_dicts_for_query(query, mobile_user_ids) + @staticmethod + def exclude_old_users(query): + # type: (QuerySet) -> QuerySet + two_weeks_ago = timezone.now() - datetime.timedelta(weeks=2) + return query.filter(timestamp__gte=two_weeks_ago) + @staticmethod def get_status_dict_by_realm(realm_id): # type: (int) -> DefaultDict[Any, Dict[Any, Any]] @@ -1437,7 +1443,11 @@ class UserPresence(models.Model): user_profile__realm_id=realm_id, user_profile__is_active=True, user_profile__is_bot=False - ).values( + ) + + query = UserPresence.exclude_old_users(query) + + query = query.values( 'client__name', 'status', 'timestamp', diff --git a/zerver/tests/test_presence.py b/zerver/tests/test_presence.py index c25b29a615..a0a36dc9b5 100644 --- a/zerver/tests/test_presence.py +++ b/zerver/tests/test_presence.py @@ -22,6 +22,7 @@ from zerver.models import ( Client, UserActivity, UserProfile, + UserPresence, ) import datetime @@ -57,6 +58,40 @@ class TestClientModel(ZulipTestCase): client = make_client('some_client') self.assertEqual(str(client), u'') +class UserPresenceModelTests(ZulipTestCase): + def test_date_logic(self): + # type: () -> None + UserPresence.objects.all().delete() + + email = "hamlet@zulip.com" + user_profile = get_user_profile_by_email(email) + presence_dct = UserPresence.get_status_dict_by_realm(user_profile.realm_id) + self.assertEqual(len(presence_dct), 0) + + self.login(email) + result = self.client_post("/json/users/me/presence", {'status': 'active'}) + self.assert_json_success(result) + + presence_dct = UserPresence.get_status_dict_by_realm(user_profile.realm_id) + self.assertEqual(len(presence_dct), 1) + self.assertEqual(presence_dct[email]['website']['status'], 'active') + + def back_date(num_weeks): + # type: (int) -> None + user_presence = UserPresence.objects.filter(user_profile=user_profile)[0] + user_presence.timestamp = timezone.now() - datetime.timedelta(weeks=num_weeks) + user_presence.save() + + # Simulate the presence being a week old first. Nothing should change. + back_date(num_weeks=1) + presence_dct = UserPresence.get_status_dict_by_realm(user_profile.realm_id) + self.assertEqual(len(presence_dct), 1) + + # If the UserPresence row is three weeks old, we ignore it. + back_date(num_weeks=3) + presence_dct = UserPresence.get_status_dict_by_realm(user_profile.realm_id) + self.assertEqual(len(presence_dct), 0) + class UserPresenceTests(ZulipTestCase): def test_invalid_presence(self): # type: () -> None