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
=== modified file 'friends/tests/test_notify.py'
--- friends/tests/test_notify.py 2013-04-08 19:33:45 +0000
+++ friends/tests/test_notify.py 2013-04-16 17:56:28 +0000
@@ -26,6 +26,11 @@
26from friends.utils.base import Base26from friends.utils.base import Base
27from friends.utils.notify import notify27from friends.utils.notify import notify
2828
29from datetime import datetime, timedelta
30
31RIGHT_NOW = datetime.now().isoformat()
32YESTERDAY = (datetime.now() - timedelta(1)).isoformat()
33LAST_WEEK = (datetime.now() - timedelta(7)).isoformat()
2934
30class TestNotifications(unittest.TestCase):35class TestNotifications(unittest.TestCase):
31 """Test notification details."""36 """Test notification details."""
@@ -43,12 +48,27 @@
43 message='http://example.com!',48 message='http://example.com!',
44 message_id='1234',49 message_id='1234',
45 sender='Benjamin',50 sender='Benjamin',
51 timestamp=RIGHT_NOW,
46 )52 )
47 notify.assert_called_once_with('Benjamin', 'http://example.com!', '')53 notify.assert_called_once_with('Benjamin', 'http://example.com!', '')
4854
49 @mock.patch('friends.utils.base.Model', TestModel)55 @mock.patch('friends.utils.base.Model', TestModel)
50 @mock.patch('friends.utils.base._seen_ids', {})56 @mock.patch('friends.utils.base._seen_ids', {})
51 @mock.patch('friends.utils.base.notify')57 @mock.patch('friends.utils.base.notify')
58 def test_publish_no_stale(self, notify):
59 Base._do_notify = lambda protocol, stream: True
60 base = Base(FakeAccount())
61 base._publish(
62 message='http://example.com!',
63 message_id='1234',
64 sender='Benjamin',
65 timestamp=LAST_WEEK,
66 )
67 self.assertEqual(notify.call_count, 0)
68
69 @mock.patch('friends.utils.base.Model', TestModel)
70 @mock.patch('friends.utils.base._seen_ids', {})
71 @mock.patch('friends.utils.base.notify')
52 def test_publish_all(self, notify):72 def test_publish_all(self, notify):
53 Base._do_notify = lambda protocol, stream: True73 Base._do_notify = lambda protocol, stream: True
54 base = Base(FakeAccount())74 base = Base(FakeAccount())
@@ -56,6 +76,7 @@
56 message='notify!',76 message='notify!',
57 message_id='1234',77 message_id='1234',
58 sender='Benjamin',78 sender='Benjamin',
79 timestamp=YESTERDAY,
59 )80 )
60 notify.assert_called_once_with('Benjamin', 'notify!', '')81 notify.assert_called_once_with('Benjamin', 'notify!', '')
6182
@@ -71,6 +92,7 @@
71 message_id='1234',92 message_id='1234',
72 sender='Benjamin',93 sender='Benjamin',
73 stream='private',94 stream='private',
95 timestamp=RIGHT_NOW,
74 )96 )
75 notify.assert_called_once_with('Benjamin', 'This message is private!', '')97 notify.assert_called_once_with('Benjamin', 'This message is private!', '')
7698
@@ -86,6 +108,7 @@
86 message_id='1234',108 message_id='1234',
87 sender='Benjamin',109 sender='Benjamin',
88 stream='messages',110 stream='messages',
111 timestamp=RIGHT_NOW,
89 )112 )
90 self.assertEqual(notify.call_count, 0)113 self.assertEqual(notify.call_count, 0)
91114
@@ -100,6 +123,7 @@
100 message_id='1234',123 message_id='1234',
101 sender='Benjamin',124 sender='Benjamin',
102 stream='messages',125 stream='messages',
126 timestamp=RIGHT_NOW,
103 )127 )
104 self.assertEqual(notify.call_count, 0)128 self.assertEqual(notify.call_count, 0)
105129
106130
=== modified file 'friends/utils/base.py'
--- friends/utils/base.py 2013-04-08 19:33:45 +0000
+++ friends/utils/base.py 2013-04-16 17:56:28 +0000
@@ -28,7 +28,7 @@
28import logging28import logging
29import threading29import threading
3030
31from datetime import datetime31from datetime import datetime, timedelta
32from oauthlib.oauth1 import Client32from oauthlib.oauth1 import Client
3333
34from gi.repository import GLib, GObject, EDataServer, EBook34from gi.repository import GLib, GObject, EDataServer, EBook
@@ -40,6 +40,7 @@
40from friends.utils.time import ISO8601_FORMAT40from friends.utils.time import ISO8601_FORMAT
4141
4242
43FIVE_DAYS_AGO = (datetime.now() - timedelta(5)).isoformat()
43STUB = lambda *ignore, **kwignore: None44STUB = lambda *ignore, **kwignore: None
44COMMA_SPACE = ', '45COMMA_SPACE = ', '
45SCHEMA = Schema()46SCHEMA = Schema()
@@ -366,9 +367,13 @@
366 # Don't let duplicate messages into the model367 # Don't let duplicate messages into the model
367 if message_id not in _seen_ids:368 if message_id not in _seen_ids:
368 _seen_ids[message_id] = Model.get_position(Model.append(*args))369 _seen_ids[message_id] = Model.get_position(Model.append(*args))
369 # I think it's safe not to notify the user about370
370 # messages that they sent themselves...371 # Don't notify messages from me, or older than five days.
371 if not args[FROM_ME_IDX] and self._do_notify(args[STREAM_IDX]):372 if args[FROM_ME_IDX] or args[TIME_IDX] < FIVE_DAYS_AGO:
373 return True
374
375 # Check if notifications are enabled before notifying.
376 if self._do_notify(args[STREAM_IDX]):
372 notify(377 notify(
373 args[SENDER_IDX],378 args[SENDER_IDX],
374 orig_message,379 orig_message,

Subscribers

People subscribed via source and target branches