mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-05 14:24:56 -04:00
Correctly handle unpersisted events when calculating auth chain difference. (#8827)
We do state res with unpersisted events when calculating the new current state of the room, so that should be the only thing impacted. I don't think this is tooooo big of a deal as: 1. the next time a state event happens in the room the current state should correct itself; 2. in the common case all the unpersisted events' auth events will be pulled in by other state, so will still return the correct result (or one which is sufficiently close to not affect the result); and 3. we mostly use the state at an event to do important operations, which isn't affected by this.
This commit is contained in:
parent
0fed46ebe5
commit
c5b6abd53d
4 changed files with 216 additions and 5 deletions
|
@ -24,7 +24,11 @@ from synapse.api.constants import EventTypes, JoinRules, Membership
|
|||
from synapse.api.room_versions import RoomVersions
|
||||
from synapse.event_auth import auth_types_for_event
|
||||
from synapse.events import make_event_from_dict
|
||||
from synapse.state.v2 import lexicographical_topological_sort, resolve_events_with_store
|
||||
from synapse.state.v2 import (
|
||||
_get_auth_chain_difference,
|
||||
lexicographical_topological_sort,
|
||||
resolve_events_with_store,
|
||||
)
|
||||
from synapse.types import EventID
|
||||
|
||||
from tests import unittest
|
||||
|
@ -587,6 +591,128 @@ class SimpleParamStateTestCase(unittest.TestCase):
|
|||
self.assert_dict(self.expected_combined_state, state)
|
||||
|
||||
|
||||
class AuthChainDifferenceTestCase(unittest.TestCase):
|
||||
"""We test that `_get_auth_chain_difference` correctly handles unpersisted
|
||||
events.
|
||||
"""
|
||||
|
||||
def test_simple(self):
|
||||
# Test getting the auth difference for a simple chain with a single
|
||||
# unpersisted event:
|
||||
#
|
||||
# Unpersisted | Persisted
|
||||
# |
|
||||
# C -|-> B -> A
|
||||
|
||||
a = FakeEvent(
|
||||
id="A", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([], [])
|
||||
|
||||
b = FakeEvent(
|
||||
id="B", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([a.event_id], [])
|
||||
|
||||
c = FakeEvent(
|
||||
id="C", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([b.event_id], [])
|
||||
|
||||
persisted_events = {a.event_id: a, b.event_id: b}
|
||||
unpersited_events = {c.event_id: c}
|
||||
|
||||
state_sets = [{"a": a.event_id, "b": b.event_id}, {"c": c.event_id}]
|
||||
|
||||
store = TestStateResolutionStore(persisted_events)
|
||||
|
||||
diff_d = _get_auth_chain_difference(state_sets, unpersited_events, store)
|
||||
difference = self.successResultOf(defer.ensureDeferred(diff_d))
|
||||
|
||||
self.assertEqual(difference, {c.event_id})
|
||||
|
||||
def test_multiple_unpersisted_chain(self):
|
||||
# Test getting the auth difference for a simple chain with multiple
|
||||
# unpersisted events:
|
||||
#
|
||||
# Unpersisted | Persisted
|
||||
# |
|
||||
# D -> C -|-> B -> A
|
||||
|
||||
a = FakeEvent(
|
||||
id="A", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([], [])
|
||||
|
||||
b = FakeEvent(
|
||||
id="B", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([a.event_id], [])
|
||||
|
||||
c = FakeEvent(
|
||||
id="C", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([b.event_id], [])
|
||||
|
||||
d = FakeEvent(
|
||||
id="D", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([c.event_id], [])
|
||||
|
||||
persisted_events = {a.event_id: a, b.event_id: b}
|
||||
unpersited_events = {c.event_id: c, d.event_id: d}
|
||||
|
||||
state_sets = [
|
||||
{"a": a.event_id, "b": b.event_id},
|
||||
{"c": c.event_id, "d": d.event_id},
|
||||
]
|
||||
|
||||
store = TestStateResolutionStore(persisted_events)
|
||||
|
||||
diff_d = _get_auth_chain_difference(state_sets, unpersited_events, store)
|
||||
difference = self.successResultOf(defer.ensureDeferred(diff_d))
|
||||
|
||||
self.assertEqual(difference, {d.event_id, c.event_id})
|
||||
|
||||
def test_unpersisted_events_different_sets(self):
|
||||
# Test getting the auth difference for with multiple unpersisted events
|
||||
# in different branches:
|
||||
#
|
||||
# Unpersisted | Persisted
|
||||
# |
|
||||
# D --> C -|-> B -> A
|
||||
# E ----^ -|---^
|
||||
# |
|
||||
|
||||
a = FakeEvent(
|
||||
id="A", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([], [])
|
||||
|
||||
b = FakeEvent(
|
||||
id="B", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([a.event_id], [])
|
||||
|
||||
c = FakeEvent(
|
||||
id="C", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([b.event_id], [])
|
||||
|
||||
d = FakeEvent(
|
||||
id="D", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([c.event_id], [])
|
||||
|
||||
e = FakeEvent(
|
||||
id="E", sender=ALICE, type=EventTypes.Member, state_key="", content={},
|
||||
).to_event([c.event_id, b.event_id], [])
|
||||
|
||||
persisted_events = {a.event_id: a, b.event_id: b}
|
||||
unpersited_events = {c.event_id: c, d.event_id: d, e.event_id: e}
|
||||
|
||||
state_sets = [
|
||||
{"a": a.event_id, "b": b.event_id, "e": e.event_id},
|
||||
{"c": c.event_id, "d": d.event_id},
|
||||
]
|
||||
|
||||
store = TestStateResolutionStore(persisted_events)
|
||||
|
||||
diff_d = _get_auth_chain_difference(state_sets, unpersited_events, store)
|
||||
difference = self.successResultOf(defer.ensureDeferred(diff_d))
|
||||
|
||||
self.assertEqual(difference, {d.event_id, e.event_id})
|
||||
|
||||
|
||||
def pairwise(iterable):
|
||||
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
|
||||
a, b = itertools.tee(iterable)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue