test_state.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014-2016 OpenMarket Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. from typing import List, Optional
  16. from unittest.mock import Mock
  17. from twisted.internet import defer
  18. from synapse.api.auth import Auth
  19. from synapse.api.constants import EventTypes, Membership
  20. from synapse.api.room_versions import RoomVersions
  21. from synapse.events import make_event_from_dict
  22. from synapse.events.snapshot import EventContext
  23. from synapse.state import StateHandler, StateResolutionHandler
  24. from tests import unittest
  25. from .utils import MockClock, default_config
  26. _next_event_id = 1000
  27. def create_event(
  28. name=None,
  29. type=None,
  30. state_key=None,
  31. depth=2,
  32. event_id=None,
  33. prev_events: Optional[List[str]] = None,
  34. **kwargs,
  35. ):
  36. global _next_event_id
  37. if not event_id:
  38. _next_event_id += 1
  39. event_id = "$%s:test" % (_next_event_id,)
  40. if not name:
  41. if state_key is not None:
  42. name = "<%s-%s, %s>" % (type, state_key, event_id)
  43. else:
  44. name = "<%s, %s>" % (type, event_id)
  45. d = {
  46. "event_id": event_id,
  47. "type": type,
  48. "sender": "@user_id:example.com",
  49. "room_id": "!room_id:example.com",
  50. "depth": depth,
  51. "prev_events": prev_events or [],
  52. }
  53. if state_key is not None:
  54. d["state_key"] = state_key
  55. d.update(kwargs)
  56. event = make_event_from_dict(d)
  57. return event
  58. class StateGroupStore:
  59. def __init__(self):
  60. self._event_to_state_group = {}
  61. self._group_to_state = {}
  62. self._event_id_to_event = {}
  63. self._next_group = 1
  64. async def get_state_groups_ids(self, room_id, event_ids):
  65. groups = {}
  66. for event_id in event_ids:
  67. group = self._event_to_state_group.get(event_id)
  68. if group:
  69. groups[group] = self._group_to_state[group]
  70. return groups
  71. async def store_state_group(
  72. self, event_id, room_id, prev_group, delta_ids, current_state_ids
  73. ):
  74. state_group = self._next_group
  75. self._next_group += 1
  76. self._group_to_state[state_group] = dict(current_state_ids)
  77. return state_group
  78. async def get_events(self, event_ids, **kwargs):
  79. return {
  80. e_id: self._event_id_to_event[e_id]
  81. for e_id in event_ids
  82. if e_id in self._event_id_to_event
  83. }
  84. async def get_state_group_delta(self, name):
  85. return (None, None)
  86. def register_events(self, events):
  87. for e in events:
  88. self._event_id_to_event[e.event_id] = e
  89. def register_event_context(self, event, context):
  90. self._event_to_state_group[event.event_id] = context.state_group
  91. def register_event_id_state_group(self, event_id, state_group):
  92. self._event_to_state_group[event_id] = state_group
  93. async def get_room_version_id(self, room_id):
  94. return RoomVersions.V1.identifier
  95. class DictObj(dict):
  96. def __init__(self, **kwargs):
  97. super().__init__(kwargs)
  98. self.__dict__ = self
  99. class Graph:
  100. def __init__(self, nodes, edges):
  101. events = {}
  102. clobbered = set(events.keys())
  103. for event_id, fields in nodes.items():
  104. refs = edges.get(event_id)
  105. if refs:
  106. clobbered.difference_update(refs)
  107. prev_events = [(r, {}) for r in refs]
  108. else:
  109. prev_events = []
  110. events[event_id] = create_event(
  111. event_id=event_id, prev_events=prev_events, **fields
  112. )
  113. self._leaves = clobbered
  114. self._events = sorted(events.values(), key=lambda e: e.depth)
  115. def walk(self):
  116. return iter(self._events)
  117. def get_leaves(self):
  118. return (self._events[i] for i in self._leaves)
  119. class StateTestCase(unittest.TestCase):
  120. def setUp(self):
  121. self.store = StateGroupStore()
  122. storage = Mock(main=self.store, state=self.store)
  123. hs = Mock(
  124. spec_set=[
  125. "config",
  126. "get_datastore",
  127. "get_storage",
  128. "get_auth",
  129. "get_state_handler",
  130. "get_clock",
  131. "get_state_resolution_handler",
  132. "hostname",
  133. ]
  134. )
  135. hs.config = default_config("tesths", True)
  136. hs.get_datastore.return_value = self.store
  137. hs.get_state_handler.return_value = None
  138. hs.get_clock.return_value = MockClock()
  139. hs.get_auth.return_value = Auth(hs)
  140. hs.get_state_resolution_handler = lambda: StateResolutionHandler(hs)
  141. hs.get_storage.return_value = storage
  142. self.state = StateHandler(hs)
  143. self.event_id = 0
  144. @defer.inlineCallbacks
  145. def test_branch_no_conflict(self):
  146. graph = Graph(
  147. nodes={
  148. "START": DictObj(
  149. type=EventTypes.Create, state_key="", content={}, depth=1
  150. ),
  151. "A": DictObj(type=EventTypes.Message, depth=2),
  152. "B": DictObj(type=EventTypes.Message, depth=3),
  153. "C": DictObj(type=EventTypes.Name, state_key="", depth=3),
  154. "D": DictObj(type=EventTypes.Message, depth=4),
  155. },
  156. edges={"A": ["START"], "B": ["A"], "C": ["A"], "D": ["B", "C"]},
  157. )
  158. self.store.register_events(graph.walk())
  159. context_store = {} # type: dict[str, EventContext]
  160. for event in graph.walk():
  161. context = yield defer.ensureDeferred(
  162. self.state.compute_event_context(event)
  163. )
  164. self.store.register_event_context(event, context)
  165. context_store[event.event_id] = context
  166. ctx_c = context_store["C"]
  167. ctx_d = context_store["D"]
  168. prev_state_ids = yield defer.ensureDeferred(ctx_d.get_prev_state_ids())
  169. self.assertEqual(2, len(prev_state_ids))
  170. self.assertEqual(ctx_c.state_group, ctx_d.state_group_before_event)
  171. self.assertEqual(ctx_d.state_group_before_event, ctx_d.state_group)
  172. @defer.inlineCallbacks
  173. def test_branch_basic_conflict(self):
  174. graph = Graph(
  175. nodes={
  176. "START": DictObj(
  177. type=EventTypes.Create,
  178. state_key="",
  179. content={"creator": "@user_id:example.com"},
  180. depth=1,
  181. ),
  182. "A": DictObj(
  183. type=EventTypes.Member,
  184. state_key="@user_id:example.com",
  185. content={"membership": Membership.JOIN},
  186. membership=Membership.JOIN,
  187. depth=2,
  188. ),
  189. "B": DictObj(type=EventTypes.Name, state_key="", depth=3),
  190. "C": DictObj(type=EventTypes.Name, state_key="", depth=4),
  191. "D": DictObj(type=EventTypes.Message, depth=5),
  192. },
  193. edges={"A": ["START"], "B": ["A"], "C": ["A"], "D": ["B", "C"]},
  194. )
  195. self.store.register_events(graph.walk())
  196. context_store = {}
  197. for event in graph.walk():
  198. context = yield defer.ensureDeferred(
  199. self.state.compute_event_context(event)
  200. )
  201. self.store.register_event_context(event, context)
  202. context_store[event.event_id] = context
  203. # C ends up winning the resolution between B and C
  204. ctx_c = context_store["C"]
  205. ctx_d = context_store["D"]
  206. prev_state_ids = yield defer.ensureDeferred(ctx_d.get_prev_state_ids())
  207. self.assertSetEqual({"START", "A", "C"}, set(prev_state_ids.values()))
  208. self.assertEqual(ctx_c.state_group, ctx_d.state_group_before_event)
  209. self.assertEqual(ctx_d.state_group_before_event, ctx_d.state_group)
  210. @defer.inlineCallbacks
  211. def test_branch_have_banned_conflict(self):
  212. graph = Graph(
  213. nodes={
  214. "START": DictObj(
  215. type=EventTypes.Create,
  216. state_key="",
  217. content={"creator": "@user_id:example.com"},
  218. depth=1,
  219. ),
  220. "A": DictObj(
  221. type=EventTypes.Member,
  222. state_key="@user_id:example.com",
  223. content={"membership": Membership.JOIN},
  224. membership=Membership.JOIN,
  225. depth=2,
  226. ),
  227. "B": DictObj(type=EventTypes.Name, state_key="", depth=3),
  228. "C": DictObj(
  229. type=EventTypes.Member,
  230. state_key="@user_id_2:example.com",
  231. content={"membership": Membership.BAN},
  232. membership=Membership.BAN,
  233. depth=4,
  234. ),
  235. "D": DictObj(
  236. type=EventTypes.Name,
  237. state_key="",
  238. depth=4,
  239. sender="@user_id_2:example.com",
  240. ),
  241. "E": DictObj(type=EventTypes.Message, depth=5),
  242. },
  243. edges={"A": ["START"], "B": ["A"], "C": ["B"], "D": ["B"], "E": ["C", "D"]},
  244. )
  245. self.store.register_events(graph.walk())
  246. context_store = {}
  247. for event in graph.walk():
  248. context = yield defer.ensureDeferred(
  249. self.state.compute_event_context(event)
  250. )
  251. self.store.register_event_context(event, context)
  252. context_store[event.event_id] = context
  253. # C ends up winning the resolution between C and D because bans win over other
  254. # changes
  255. ctx_c = context_store["C"]
  256. ctx_e = context_store["E"]
  257. prev_state_ids = yield defer.ensureDeferred(ctx_e.get_prev_state_ids())
  258. self.assertSetEqual({"START", "A", "B", "C"}, set(prev_state_ids.values()))
  259. self.assertEqual(ctx_c.state_group, ctx_e.state_group_before_event)
  260. self.assertEqual(ctx_e.state_group_before_event, ctx_e.state_group)
  261. @defer.inlineCallbacks
  262. def test_branch_have_perms_conflict(self):
  263. userid1 = "@user_id:example.com"
  264. userid2 = "@user_id2:example.com"
  265. nodes = {
  266. "A1": DictObj(
  267. type=EventTypes.Create,
  268. state_key="",
  269. content={"creator": userid1},
  270. depth=1,
  271. ),
  272. "A2": DictObj(
  273. type=EventTypes.Member,
  274. state_key=userid1,
  275. content={"membership": Membership.JOIN},
  276. membership=Membership.JOIN,
  277. ),
  278. "A3": DictObj(
  279. type=EventTypes.Member,
  280. state_key=userid2,
  281. content={"membership": Membership.JOIN},
  282. membership=Membership.JOIN,
  283. ),
  284. "A4": DictObj(
  285. type=EventTypes.PowerLevels,
  286. state_key="",
  287. content={
  288. "events": {"m.room.name": 50},
  289. "users": {userid1: 100, userid2: 60},
  290. },
  291. ),
  292. "A5": DictObj(type=EventTypes.Name, state_key=""),
  293. "B": DictObj(
  294. type=EventTypes.PowerLevels,
  295. state_key="",
  296. content={"events": {"m.room.name": 50}, "users": {userid2: 30}},
  297. ),
  298. "C": DictObj(type=EventTypes.Name, state_key="", sender=userid2),
  299. "D": DictObj(type=EventTypes.Message),
  300. }
  301. edges = {
  302. "A2": ["A1"],
  303. "A3": ["A2"],
  304. "A4": ["A3"],
  305. "A5": ["A4"],
  306. "B": ["A5"],
  307. "C": ["A5"],
  308. "D": ["B", "C"],
  309. }
  310. self._add_depths(nodes, edges)
  311. graph = Graph(nodes, edges)
  312. self.store.register_events(graph.walk())
  313. context_store = {}
  314. for event in graph.walk():
  315. context = yield defer.ensureDeferred(
  316. self.state.compute_event_context(event)
  317. )
  318. self.store.register_event_context(event, context)
  319. context_store[event.event_id] = context
  320. # B ends up winning the resolution between B and C because power levels
  321. # win over other changes.
  322. ctx_b = context_store["B"]
  323. ctx_d = context_store["D"]
  324. prev_state_ids = yield defer.ensureDeferred(ctx_d.get_prev_state_ids())
  325. self.assertSetEqual({"A1", "A2", "A3", "A5", "B"}, set(prev_state_ids.values()))
  326. self.assertEqual(ctx_b.state_group, ctx_d.state_group_before_event)
  327. self.assertEqual(ctx_d.state_group_before_event, ctx_d.state_group)
  328. def _add_depths(self, nodes, edges):
  329. def _get_depth(ev):
  330. node = nodes[ev]
  331. if "depth" not in node:
  332. prevs = edges[ev]
  333. depth = max(_get_depth(prev) for prev in prevs) + 1
  334. node["depth"] = depth
  335. return node["depth"]
  336. for n in nodes:
  337. _get_depth(n)
  338. @defer.inlineCallbacks
  339. def test_annotate_with_old_message(self):
  340. event = create_event(type="test_message", name="event")
  341. old_state = [
  342. create_event(type="test1", state_key="1"),
  343. create_event(type="test1", state_key="2"),
  344. create_event(type="test2", state_key=""),
  345. ]
  346. context = yield defer.ensureDeferred(
  347. self.state.compute_event_context(event, old_state=old_state)
  348. )
  349. prev_state_ids = yield defer.ensureDeferred(context.get_prev_state_ids())
  350. self.assertCountEqual((e.event_id for e in old_state), prev_state_ids.values())
  351. current_state_ids = yield defer.ensureDeferred(context.get_current_state_ids())
  352. self.assertCountEqual(
  353. (e.event_id for e in old_state), current_state_ids.values()
  354. )
  355. self.assertIsNotNone(context.state_group_before_event)
  356. self.assertEqual(context.state_group_before_event, context.state_group)
  357. @defer.inlineCallbacks
  358. def test_annotate_with_old_state(self):
  359. event = create_event(type="state", state_key="", name="event")
  360. old_state = [
  361. create_event(type="test1", state_key="1"),
  362. create_event(type="test1", state_key="2"),
  363. create_event(type="test2", state_key=""),
  364. ]
  365. context = yield defer.ensureDeferred(
  366. self.state.compute_event_context(event, old_state=old_state)
  367. )
  368. prev_state_ids = yield defer.ensureDeferred(context.get_prev_state_ids())
  369. self.assertCountEqual((e.event_id for e in old_state), prev_state_ids.values())
  370. current_state_ids = yield defer.ensureDeferred(context.get_current_state_ids())
  371. self.assertCountEqual(
  372. (e.event_id for e in old_state + [event]), current_state_ids.values()
  373. )
  374. self.assertIsNotNone(context.state_group_before_event)
  375. self.assertNotEqual(context.state_group_before_event, context.state_group)
  376. self.assertEqual(context.state_group_before_event, context.prev_group)
  377. self.assertEqual({("state", ""): event.event_id}, context.delta_ids)
  378. @defer.inlineCallbacks
  379. def test_trivial_annotate_message(self):
  380. prev_event_id = "prev_event_id"
  381. event = create_event(
  382. type="test_message", name="event2", prev_events=[(prev_event_id, {})]
  383. )
  384. old_state = [
  385. create_event(type="test1", state_key="1"),
  386. create_event(type="test1", state_key="2"),
  387. create_event(type="test2", state_key=""),
  388. ]
  389. group_name = yield defer.ensureDeferred(
  390. self.store.store_state_group(
  391. prev_event_id,
  392. event.room_id,
  393. None,
  394. None,
  395. {(e.type, e.state_key): e.event_id for e in old_state},
  396. )
  397. )
  398. self.store.register_event_id_state_group(prev_event_id, group_name)
  399. context = yield defer.ensureDeferred(self.state.compute_event_context(event))
  400. current_state_ids = yield defer.ensureDeferred(context.get_current_state_ids())
  401. self.assertEqual(
  402. {e.event_id for e in old_state}, set(current_state_ids.values())
  403. )
  404. self.assertEqual(group_name, context.state_group)
  405. @defer.inlineCallbacks
  406. def test_trivial_annotate_state(self):
  407. prev_event_id = "prev_event_id"
  408. event = create_event(
  409. type="state", state_key="", name="event2", prev_events=[(prev_event_id, {})]
  410. )
  411. old_state = [
  412. create_event(type="test1", state_key="1"),
  413. create_event(type="test1", state_key="2"),
  414. create_event(type="test2", state_key=""),
  415. ]
  416. group_name = yield defer.ensureDeferred(
  417. self.store.store_state_group(
  418. prev_event_id,
  419. event.room_id,
  420. None,
  421. None,
  422. {(e.type, e.state_key): e.event_id for e in old_state},
  423. )
  424. )
  425. self.store.register_event_id_state_group(prev_event_id, group_name)
  426. context = yield defer.ensureDeferred(self.state.compute_event_context(event))
  427. prev_state_ids = yield defer.ensureDeferred(context.get_prev_state_ids())
  428. self.assertEqual({e.event_id for e in old_state}, set(prev_state_ids.values()))
  429. self.assertIsNotNone(context.state_group)
  430. @defer.inlineCallbacks
  431. def test_resolve_message_conflict(self):
  432. prev_event_id1 = "event_id1"
  433. prev_event_id2 = "event_id2"
  434. event = create_event(
  435. type="test_message",
  436. name="event3",
  437. prev_events=[(prev_event_id1, {}), (prev_event_id2, {})],
  438. )
  439. creation = create_event(type=EventTypes.Create, state_key="")
  440. old_state_1 = [
  441. creation,
  442. create_event(type="test1", state_key="1"),
  443. create_event(type="test1", state_key="2"),
  444. create_event(type="test2", state_key=""),
  445. ]
  446. old_state_2 = [
  447. creation,
  448. create_event(type="test1", state_key="1"),
  449. create_event(type="test3", state_key="2"),
  450. create_event(type="test4", state_key=""),
  451. ]
  452. self.store.register_events(old_state_1)
  453. self.store.register_events(old_state_2)
  454. context = yield self._get_context(
  455. event, prev_event_id1, old_state_1, prev_event_id2, old_state_2
  456. )
  457. current_state_ids = yield defer.ensureDeferred(context.get_current_state_ids())
  458. self.assertEqual(len(current_state_ids), 6)
  459. self.assertIsNotNone(context.state_group)
  460. @defer.inlineCallbacks
  461. def test_resolve_state_conflict(self):
  462. prev_event_id1 = "event_id1"
  463. prev_event_id2 = "event_id2"
  464. event = create_event(
  465. type="test4",
  466. state_key="",
  467. name="event",
  468. prev_events=[(prev_event_id1, {}), (prev_event_id2, {})],
  469. )
  470. creation = create_event(type=EventTypes.Create, state_key="")
  471. old_state_1 = [
  472. creation,
  473. create_event(type="test1", state_key="1"),
  474. create_event(type="test1", state_key="2"),
  475. create_event(type="test2", state_key=""),
  476. ]
  477. old_state_2 = [
  478. creation,
  479. create_event(type="test1", state_key="1"),
  480. create_event(type="test3", state_key="2"),
  481. create_event(type="test4", state_key=""),
  482. ]
  483. store = StateGroupStore()
  484. store.register_events(old_state_1)
  485. store.register_events(old_state_2)
  486. self.store.get_events = store.get_events
  487. context = yield self._get_context(
  488. event, prev_event_id1, old_state_1, prev_event_id2, old_state_2
  489. )
  490. current_state_ids = yield defer.ensureDeferred(context.get_current_state_ids())
  491. self.assertEqual(len(current_state_ids), 6)
  492. self.assertIsNotNone(context.state_group)
  493. @defer.inlineCallbacks
  494. def test_standard_depth_conflict(self):
  495. prev_event_id1 = "event_id1"
  496. prev_event_id2 = "event_id2"
  497. event = create_event(
  498. type="test4",
  499. name="event",
  500. prev_events=[(prev_event_id1, {}), (prev_event_id2, {})],
  501. )
  502. member_event = create_event(
  503. type=EventTypes.Member,
  504. state_key="@user_id:example.com",
  505. content={"membership": Membership.JOIN},
  506. )
  507. power_levels = create_event(
  508. type=EventTypes.PowerLevels,
  509. state_key="",
  510. content={"users": {"@foo:bar": "100", "@user_id:example.com": "100"}},
  511. )
  512. creation = create_event(
  513. type=EventTypes.Create, state_key="", content={"creator": "@foo:bar"}
  514. )
  515. old_state_1 = [
  516. creation,
  517. power_levels,
  518. member_event,
  519. create_event(type="test1", state_key="1", depth=1),
  520. ]
  521. old_state_2 = [
  522. creation,
  523. power_levels,
  524. member_event,
  525. create_event(type="test1", state_key="1", depth=2),
  526. ]
  527. store = StateGroupStore()
  528. store.register_events(old_state_1)
  529. store.register_events(old_state_2)
  530. self.store.get_events = store.get_events
  531. context = yield self._get_context(
  532. event, prev_event_id1, old_state_1, prev_event_id2, old_state_2
  533. )
  534. current_state_ids = yield defer.ensureDeferred(context.get_current_state_ids())
  535. self.assertEqual(old_state_2[3].event_id, current_state_ids[("test1", "1")])
  536. # Reverse the depth to make sure we are actually using the depths
  537. # during state resolution.
  538. old_state_1 = [
  539. creation,
  540. power_levels,
  541. member_event,
  542. create_event(type="test1", state_key="1", depth=2),
  543. ]
  544. old_state_2 = [
  545. creation,
  546. power_levels,
  547. member_event,
  548. create_event(type="test1", state_key="1", depth=1),
  549. ]
  550. store.register_events(old_state_1)
  551. store.register_events(old_state_2)
  552. context = yield self._get_context(
  553. event, prev_event_id1, old_state_1, prev_event_id2, old_state_2
  554. )
  555. current_state_ids = yield defer.ensureDeferred(context.get_current_state_ids())
  556. self.assertEqual(old_state_1[3].event_id, current_state_ids[("test1", "1")])
  557. @defer.inlineCallbacks
  558. def _get_context(
  559. self, event, prev_event_id_1, old_state_1, prev_event_id_2, old_state_2
  560. ):
  561. sg1 = yield defer.ensureDeferred(
  562. self.store.store_state_group(
  563. prev_event_id_1,
  564. event.room_id,
  565. None,
  566. None,
  567. {(e.type, e.state_key): e.event_id for e in old_state_1},
  568. )
  569. )
  570. self.store.register_event_id_state_group(prev_event_id_1, sg1)
  571. sg2 = yield defer.ensureDeferred(
  572. self.store.store_state_group(
  573. prev_event_id_2,
  574. event.room_id,
  575. None,
  576. None,
  577. {(e.type, e.state_key): e.event_id for e in old_state_2},
  578. )
  579. )
  580. self.store.register_event_id_state_group(prev_event_id_2, sg2)
  581. result = yield defer.ensureDeferred(self.state.compute_event_context(event))
  582. return result