Handle missing previous read marker event. (#15464)
If the previous read marker is pointing to an event that no longer exists
(e.g. due to retention) then assume that the newly given read marker
is newer.
2 files changed, 14 insertions, 10 deletions
diff --git a/synapse/handlers/read_marker.py b/synapse/handlers/read_marker.py
index 6d35e61880..49a497a860 100644
--- a/synapse/handlers/read_marker.py
+++ b/synapse/handlers/read_marker.py
@@ -16,6 +16,7 @@ import logging
from typing import TYPE_CHECKING
from synapse.api.constants import ReceiptTypes
+from synapse.api.errors import SynapseError
from synapse.util.async_helpers import Linearizer
if TYPE_CHECKING:
@@ -47,12 +48,21 @@ class ReadMarkerHandler:
)
should_update = True
+ # Get event ordering, this also ensures we know about the event
+ event_ordering = await self.store.get_event_ordering(event_id)
if existing_read_marker:
- # Only update if the new marker is ahead in the stream
- should_update = await self.store.is_event_after(
- event_id, existing_read_marker["event_id"]
- )
+ try:
+ old_event_ordering = await self.store.get_event_ordering(
+ existing_read_marker["event_id"]
+ )
+ except SynapseError:
+ # Old event no longer exists, assume new is ahead. This may
+ # happen if the old event was removed due to retention.
+ pass
+ else:
+ # Only update if the new marker is ahead in the stream
+ should_update = event_ordering > old_event_ordering
if should_update:
content = {"event_id": event_id}
diff --git a/synapse/storage/databases/main/events_worker.py b/synapse/storage/databases/main/events_worker.py
index 53aa5933d5..a39bc90974 100644
--- a/synapse/storage/databases/main/events_worker.py
+++ b/synapse/storage/databases/main/events_worker.py
@@ -1973,12 +1973,6 @@ class EventsWorkerStore(SQLBaseStore):
return rows, to_token, True
- async def is_event_after(self, event_id1: str, event_id2: str) -> bool:
- """Returns True if event_id1 is after event_id2 in the stream"""
- to_1, so_1 = await self.get_event_ordering(event_id1)
- to_2, so_2 = await self.get_event_ordering(event_id2)
- return (to_1, so_1) > (to_2, so_2)
-
@cached(max_entries=5000)
async def get_event_ordering(self, event_id: str) -> Tuple[int, int]:
res = await self.db_pool.simple_select_one(
|