Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 4c6a31c

Browse files
committed
Calculate the forward extremeties once
1 parent 09eb08f commit 4c6a31c

File tree

2 files changed

+92
-126
lines changed

2 files changed

+92
-126
lines changed

synapse/storage/event_federation.py

Lines changed: 6 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -235,80 +235,21 @@ def _handle_mult_prev_events(self, txn, events):
235235
],
236236
)
237237

238-
self._update_extremeties(txn, events)
238+
self._update_backward_extremeties(txn, events)
239239

240-
def _update_extremeties(self, txn, events):
241-
"""Updates the event_*_extremities tables based on the new/updated
240+
def _update_backward_extremeties(self, txn, events):
241+
"""Updates the event_backward_extremities tables based on the new/updated
242242
events being persisted.
243243
244244
This is called for new events *and* for events that were outliers, but
245-
are are now being persisted as non-outliers.
245+
are now being persisted as non-outliers.
246+
247+
Forward extremities are handled when we first start persisting the events.
246248
"""
247249
events_by_room = {}
248250
for ev in events:
249251
events_by_room.setdefault(ev.room_id, []).append(ev)
250252

251-
for room_id, room_events in events_by_room.items():
252-
prevs = [
253-
e_id for ev in room_events for e_id, _ in ev.prev_events
254-
if not ev.internal_metadata.is_outlier()
255-
]
256-
if prevs:
257-
txn.execute(
258-
"DELETE FROM event_forward_extremities"
259-
" WHERE room_id = ?"
260-
" AND event_id in (%s)" % (
261-
",".join(["?"] * len(prevs)),
262-
),
263-
[room_id] + prevs,
264-
)
265-
266-
query = (
267-
"INSERT INTO event_forward_extremities (event_id, room_id)"
268-
" SELECT ?, ? WHERE NOT EXISTS ("
269-
" SELECT 1 FROM event_edges WHERE prev_event_id = ?"
270-
" )"
271-
)
272-
273-
txn.executemany(
274-
query,
275-
[
276-
(ev.event_id, ev.room_id, ev.event_id) for ev in events
277-
if not ev.internal_metadata.is_outlier()
278-
]
279-
)
280-
281-
# We now insert into stream_ordering_to_exterm a mapping from room_id,
282-
# new stream_ordering to new forward extremeties in the room.
283-
# This allows us to later efficiently look up the forward extremeties
284-
# for a room before a given stream_ordering
285-
max_stream_ord = max(
286-
ev.internal_metadata.stream_ordering for ev in events
287-
)
288-
new_extrem = {}
289-
for room_id in events_by_room:
290-
event_ids = self._simple_select_onecol_txn(
291-
txn,
292-
table="event_forward_extremities",
293-
keyvalues={"room_id": room_id},
294-
retcol="event_id",
295-
)
296-
new_extrem[room_id] = event_ids
297-
298-
self._simple_insert_many_txn(
299-
txn,
300-
table="stream_ordering_to_exterm",
301-
values=[
302-
{
303-
"room_id": room_id,
304-
"event_id": event_id,
305-
"stream_ordering": max_stream_ord,
306-
}
307-
for room_id, extrem_evs in new_extrem.items()
308-
for event_id in extrem_evs
309-
]
310-
)
311-
312253
query = (
313254
"INSERT INTO event_backward_extremities (event_id, room_id)"
314255
" SELECT ?, ? WHERE NOT EXISTS ("
@@ -339,11 +280,6 @@ def _update_extremeties(self, txn, events):
339280
]
340281
)
341282

342-
for room_id in events_by_room:
343-
txn.call_after(
344-
self.get_latest_event_ids_in_room.invalidate, (room_id,)
345-
)
346-
347283
def get_forward_extremeties_for_room(self, room_id, stream_ordering):
348284
# We want to make the cache more effective, so we clamp to the last
349285
# change before the given ordering.

synapse/storage/events.py

Lines changed: 86 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ def _persist_events(self, events_and_contexts, backfilled=False,
279279
# We can't easily parallelize these since different chunks
280280
# might contain the same event. :(
281281

282+
new_forward_extremeties = {}
282283
current_state_for_room = {}
283284
if not backfilled:
284285
# Work out the new "current state" for each room.
@@ -296,20 +297,16 @@ def _persist_events(self, events_and_contexts, backfilled=False,
296297
latest_event_ids = yield self.get_latest_event_ids_in_room(
297298
room_id
298299
)
299-
new_latest_event_ids = set(latest_event_ids)
300-
for event, ctx in ev_ctx_rm:
301-
if event.internal_metadata.is_outlier():
302-
continue
303-
304-
new_latest_event_ids.difference_update(
305-
e_id for e_id, _ in event.prev_events
306-
)
307-
new_latest_event_ids.add(event.event_id)
300+
new_latest_event_ids = yield self._calculate_new_extremeties(
301+
room_id, [ev for ev, _ in ev_ctx_rm]
302+
)
308303

309304
if new_latest_event_ids == set(latest_event_ids):
310305
# No change in extremities, so no change in state
311306
continue
312307

308+
new_forward_extremeties[room_id] = new_latest_event_ids
309+
313310
# Now we need to work out the different state sets for
314311
# each state extremities
315312
state_sets = []
@@ -358,9 +355,45 @@ def _persist_events(self, events_and_contexts, backfilled=False,
358355
backfilled=backfilled,
359356
delete_existing=delete_existing,
360357
current_state_for_room=current_state_for_room,
358+
new_forward_extremeties=new_forward_extremeties,
361359
)
362360
persist_event_counter.inc_by(len(chunk))
363361

362+
@defer.inlineCallbacks
363+
def _calculate_new_extremeties(self, room_id, events):
364+
latest_event_ids = yield self.get_latest_event_ids_in_room(
365+
room_id
366+
)
367+
new_latest_event_ids = set(latest_event_ids)
368+
new_latest_event_ids.update(
369+
event.event_id for event in events
370+
if not event.internal_metadata.is_outlier()
371+
)
372+
new_latest_event_ids.difference_update(
373+
e_id
374+
for event in events
375+
for e_id, _ in event.prev_events
376+
if not event.internal_metadata.is_outlier()
377+
)
378+
379+
rows = yield self._simple_select_many_batch(
380+
table="event_edges",
381+
column="prev_event_id",
382+
iterable=list(new_latest_event_ids),
383+
retcols=["prev_event_id"],
384+
keyvalues={
385+
"room_id": room_id,
386+
"is_state": False,
387+
},
388+
desc="_calculate_new_extremeties",
389+
)
390+
391+
new_latest_event_ids.difference_update(
392+
row["prev_event_id"] for row in rows
393+
)
394+
395+
defer.returnValue(new_latest_event_ids)
396+
364397
@defer.inlineCallbacks
365398
def get_event(self, event_id, check_redacted=True,
366399
get_prev_content=False, allow_rejected=False,
@@ -417,53 +450,10 @@ def get_events(self, event_ids, check_redacted=True,
417450

418451
defer.returnValue({e.event_id: e for e in events})
419452

420-
@log_function
421-
def _persist_event_txn(self, txn, event, context, current_state, backfilled=False,
422-
delete_existing=False):
423-
# We purposefully do this first since if we include a `current_state`
424-
# key, we *want* to update the `current_state_events` table
425-
if current_state:
426-
txn.call_after(self._get_current_state_for_key.invalidate_all)
427-
txn.call_after(self.get_rooms_for_user.invalidate_all)
428-
txn.call_after(self.get_users_in_room.invalidate, (event.room_id,))
429-
430-
# Add an entry to the current_state_resets table to record the point
431-
# where we clobbered the current state
432-
stream_order = event.internal_metadata.stream_ordering
433-
self._simple_insert_txn(
434-
txn,
435-
table="current_state_resets",
436-
values={"event_stream_ordering": stream_order}
437-
)
438-
439-
self._simple_delete_txn(
440-
txn,
441-
table="current_state_events",
442-
keyvalues={"room_id": event.room_id},
443-
)
444-
445-
for s in current_state:
446-
self._simple_insert_txn(
447-
txn,
448-
"current_state_events",
449-
{
450-
"event_id": s.event_id,
451-
"room_id": s.room_id,
452-
"type": s.type,
453-
"state_key": s.state_key,
454-
}
455-
)
456-
457-
return self._persist_events_txn(
458-
txn,
459-
[(event, context)],
460-
backfilled=backfilled,
461-
delete_existing=delete_existing,
462-
)
463-
464453
@log_function
465454
def _persist_events_txn(self, txn, events_and_contexts, backfilled,
466-
delete_existing=False, current_state_for_room={}):
455+
delete_existing=False, current_state_for_room={},
456+
new_forward_extremeties={}):
467457
"""Insert some number of room events into the necessary database tables.
468458
469459
Rejected events are only inserted into the events table, the events_json table,
@@ -473,18 +463,18 @@ def _persist_events_txn(self, txn, events_and_contexts, backfilled,
473463
If delete_existing is True then existing events will be purged from the
474464
database before insertion. This is useful when retrying due to IntegrityError.
475465
"""
466+
max_stream_order = events_and_contexts[-1][0].internal_metadata.stream_ordering
476467
for room_id, current_state in current_state_for_room.iteritems():
477468
txn.call_after(self._get_current_state_for_key.invalidate_all)
478469
txn.call_after(self.get_rooms_for_user.invalidate_all)
479470
txn.call_after(self.get_users_in_room.invalidate, (room_id,))
480471

481472
# Add an entry to the current_state_resets table to record the point
482473
# where we clobbered the current state
483-
stream_order = events_and_contexts[-1][0].internal_metadata.stream_ordering
484474
self._simple_insert_txn(
485475
txn,
486476
table="current_state_resets",
487-
values={"event_stream_ordering": stream_order}
477+
values={"event_stream_ordering": max_stream_order}
488478
)
489479

490480
self._simple_delete_txn(
@@ -507,6 +497,46 @@ def _persist_events_txn(self, txn, events_and_contexts, backfilled,
507497
],
508498
)
509499

500+
for room_id, new_extrem in new_forward_extremeties.items():
501+
self._simple_delete_txn(
502+
txn,
503+
table="event_forward_extremities",
504+
keyvalues={"room_id": room_id},
505+
)
506+
txn.call_after(
507+
self.get_latest_event_ids_in_room.invalidate, (room_id,)
508+
)
509+
510+
self._simple_insert_many_txn(
511+
txn,
512+
table="event_forward_extremities",
513+
values=[
514+
{
515+
"event_id": ev_id,
516+
"room_id": room_id,
517+
}
518+
for room_id, new_extrem in new_forward_extremeties.items()
519+
for ev_id in new_extrem
520+
],
521+
)
522+
# We now insert into stream_ordering_to_exterm a mapping from room_id,
523+
# new stream_ordering to new forward extremeties in the room.
524+
# This allows us to later efficiently look up the forward extremeties
525+
# for a room before a given stream_ordering
526+
self._simple_insert_many_txn(
527+
txn,
528+
table="stream_ordering_to_exterm",
529+
values=[
530+
{
531+
"room_id": room_id,
532+
"event_id": event_id,
533+
"stream_ordering": max_stream_order,
534+
}
535+
for room_id, new_extrem in new_forward_extremeties.items()
536+
for event_id in new_extrem
537+
]
538+
)
539+
510540
# Ensure that we don't have the same event twice.
511541
# Pick the earliest non-outlier if there is one, else the earliest one.
512542
new_events_and_contexts = OrderedDict()

0 commit comments

Comments
 (0)