mirror of
https://github.com/element-hq/synapse.git
synced 2024-11-29 07:28:55 +03:00
Consider the origin_server_ts
of the m.space.child
event when ordering rooms. (#10730)
This updates the ordering of the returned events from the spaces summary API to that defined in MSC2946 (which updates MSC1772). Previously a step was skipped causing ordering to be inconsistent with clients.
This commit is contained in:
parent
d1f1b46c2c
commit
6258730ebe
3 changed files with 22 additions and 12 deletions
1
changelog.d/10730.bugfix
Normal file
1
changelog.d/10730.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix a bug where the ordering algorithm was skipping the `origin_server_ts` step in the spaces summary resulting in unstable room orderings.
|
|
@ -1139,25 +1139,26 @@ def _is_suggested_child_event(edge_event: EventBase) -> bool:
|
||||||
_INVALID_ORDER_CHARS_RE = re.compile(r"[^\x20-\x7E]")
|
_INVALID_ORDER_CHARS_RE = re.compile(r"[^\x20-\x7E]")
|
||||||
|
|
||||||
|
|
||||||
def _child_events_comparison_key(child: EventBase) -> Tuple[bool, Optional[str], str]:
|
def _child_events_comparison_key(
|
||||||
|
child: EventBase,
|
||||||
|
) -> Tuple[bool, Optional[str], int, str]:
|
||||||
"""
|
"""
|
||||||
Generate a value for comparing two child events for ordering.
|
Generate a value for comparing two child events for ordering.
|
||||||
|
|
||||||
The rules for ordering are supposed to be:
|
The rules for ordering are:
|
||||||
|
|
||||||
1. The 'order' key, if it is valid.
|
1. The 'order' key, if it is valid.
|
||||||
2. The 'origin_server_ts' of the 'm.room.create' event.
|
2. The 'origin_server_ts' of the 'm.space.child' event.
|
||||||
3. The 'room_id'.
|
3. The 'room_id'.
|
||||||
|
|
||||||
But we skip step 2 since we may not have any state from the room.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
child: The event for generating a comparison key.
|
child: The event for generating a comparison key.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The comparison key as a tuple of:
|
The comparison key as a tuple of:
|
||||||
False if the ordering is valid.
|
False if the ordering is valid.
|
||||||
The ordering field.
|
The 'order' field or None if it is not given or invalid.
|
||||||
|
The 'origin_server_ts' field.
|
||||||
The room ID.
|
The room ID.
|
||||||
"""
|
"""
|
||||||
order = child.content.get("order")
|
order = child.content.get("order")
|
||||||
|
@ -1168,4 +1169,4 @@ def _child_events_comparison_key(child: EventBase) -> Tuple[bool, Optional[str],
|
||||||
order = None
|
order = None
|
||||||
|
|
||||||
# Items without an order come last.
|
# Items without an order come last.
|
||||||
return (order is None, order, child.room_id)
|
return (order is None, order, child.origin_server_ts, child.room_id)
|
||||||
|
|
|
@ -35,10 +35,11 @@ from synapse.types import JsonDict, UserID
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
|
||||||
|
|
||||||
def _create_event(room_id: str, order: Optional[Any] = None):
|
def _create_event(room_id: str, order: Optional[Any] = None, origin_server_ts: int = 0):
|
||||||
result = mock.Mock()
|
result = mock.Mock(name=room_id)
|
||||||
result.room_id = room_id
|
result.room_id = room_id
|
||||||
result.content = {}
|
result.content = {}
|
||||||
|
result.origin_server_ts = origin_server_ts
|
||||||
if order is not None:
|
if order is not None:
|
||||||
result.content["order"] = order
|
result.content["order"] = order
|
||||||
return result
|
return result
|
||||||
|
@ -63,10 +64,17 @@ class TestSpaceSummarySort(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual([ev2, ev1], _order(ev1, ev2))
|
self.assertEqual([ev2, ev1], _order(ev1, ev2))
|
||||||
|
|
||||||
|
def test_order_origin_server_ts(self):
|
||||||
|
"""Origin server is a tie-breaker for ordering."""
|
||||||
|
ev1 = _create_event("!abc:test", origin_server_ts=10)
|
||||||
|
ev2 = _create_event("!xyz:test", origin_server_ts=30)
|
||||||
|
|
||||||
|
self.assertEqual([ev1, ev2], _order(ev1, ev2))
|
||||||
|
|
||||||
def test_order_room_id(self):
|
def test_order_room_id(self):
|
||||||
"""Room ID is a tie-breaker for ordering."""
|
"""Room ID is a final tie-breaker for ordering."""
|
||||||
ev1 = _create_event("!abc:test", "abc")
|
ev1 = _create_event("!abc:test")
|
||||||
ev2 = _create_event("!xyz:test", "abc")
|
ev2 = _create_event("!xyz:test")
|
||||||
|
|
||||||
self.assertEqual([ev1, ev2], _order(ev1, ev2))
|
self.assertEqual([ev1, ev2], _order(ev1, ev2))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue