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

Commit d26094e

Browse files
Add base starting insertion event when no chunk ID is provided (MSC2716) (#10250)
* Add base starting insertion point when no chunk ID is provided This is so we can have the marker event point to this initial insertion event and be able to traverse the events in the first chunk.
1 parent 33ae301 commit d26094e

File tree

3 files changed

+98
-23
lines changed

3 files changed

+98
-23
lines changed

changelog.d/10250.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add base starting insertion event when no chunk ID is specified in the historical batch send API.

synapse/handlers/message.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,9 @@ async def create_event(
518518
outlier: Indicates whether the event is an `outlier`, i.e. if
519519
it's from an arbitrary point and floating in the DAG as
520520
opposed to being inline with the current DAG.
521+
historical: Indicates whether the message is being inserted
522+
back in time around some existing events. This is used to skip
523+
a few checks and mark the event as backfilled.
521524
depth: Override the depth used to order the event in the DAG.
522525
Should normally be set to None, which will cause the depth to be calculated
523526
based on the prev_events.
@@ -772,6 +775,7 @@ async def create_and_send_nonmember_event(
772775
txn_id: Optional[str] = None,
773776
ignore_shadow_ban: bool = False,
774777
outlier: bool = False,
778+
historical: bool = False,
775779
depth: Optional[int] = None,
776780
) -> Tuple[EventBase, int]:
777781
"""
@@ -799,6 +803,9 @@ async def create_and_send_nonmember_event(
799803
outlier: Indicates whether the event is an `outlier`, i.e. if
800804
it's from an arbitrary point and floating in the DAG as
801805
opposed to being inline with the current DAG.
806+
historical: Indicates whether the message is being inserted
807+
back in time around some existing events. This is used to skip
808+
a few checks and mark the event as backfilled.
802809
depth: Override the depth used to order the event in the DAG.
803810
Should normally be set to None, which will cause the depth to be calculated
804811
based on the prev_events.
@@ -847,6 +854,7 @@ async def create_and_send_nonmember_event(
847854
prev_event_ids=prev_event_ids,
848855
auth_event_ids=auth_event_ids,
849856
outlier=outlier,
857+
historical=historical,
850858
depth=depth,
851859
)
852860

synapse/rest/client/v1/room.py

Lines changed: 89 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,35 @@ async def inherit_depth_from_prev_ids(self, prev_event_ids) -> int:
349349

350350
return depth
351351

352+
def _create_insertion_event_dict(
353+
self, sender: str, room_id: str, origin_server_ts: int
354+
):
355+
"""Creates an event dict for an "insertion" event with the proper fields
356+
and a random chunk ID.
357+
358+
Args:
359+
sender: The event author MXID
360+
room_id: The room ID that the event belongs to
361+
origin_server_ts: Timestamp when the event was sent
362+
363+
Returns:
364+
Tuple of event ID and stream ordering position
365+
"""
366+
367+
next_chunk_id = random_string(8)
368+
insertion_event = {
369+
"type": EventTypes.MSC2716_INSERTION,
370+
"sender": sender,
371+
"room_id": room_id,
372+
"content": {
373+
EventContentFields.MSC2716_NEXT_CHUNK_ID: next_chunk_id,
374+
EventContentFields.MSC2716_HISTORICAL: True,
375+
},
376+
"origin_server_ts": origin_server_ts,
377+
}
378+
379+
return insertion_event
380+
352381
async def on_POST(self, request, room_id):
353382
requester = await self.auth.get_user_by_req(request, allow_guest=False)
354383

@@ -449,37 +478,68 @@ async def on_POST(self, request, room_id):
449478

450479
events_to_create = body["events"]
451480

452-
# If provided, connect the chunk to the last insertion point
453-
# The chunk ID passed in comes from the chunk_id in the
454-
# "insertion" event from the previous chunk.
481+
prev_event_ids = prev_events_from_query
482+
inherited_depth = await self.inherit_depth_from_prev_ids(prev_events_from_query)
483+
484+
# Figure out which chunk to connect to. If they passed in
485+
# chunk_id_from_query let's use it. The chunk ID passed in comes
486+
# from the chunk_id in the "insertion" event from the previous chunk.
487+
last_event_in_chunk = events_to_create[-1]
488+
chunk_id_to_connect_to = chunk_id_from_query
489+
base_insertion_event = None
455490
if chunk_id_from_query:
456-
last_event_in_chunk = events_to_create[-1]
457-
last_event_in_chunk["content"][
458-
EventContentFields.MSC2716_CHUNK_ID
459-
] = chunk_id_from_query
491+
# TODO: Verify the chunk_id_from_query corresponds to an insertion event
492+
pass
493+
# Otherwise, create an insertion event to act as a starting point.
494+
#
495+
# We don't always have an insertion event to start hanging more history
496+
# off of (ideally there would be one in the main DAG, but that's not the
497+
# case if we're wanting to add history to e.g. existing rooms without
498+
# an insertion event), in which case we just create a new insertion event
499+
# that can then get pointed to by a "marker" event later.
500+
else:
501+
base_insertion_event_dict = self._create_insertion_event_dict(
502+
sender=requester.user.to_string(),
503+
room_id=room_id,
504+
origin_server_ts=last_event_in_chunk["origin_server_ts"],
505+
)
506+
base_insertion_event_dict["prev_events"] = prev_event_ids.copy()
460507

461-
# Add an "insertion" event to the start of each chunk (next to the oldest
508+
(
509+
base_insertion_event,
510+
_,
511+
) = await self.event_creation_handler.create_and_send_nonmember_event(
512+
requester,
513+
base_insertion_event_dict,
514+
prev_event_ids=base_insertion_event_dict.get("prev_events"),
515+
auth_event_ids=auth_event_ids,
516+
historical=True,
517+
depth=inherited_depth,
518+
)
519+
520+
chunk_id_to_connect_to = base_insertion_event["content"][
521+
EventContentFields.MSC2716_NEXT_CHUNK_ID
522+
]
523+
524+
# Connect this current chunk to the insertion event from the previous chunk
525+
last_event_in_chunk["content"][
526+
EventContentFields.MSC2716_CHUNK_ID
527+
] = chunk_id_to_connect_to
528+
529+
# Add an "insertion" event to the start of each chunk (next to the oldest-in-time
462530
# event in the chunk) so the next chunk can be connected to this one.
463-
next_chunk_id = random_string(64)
464-
insertion_event = {
465-
"type": EventTypes.MSC2716_INSERTION,
466-
"sender": requester.user.to_string(),
467-
"content": {
468-
EventContentFields.MSC2716_NEXT_CHUNK_ID: next_chunk_id,
469-
EventContentFields.MSC2716_HISTORICAL: True,
470-
},
531+
insertion_event = self._create_insertion_event_dict(
532+
sender=requester.user.to_string(),
533+
room_id=room_id,
471534
# Since the insertion event is put at the start of the chunk,
472-
# where the oldest event is, copy the origin_server_ts from
535+
# where the oldest-in-time event is, copy the origin_server_ts from
473536
# the first event we're inserting
474-
"origin_server_ts": events_to_create[0]["origin_server_ts"],
475-
}
537+
origin_server_ts=events_to_create[0]["origin_server_ts"],
538+
)
476539
# Prepend the insertion event to the start of the chunk
477540
events_to_create = [insertion_event] + events_to_create
478541

479-
inherited_depth = await self.inherit_depth_from_prev_ids(prev_events_from_query)
480-
481542
event_ids = []
482-
prev_event_ids = prev_events_from_query
483543
events_to_persist = []
484544
for ev in events_to_create:
485545
assert_params_in_dict(ev, ["type", "origin_server_ts", "content", "sender"])
@@ -533,10 +593,16 @@ async def on_POST(self, request, room_id):
533593
context=context,
534594
)
535595

596+
# Add the base_insertion_event to the bottom of the list we return
597+
if base_insertion_event is not None:
598+
event_ids.append(base_insertion_event.event_id)
599+
536600
return 200, {
537601
"state_events": auth_event_ids,
538602
"events": event_ids,
539-
"next_chunk_id": next_chunk_id,
603+
"next_chunk_id": insertion_event["content"][
604+
EventContentFields.MSC2716_NEXT_CHUNK_ID
605+
],
540606
}
541607

542608
def on_GET(self, request, room_id):

0 commit comments

Comments
 (0)