Merge lp:~robru/friends/limit-notifications into lp:friends

Proposed by Robert Bruce Park
Status: Merged
Approved by: Ken VanDine
Approved revision: 192
Merged at revision: 195
Proposed branch: lp:~robru/friends/limit-notifications
Merge into: lp:friends
Diff against target: 113 lines (+33/-4)
2 files modified
friends/tests/test_notify.py (+24/-0)
friends/utils/base.py (+9/-4)
To merge this branch: bzr merge lp:~robru/friends/limit-notifications
Reviewer Review Type Date Requested Status
Ken VanDine Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+158510@code.launchpad.net

Commit message

Limit the rate and age of friends notifications.

Description of the change

I've taken a two-pronged approach at limiting notifications here.

The first is by preventing messages more than 5 days old from being notified. Lots of people were complaining about ancient messages being re-notified, so this should curb that. We might even want to consider making the limit less than 5 days, but I think this is a good choice for now and we can easily finesse it in future based on user feedback (if any).

Secondly, I also implement a global limit of 5 notifications per instance of friends-dispatcher. In practise this means that friends will never notify more than 5 times per refresh interval (which is 15 minutes by default). This value of 5 may also need finessing as well, but the point is that the infrastructure is now in place and it is easy to tweak as we see fit later on.

As usual, massive test coverage is included so we know for sure that these limitations are actually taking effect as expected.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:190
http://jenkins.qa.ubuntu.com/job/friends-ci/27/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/friends-raring-amd64-ci/27

Click here to trigger a rebuild:
http://s-jenkins:8080/job/friends-ci/27/rebuild

review: Approve (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

I like the idea of not notifying for older events, and 5 days is probably good. But I don't think we should limit the number shown per refresh, at least not across all operations. For example, it is more important to see a notification for a direct message or mention than it is to see one for some random status update. So perhaps the limit should be per operation, with different thresholds, so we can notify for all direct messages but only 5 status updates (assuming notifications are enabled for all).

review: Needs Information
Revision history for this message
Robert Bruce Park (robru) wrote :

Well, the default is to not even show notifications for regular status updates, only direct & mentions. I disagree that it's important to notify for all the mentions, because once you see 5 notifications you're going to either check your Friends-app, or maybe even sign in in your browser, and there you will discover all of the messages that are waiting for you anyway.

Also, it's not currently possible to know whether a notify was for a mention or a regular status update from within notify(), so it would be difficult to implement the way you request.

191. By Robert Bruce Park

Revert r188, so allow more than 5 notifications

(but keep the logic about not allowing notifications older than 5 days)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:191
http://jenkins.qa.ubuntu.com/job/friends-ci/36/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/friends-raring-amd64-ci/36/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/friends-ci/36/rebuild

review: Needs Fixing (continuous-integration)
192. By Robert Bruce Park

Fix tests.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:192
http://jenkins.qa.ubuntu.com/job/friends-ci/37/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/friends-raring-amd64-ci/37

Click here to trigger a rebuild:
http://s-jenkins:8080/job/friends-ci/37/rebuild

review: Approve (continuous-integration)
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Good solution for now, thanks

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'friends/tests/test_notify.py'
2--- friends/tests/test_notify.py 2013-04-08 19:33:45 +0000
3+++ friends/tests/test_notify.py 2013-04-16 17:56:28 +0000
4@@ -26,6 +26,11 @@
5 from friends.utils.base import Base
6 from friends.utils.notify import notify
7
8+from datetime import datetime, timedelta
9+
10+RIGHT_NOW = datetime.now().isoformat()
11+YESTERDAY = (datetime.now() - timedelta(1)).isoformat()
12+LAST_WEEK = (datetime.now() - timedelta(7)).isoformat()
13
14 class TestNotifications(unittest.TestCase):
15 """Test notification details."""
16@@ -43,12 +48,27 @@
17 message='http://example.com!',
18 message_id='1234',
19 sender='Benjamin',
20+ timestamp=RIGHT_NOW,
21 )
22 notify.assert_called_once_with('Benjamin', 'http://example.com!', '')
23
24 @mock.patch('friends.utils.base.Model', TestModel)
25 @mock.patch('friends.utils.base._seen_ids', {})
26 @mock.patch('friends.utils.base.notify')
27+ def test_publish_no_stale(self, notify):
28+ Base._do_notify = lambda protocol, stream: True
29+ base = Base(FakeAccount())
30+ base._publish(
31+ message='http://example.com!',
32+ message_id='1234',
33+ sender='Benjamin',
34+ timestamp=LAST_WEEK,
35+ )
36+ self.assertEqual(notify.call_count, 0)
37+
38+ @mock.patch('friends.utils.base.Model', TestModel)
39+ @mock.patch('friends.utils.base._seen_ids', {})
40+ @mock.patch('friends.utils.base.notify')
41 def test_publish_all(self, notify):
42 Base._do_notify = lambda protocol, stream: True
43 base = Base(FakeAccount())
44@@ -56,6 +76,7 @@
45 message='notify!',
46 message_id='1234',
47 sender='Benjamin',
48+ timestamp=YESTERDAY,
49 )
50 notify.assert_called_once_with('Benjamin', 'notify!', '')
51
52@@ -71,6 +92,7 @@
53 message_id='1234',
54 sender='Benjamin',
55 stream='private',
56+ timestamp=RIGHT_NOW,
57 )
58 notify.assert_called_once_with('Benjamin', 'This message is private!', '')
59
60@@ -86,6 +108,7 @@
61 message_id='1234',
62 sender='Benjamin',
63 stream='messages',
64+ timestamp=RIGHT_NOW,
65 )
66 self.assertEqual(notify.call_count, 0)
67
68@@ -100,6 +123,7 @@
69 message_id='1234',
70 sender='Benjamin',
71 stream='messages',
72+ timestamp=RIGHT_NOW,
73 )
74 self.assertEqual(notify.call_count, 0)
75
76
77=== modified file 'friends/utils/base.py'
78--- friends/utils/base.py 2013-04-08 19:33:45 +0000
79+++ friends/utils/base.py 2013-04-16 17:56:28 +0000
80@@ -28,7 +28,7 @@
81 import logging
82 import threading
83
84-from datetime import datetime
85+from datetime import datetime, timedelta
86 from oauthlib.oauth1 import Client
87
88 from gi.repository import GLib, GObject, EDataServer, EBook
89@@ -40,6 +40,7 @@
90 from friends.utils.time import ISO8601_FORMAT
91
92
93+FIVE_DAYS_AGO = (datetime.now() - timedelta(5)).isoformat()
94 STUB = lambda *ignore, **kwignore: None
95 COMMA_SPACE = ', '
96 SCHEMA = Schema()
97@@ -366,9 +367,13 @@
98 # Don't let duplicate messages into the model
99 if message_id not in _seen_ids:
100 _seen_ids[message_id] = Model.get_position(Model.append(*args))
101- # I think it's safe not to notify the user about
102- # messages that they sent themselves...
103- if not args[FROM_ME_IDX] and self._do_notify(args[STREAM_IDX]):
104+
105+ # Don't notify messages from me, or older than five days.
106+ if args[FROM_ME_IDX] or args[TIME_IDX] < FIVE_DAYS_AGO:
107+ return True
108+
109+ # Check if notifications are enabled before notifying.
110+ if self._do_notify(args[STREAM_IDX]):
111 notify(
112 args[SENDER_IDX],
113 orig_message,

Subscribers

People subscribed via source and target branches