From 99b481ea6cfec6f1193922a81076e5d89e3ae61e Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 7 Jun 2021 10:25:58 +0100 Subject: [PATCH 1/4] Handle /backfill returning no events Fixes #10123 --- synapse/handlers/federation.py | 38 ++++++++++++------- synapse/util/linked_list.py | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 synapse/util/linked_list.py diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index b802822baaa2..abbb71424d7d 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -22,6 +22,7 @@ from http import HTTPStatus from typing import ( TYPE_CHECKING, + Collection, Dict, Iterable, List, @@ -1364,11 +1365,12 @@ async def get_event(event_id: str): event_infos.append(_NewEventInfo(event, None, auth)) - await self._auth_and_persist_events( - destination, - room_id, - event_infos, - ) + if event_infos: + await self._auth_and_persist_events( + destination, + room_id, + event_infos, + ) def _sanity_check_event(self, ev: EventBase) -> None: """ @@ -2077,7 +2079,7 @@ async def _auth_and_persist_events( self, origin: str, room_id: str, - event_infos: Iterable[_NewEventInfo], + event_infos: Collection[_NewEventInfo], backfilled: bool = False, ) -> None: """Creates the appropriate contexts and persists events. The events @@ -2088,6 +2090,9 @@ async def _auth_and_persist_events( Notifies about the events where appropriate. """ + if not event_infos: + return + async def prep(ev_info: _NewEventInfo): event = ev_info.event with nested_logging_context(suffix=event.event_id): @@ -2216,13 +2221,14 @@ async def _persist_auth_tree( raise events_to_context[e.event_id].rejected = RejectedReason.AUTH_ERROR - await self.persist_events_and_notify( - room_id, - [ - (e, events_to_context[e.event_id]) - for e in itertools.chain(auth_events, state) - ], - ) + if auth_events or state: + await self.persist_events_and_notify( + room_id, + [ + (e, events_to_context[e.event_id]) + for e in itertools.chain(auth_events, state) + ], + ) new_event_context = await self.state_handler.compute_event_context( event, old_state=state @@ -3061,7 +3067,13 @@ async def persist_events_and_notify( the same room. backfilled: Whether these events are a result of backfilling or not + + Returns: + The stream ID after which all events have been persisted. """ + if not event_and_contexts: + return self.store.get_current_events_token() + instance = self.config.worker.events_shard_config.get_instance(room_id) if instance != self._instance_name: # Limit the number of events sent over replication. We choose 200 diff --git a/synapse/util/linked_list.py b/synapse/util/linked_list.py new file mode 100644 index 000000000000..1f1dbd56b4cb --- /dev/null +++ b/synapse/util/linked_list.py @@ -0,0 +1,68 @@ +# Copyright 2021 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import logging +from typing import Generic, Optional, Protocol, TypeVar + +import attr + +logger = logging.getLogger(__name__) + + +class ListValue(Protocol): + def drop(self) -> None: + ... + + +V = TypeVar("V", bound=ListValue) + + +@attr.s(slots=True, auto_attribs=True) +class _ListNode(Generic[V]): + value: Optional[V] = None + prev_node: "_ListNode" = attr.Factory(lambda self: self, takes_self=True) + next_node: "_ListNode" = attr.Factory(lambda self: self, takes_self=True) + + def delete_from_cache(self) -> None: + if self.value is None: + logger.warning("Tried delete list node from cache twice.") + return + + self.value.drop() + + def remove_from_list(self) -> None: + prev_node = self.prev_node + next_node = self.next_node + prev_node.next_node = next_node + next_node.prev_node = prev_node + + self.value = None + + def move_node_to_front(self, list_root: "_ListNode") -> None: + self.remove_from_list() + + prev_node = list_root + next_node = prev_node.next_node + + self.prev_node = prev_node + self.next_node = next_node + + prev_node.next_node = self + next_node.prev_node = self + + +@attr.s(slots=True) +class LinkedList(Generic[V]): + root: _ListNode[V] = attr.Factory(_ListNode) From abdadb52ac4fcca1e3c10a8bfe8245e0d5dee8f0 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 7 Jun 2021 10:33:20 +0100 Subject: [PATCH 2/4] Newsfile --- changelog.d/10133.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/10133.bugfix diff --git a/changelog.d/10133.bugfix b/changelog.d/10133.bugfix new file mode 100644 index 000000000000..c0474727b957 --- /dev/null +++ b/changelog.d/10133.bugfix @@ -0,0 +1 @@ +Fix bug when using workers where pagination requests failed if a remote server returned zero events from `/backfill`. From 862657b301a8978f0f2fd7d1615e8bfa27cdb200 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 7 Jun 2021 12:34:27 +0100 Subject: [PATCH 3/4] Remove file --- synapse/util/linked_list.py | 68 ------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 synapse/util/linked_list.py diff --git a/synapse/util/linked_list.py b/synapse/util/linked_list.py deleted file mode 100644 index 1f1dbd56b4cb..000000000000 --- a/synapse/util/linked_list.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2021 The Matrix.org Foundation C.I.C. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import logging -from typing import Generic, Optional, Protocol, TypeVar - -import attr - -logger = logging.getLogger(__name__) - - -class ListValue(Protocol): - def drop(self) -> None: - ... - - -V = TypeVar("V", bound=ListValue) - - -@attr.s(slots=True, auto_attribs=True) -class _ListNode(Generic[V]): - value: Optional[V] = None - prev_node: "_ListNode" = attr.Factory(lambda self: self, takes_self=True) - next_node: "_ListNode" = attr.Factory(lambda self: self, takes_self=True) - - def delete_from_cache(self) -> None: - if self.value is None: - logger.warning("Tried delete list node from cache twice.") - return - - self.value.drop() - - def remove_from_list(self) -> None: - prev_node = self.prev_node - next_node = self.next_node - prev_node.next_node = next_node - next_node.prev_node = prev_node - - self.value = None - - def move_node_to_front(self, list_root: "_ListNode") -> None: - self.remove_from_list() - - prev_node = list_root - next_node = prev_node.next_node - - self.prev_node = prev_node - self.next_node = next_node - - prev_node.next_node = self - next_node.prev_node = self - - -@attr.s(slots=True) -class LinkedList(Generic[V]): - root: _ListNode[V] = attr.Factory(_ListNode) From 2310c76fd65f6205d7f3dfc4883d8755de6277e6 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Mon, 7 Jun 2021 12:35:45 +0100 Subject: [PATCH 4/4] Newsfile --- changelog.d/10133.bugfix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/10133.bugfix b/changelog.d/10133.bugfix index c0474727b957..a62c15b260a1 100644 --- a/changelog.d/10133.bugfix +++ b/changelog.d/10133.bugfix @@ -1 +1 @@ -Fix bug when using workers where pagination requests failed if a remote server returned zero events from `/backfill`. +Fix bug when using workers where pagination requests failed if a remote server returned zero events from `/backfill`. Introduced in 1.35.0.