@@ -689,7 +689,7 @@ async def create_and_send_nonmember_event(
689689 send this event.
690690
691691 Returns:
692- The event, and its stream ordering (if state event deduplication happened,
692+ The event, and its stream ordering (if deduplication happened,
693693 the previous, duplicate event).
694694
695695 Raises:
@@ -712,6 +712,19 @@ async def create_and_send_nonmember_event(
712712 # extremities to pile up, which in turn leads to state resolution
713713 # taking longer.
714714 with (await self .limiter .queue (event_dict ["room_id" ])):
715+ if txn_id and requester .access_token_id :
716+ existing_event_id = await self .store .get_event_id_from_transaction_id (
717+ event_dict ["room_id" ],
718+ requester .user .to_string (),
719+ requester .access_token_id ,
720+ txn_id ,
721+ )
722+ if existing_event_id :
723+ event = await self .store .get_event (existing_event_id )
724+ # we know it was persisted, so must have a stream ordering
725+ assert event .internal_metadata .stream_ordering
726+ return event , event .internal_metadata .stream_ordering
727+
715728 event , context = await self .create_event (
716729 requester , event_dict , token_id = requester .access_token_id , txn_id = txn_id
717730 )
@@ -913,10 +926,20 @@ async def handle_new_client_event(
913926 extra_users = extra_users ,
914927 )
915928 stream_id = result ["stream_id" ]
916- event .internal_metadata .stream_ordering = stream_id
929+ event_id = result ["event_id" ]
930+ if event_id != event .event_id :
931+ # If we get a different event back then it means that its
932+ # been de-duplicated, so we replace the given event with the
933+ # one already persisted.
934+ event = await self .store .get_event (event_id )
935+ else :
936+ # If we newly persisted the event then we need to update its
937+ # stream_ordering entry manually (as it was persisted on
938+ # another worker).
939+ event .internal_metadata .stream_ordering = stream_id
917940 return event
918941
919- stream_id = await self .persist_and_notify_client_event (
942+ event = await self .persist_and_notify_client_event (
920943 requester , event , context , ratelimit = ratelimit , extra_users = extra_users
921944 )
922945
@@ -965,11 +988,16 @@ async def persist_and_notify_client_event(
965988 context : EventContext ,
966989 ratelimit : bool = True ,
967990 extra_users : List [UserID ] = [],
968- ) -> int :
991+ ) -> EventBase :
969992 """Called when we have fully built the event, have already
970993 calculated the push actions for the event, and checked auth.
971994
972995 This should only be run on the instance in charge of persisting events.
996+
997+ Returns:
998+ The persisted event. This may be different than the given event if
999+ it was de-duplicated (e.g. because we had already persisted an
1000+ event with the same transaction ID.)
9731001 """
9741002 assert self .storage .persistence is not None
9751003 assert self ._events_shard_config .should_handle (
@@ -1137,9 +1165,13 @@ def is_inviter_member_event(e):
11371165 if prev_state_ids :
11381166 raise AuthError (403 , "Changing the room create event is forbidden" )
11391167
1140- event_pos , max_stream_token = await self .storage .persistence .persist_event (
1141- event , context = context
1142- )
1168+ # Note that this returns the event that was persisted, which may not be
1169+ # the same as we passed in if it was deduplicated due transaction IDs.
1170+ (
1171+ event ,
1172+ event_pos ,
1173+ max_stream_token ,
1174+ ) = await self .storage .persistence .persist_event (event , context = context )
11431175
11441176 if self ._ephemeral_events_enabled :
11451177 # If there's an expiry timestamp on the event, schedule its expiry.
@@ -1160,7 +1192,7 @@ def _notify():
11601192 # matters as sometimes presence code can take a while.
11611193 run_in_background (self ._bump_active_time , requester .user )
11621194
1163- return event_pos . stream
1195+ return event
11641196
11651197 async def _bump_active_time (self , user : UserID ) -> None :
11661198 try :
0 commit comments