mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2024-10-01 11:49:51 -04:00
Add experimental "dont_push" push action to suppress push for notifications
This is a potential solution to https://github.com/vector-im/riot-web/issues/3374 and https://github.com/vector-im/riot-web/issues/5953 as raised by Mozilla at https://github.com/vector-im/riot-web/issues/10868. This lets you define a push rule action which increases the badge count (unread notification) count on a given room, but doesn't actually send a push for that notification via email or HTTP. We might want to define this as the default behaviour for group chats in future to solve https://github.com/vector-im/riot-web/issues/3268 at last. This is implemented as a string action rather than a tweak because: * Other pushers don't care about the tweak, given they won't ever get pushed * The DB can store the tweak more efficiently using the existing `notify` table. * It avoids breaking the default_notif/highlight_action optimisations. Clients which generate their own notifs (e.g. desktop notifs from Riot/Web would need to be aware of the new push action) to uphold it. An alternative way to do this would be to maintain a `msg_count` alongside `highlight_count` and `notification_count` in `unread_notifications` in sync responses. However, doing this by counting the rows in `events` since the `stream_position` of the user's last read receipt turns out to be painfully slow (~200ms), perhaps due to the size of the events table. So instead, we use the highly optimised existing event_push_actions (and event_push_actions_staging) table to maintain the counts - using the code paths which already exist for tracking unread notification counts efficiently. These queries are typically ~3ms or so. The biggest issues I see here are: * We're slightly repurposing the `notif` field on `event_push_actions` to track whether a given action actually sent a `push` or not. This doesn't seem unreasonable, but it's slightly naughty given that previously the field explicitly tracked whether `notify` was true for the action (and as a result, it was uselessly always set to 1 in the DB). * We're going to put more load on the `event_push_actions` table for all the random group chats which people had previously muted. In practice i don't think there are many of these though. * There isn't an MSC for this yet (although this comment could become one).
This commit is contained in:
parent
38fd1f8e3f
commit
2292dc35fc
@ -124,8 +124,8 @@ class EventPushActionsWorkerStore(SQLBaseStore):
|
|||||||
def _get_unread_counts_by_pos_txn(self, txn, room_id, user_id, stream_ordering):
|
def _get_unread_counts_by_pos_txn(self, txn, room_id, user_id, stream_ordering):
|
||||||
|
|
||||||
# First get number of notifications.
|
# First get number of notifications.
|
||||||
# We don't need to put a notif=1 clause as all rows always have
|
# We ignore the notif column, given we want unread counts irrespective of
|
||||||
# notif=1
|
# whether the notification actually sent a push or not.
|
||||||
sql = (
|
sql = (
|
||||||
"SELECT count(*)"
|
"SELECT count(*)"
|
||||||
" FROM event_push_actions ea"
|
" FROM event_push_actions ea"
|
||||||
@ -223,6 +223,7 @@ class EventPushActionsWorkerStore(SQLBaseStore):
|
|||||||
" AND ep.user_id = ?"
|
" AND ep.user_id = ?"
|
||||||
" AND ep.stream_ordering > ?"
|
" AND ep.stream_ordering > ?"
|
||||||
" AND ep.stream_ordering <= ?"
|
" AND ep.stream_ordering <= ?"
|
||||||
|
" AND ep.notif = 1"
|
||||||
" ORDER BY ep.stream_ordering ASC LIMIT ?"
|
" ORDER BY ep.stream_ordering ASC LIMIT ?"
|
||||||
)
|
)
|
||||||
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
||||||
@ -251,6 +252,7 @@ class EventPushActionsWorkerStore(SQLBaseStore):
|
|||||||
" AND ep.user_id = ?"
|
" AND ep.user_id = ?"
|
||||||
" AND ep.stream_ordering > ?"
|
" AND ep.stream_ordering > ?"
|
||||||
" AND ep.stream_ordering <= ?"
|
" AND ep.stream_ordering <= ?"
|
||||||
|
" AND ep.notif = 1"
|
||||||
" ORDER BY ep.stream_ordering ASC LIMIT ?"
|
" ORDER BY ep.stream_ordering ASC LIMIT ?"
|
||||||
)
|
)
|
||||||
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
||||||
@ -323,6 +325,7 @@ class EventPushActionsWorkerStore(SQLBaseStore):
|
|||||||
" AND ep.user_id = ?"
|
" AND ep.user_id = ?"
|
||||||
" AND ep.stream_ordering > ?"
|
" AND ep.stream_ordering > ?"
|
||||||
" AND ep.stream_ordering <= ?"
|
" AND ep.stream_ordering <= ?"
|
||||||
|
" AND ep.notif = 1"
|
||||||
" ORDER BY ep.stream_ordering DESC LIMIT ?"
|
" ORDER BY ep.stream_ordering DESC LIMIT ?"
|
||||||
)
|
)
|
||||||
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
||||||
@ -351,6 +354,7 @@ class EventPushActionsWorkerStore(SQLBaseStore):
|
|||||||
" AND ep.user_id = ?"
|
" AND ep.user_id = ?"
|
||||||
" AND ep.stream_ordering > ?"
|
" AND ep.stream_ordering > ?"
|
||||||
" AND ep.stream_ordering <= ?"
|
" AND ep.stream_ordering <= ?"
|
||||||
|
" AND ep.notif = 1"
|
||||||
" ORDER BY ep.stream_ordering DESC LIMIT ?"
|
" ORDER BY ep.stream_ordering DESC LIMIT ?"
|
||||||
)
|
)
|
||||||
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
args = [user_id, user_id, min_stream_ordering, max_stream_ordering, limit]
|
||||||
@ -400,7 +404,7 @@ class EventPushActionsWorkerStore(SQLBaseStore):
|
|||||||
def _get_if_maybe_push_in_range_for_user_txn(txn):
|
def _get_if_maybe_push_in_range_for_user_txn(txn):
|
||||||
sql = """
|
sql = """
|
||||||
SELECT 1 FROM event_push_actions
|
SELECT 1 FROM event_push_actions
|
||||||
WHERE user_id = ? AND stream_ordering > ?
|
WHERE user_id = ? AND stream_ordering > ? AND notif = 1
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -429,14 +433,15 @@ class EventPushActionsWorkerStore(SQLBaseStore):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# This is a helper function for generating the necessary tuple that
|
# This is a helper function for generating the necessary tuple that
|
||||||
# can be used to inert into the `event_push_actions_staging` table.
|
# can be used to insert into the `event_push_actions_staging` table.
|
||||||
def _gen_entry(user_id, actions):
|
def _gen_entry(user_id, actions):
|
||||||
is_highlight = 1 if _action_has_highlight(actions) else 0
|
is_highlight = 1 if _action_has_highlight(actions) else 0
|
||||||
|
notif = 0 if "dont_push" in actions else 1
|
||||||
return (
|
return (
|
||||||
event_id, # event_id column
|
event_id, # event_id column
|
||||||
user_id, # user_id column
|
user_id, # user_id column
|
||||||
_serialize_action(actions, is_highlight), # actions column
|
_serialize_action(actions, is_highlight), # actions column
|
||||||
1, # notif column
|
notif, # notif column
|
||||||
is_highlight, # highlight column
|
is_highlight, # highlight column
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user