Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit c9dbee5

Browse files
authored
Fixup pusher pool notifications (#8287)
`pusher_pool.on_new_notifications` expected a min and max stream ID, however that was not what we were passing in. Instead, let's just pass it the current max stream ID and have it track the last stream ID it got passed. I believe that it mostly worked as we called the function for every event. However, it would break for events that got persisted out of order, i.e, that were persisted but the max stream ID wasn't incremented as not all preceding events had finished persisting, and push for that event would be delayed until another event got pushed to the effected users.
1 parent dc9dcdb commit c9dbee5

File tree

8 files changed

+24
-8
lines changed

8 files changed

+24
-8
lines changed

changelog.d/8287.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix edge case where push could get delayed for a user until a later event was pushed.

synapse/handlers/federation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2970,7 +2970,7 @@ async def _notify_persisted_event(
29702970
event, event_stream_id, max_stream_id, extra_users=extra_users
29712971
)
29722972

2973-
await self.pusher_pool.on_new_notifications(event_stream_id, max_stream_id)
2973+
await self.pusher_pool.on_new_notifications(max_stream_id)
29742974

29752975
async def _clean_room_for_join(self, room_id: str) -> None:
29762976
"""Called to clean up any data in DB for a given room, ready for the

synapse/handlers/message.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ def is_inviter_member_event(e):
11451145
# If there's an expiry timestamp on the event, schedule its expiry.
11461146
self._message_handler.maybe_schedule_expiry(event)
11471147

1148-
await self.pusher_pool.on_new_notifications(event_stream_id, max_stream_id)
1148+
await self.pusher_pool.on_new_notifications(max_stream_id)
11491149

11501150
def _notify():
11511151
try:

synapse/push/emailpusher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def on_stop(self):
9191
pass
9292
self.timed_call = None
9393

94-
def on_new_notifications(self, min_stream_ordering, max_stream_ordering):
94+
def on_new_notifications(self, max_stream_ordering):
9595
if self.max_stream_ordering:
9696
self.max_stream_ordering = max(
9797
max_stream_ordering, self.max_stream_ordering

synapse/push/httppusher.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def on_started(self, should_check_for_notifs):
114114
if should_check_for_notifs:
115115
self._start_processing()
116116

117-
def on_new_notifications(self, min_stream_ordering, max_stream_ordering):
117+
def on_new_notifications(self, max_stream_ordering):
118118
self.max_stream_ordering = max(
119119
max_stream_ordering, self.max_stream_ordering or 0
120120
)

synapse/push/pusherpool.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ def __init__(self, hs: "HomeServer"):
6464
self._pusher_shard_config = hs.config.push.pusher_shard_config
6565
self._instance_name = hs.get_instance_name()
6666

67+
# Record the last stream ID that we were poked about so we can get
68+
# changes since then. We set this to the current max stream ID on
69+
# startup as every individual pusher will have checked for changes on
70+
# startup.
71+
self._last_room_stream_id_seen = self.store.get_room_max_stream_ordering()
72+
6773
# map from user id to app_id:pushkey to pusher
6874
self.pushers = {} # type: Dict[str, Dict[str, Union[HttpPusher, EmailPusher]]]
6975

@@ -178,20 +184,27 @@ async def remove_pushers_by_access_token(self, user_id, access_tokens):
178184
)
179185
await self.remove_pusher(p["app_id"], p["pushkey"], p["user_name"])
180186

181-
async def on_new_notifications(self, min_stream_id, max_stream_id):
187+
async def on_new_notifications(self, max_stream_id):
182188
if not self.pushers:
183189
# nothing to do here.
184190
return
185191

192+
if max_stream_id < self._last_room_stream_id_seen:
193+
# Nothing to do
194+
return
195+
196+
prev_stream_id = self._last_room_stream_id_seen
197+
self._last_room_stream_id_seen = max_stream_id
198+
186199
try:
187200
users_affected = await self.store.get_push_action_users_in_range(
188-
min_stream_id, max_stream_id
201+
prev_stream_id, max_stream_id
189202
)
190203

191204
for u in users_affected:
192205
if u in self.pushers:
193206
for p in self.pushers[u].values():
194-
p.on_new_notifications(min_stream_id, max_stream_id)
207+
p.on_new_notifications(max_stream_id)
195208

196209
except Exception:
197210
logger.exception("Exception in pusher on_new_notifications")

synapse/replication/tcp/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ async def on_rdata(
154154
max_token = self.store.get_room_max_stream_ordering()
155155
self.notifier.on_new_room_event(event, token, max_token, extra_users)
156156

157-
await self.pusher_pool.on_new_notifications(token, token)
157+
max_token = self.store.get_room_max_stream_ordering()
158+
await self.pusher_pool.on_new_notifications(max_token)
158159

159160
# Notify any waiting deferreds. The list is ordered by position so we
160161
# just iterate through the list until we reach a position that is

tests/handlers/test_typing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def make_homeserver(self, reactor, clock):
8080
"get_user_directory_stream_pos",
8181
"get_current_state_deltas",
8282
"get_device_updates_by_remote",
83+
"get_room_max_stream_ordering",
8384
]
8485
)
8586

0 commit comments

Comments
 (0)