@@ -817,10 +817,19 @@ def _on_room_event(self, event: proto_room.RoomEvent) -> None:
817817 lpublication ._first_subscription .set_result (None )
818818 self .emit ("local_track_subscribed" , lpublication .track )
819819 elif which == "track_published" :
820- rparticipant = self ._remote_participants [event .track_published .participant_identity ]
821- rpublication = RemoteTrackPublication (event .track_published .publication )
822- rparticipant ._track_publications [rpublication .sid ] = rpublication
823- self .emit ("track_published" , rpublication , rparticipant )
820+ # The participant may already have been removed by a racing
821+ # disconnect or a duplicate event, so the lookup is done defensively
822+ # and the emit is skipped when the participant is gone, mirroring the
823+ # track_unpublished handler, instead of raising a KeyError that
824+ # _listen_task logs as an error.
825+ identity = event .track_published .participant_identity
826+ rp = self ._remote_participants .get (identity )
827+ if rp is not None :
828+ rpub = RemoteTrackPublication (event .track_published .publication )
829+ rp ._track_publications [rpub .sid ] = rpub
830+ self .emit ("track_published" , rpub , rp )
831+ else :
832+ logger .debug ("track_published for untracked participant %s" , identity )
824833 elif which == "track_unpublished" :
825834 # The participant or publication may already have been removed by a
826835 # racing disconnect or a duplicate event, so both lookups are done
@@ -839,41 +848,77 @@ def _on_room_event(self, event: proto_room.RoomEvent) -> None:
839848 else :
840849 logger .debug ("track_unpublished for untracked participant %s" , identity )
841850 elif which == "track_subscribed" :
851+ # The participant or publication may already have been removed by a
852+ # racing disconnect or unpublish, so both lookups are done
853+ # defensively and the emit is skipped when either entry is gone,
854+ # mirroring the track_unpublished handler, instead of raising a
855+ # KeyError that _listen_task logs as an error.
842856 owned_track_info = event .track_subscribed .track
843857 track_info = owned_track_info .info
844- rparticipant = self ._remote_participants [event .track_subscribed .participant_identity ]
845- rpublication = rparticipant .track_publications [track_info .sid ]
846- rpublication ._subscribed = True
847- if track_info .kind == TrackKind .KIND_VIDEO :
848- remote_video_track = RemoteVideoTrack (owned_track_info )
849- remote_video_track ._set_room (self )
850- rpublication ._track = remote_video_track
851- self .emit ("track_subscribed" , remote_video_track , rpublication , rparticipant )
852- elif track_info .kind == TrackKind .KIND_AUDIO :
853- remote_audio_track = RemoteAudioTrack (owned_track_info )
854- remote_audio_track ._set_room (self )
855- rpublication ._track = remote_audio_track
856- self .emit ("track_subscribed" , remote_audio_track , rpublication , rparticipant )
858+ identity = event .track_subscribed .participant_identity
859+ rp = self ._remote_participants .get (identity )
860+ rpub = rp .track_publications .get (track_info .sid ) if rp is not None else None
861+ if rp is not None and rpub is not None :
862+ rpub ._subscribed = True
863+ if track_info .kind == TrackKind .KIND_VIDEO :
864+ remote_video_track = RemoteVideoTrack (owned_track_info )
865+ remote_video_track ._set_room (self )
866+ rpub ._track = remote_video_track
867+ self .emit ("track_subscribed" , remote_video_track , rpub , rp )
868+ elif track_info .kind == TrackKind .KIND_AUDIO :
869+ remote_audio_track = RemoteAudioTrack (owned_track_info )
870+ remote_audio_track ._set_room (self )
871+ rpub ._track = remote_audio_track
872+ self .emit ("track_subscribed" , remote_audio_track , rpub , rp )
873+ else :
874+ logger .debug (
875+ "track_subscribed for untracked participant %s or publication %s" ,
876+ identity ,
877+ track_info .sid ,
878+ )
857879 elif which == "track_unsubscribed" :
880+ # The participant or publication may already have been removed by a
881+ # racing disconnect or unpublish, so both lookups are done
882+ # defensively and the emit is skipped when either entry is gone,
883+ # mirroring the track_unpublished handler, instead of raising a
884+ # KeyError that _listen_task logs as an error.
858885 identity = event .track_unsubscribed .participant_identity
859- rparticipant = self ._remote_participants [identity ]
860- rpublication = rparticipant .track_publications [event .track_unsubscribed .track_sid ]
861- rtrack = rpublication .track
862- if rtrack is not None :
863- rtrack ._set_room (None )
864- rpublication ._track = None
865- rpublication ._subscribed = False
866- self .emit ("track_unsubscribed" , rtrack , rpublication , rparticipant )
886+ rp = self ._remote_participants .get (identity )
887+ rpub = (
888+ rp .track_publications .get (event .track_unsubscribed .track_sid )
889+ if rp is not None
890+ else None
891+ )
892+ if rp is not None and rpub is not None :
893+ rtrack = rpub .track
894+ if rtrack is not None :
895+ rtrack ._set_room (None )
896+ rpub ._track = None
897+ rpub ._subscribed = False
898+ self .emit ("track_unsubscribed" , rtrack , rpub , rp )
899+ else :
900+ logger .debug (
901+ "track_unsubscribed for untracked participant %s or publication %s" ,
902+ identity ,
903+ event .track_unsubscribed .track_sid ,
904+ )
867905 elif which == "track_subscription_failed" :
906+ # The participant may already have been removed by a racing
907+ # disconnect, so the lookup is done defensively and the emit is
908+ # skipped when the participant is gone, instead of raising a KeyError
909+ # that _listen_task logs as an error.
868910 identity = event .track_subscription_failed .participant_identity
869- rparticipant = self ._remote_participants [identity ]
870- error = event .track_subscription_failed .error
871- self .emit (
872- "track_subscription_failed" ,
873- rparticipant ,
874- event .track_subscription_failed .track_sid ,
875- error ,
876- )
911+ rp = self ._remote_participants .get (identity )
912+ if rp is not None :
913+ error = event .track_subscription_failed .error
914+ self .emit (
915+ "track_subscription_failed" ,
916+ rp ,
917+ event .track_subscription_failed .track_sid ,
918+ error ,
919+ )
920+ else :
921+ logger .debug ("track_subscription_failed for untracked participant %s" , identity )
877922 elif which == "track_muted" :
878923 identity = event .track_muted .participant_identity
879924 # TODO: pass participant identity
0 commit comments