private async Task RemoveParticipant(Participant participant, string?connectionId, CancellationToken cancellationToken) { _logger.LogDebug("RemoveParticipant() | {participant}, connectionId:{connectionId}", participant, connectionId); if (connectionId == null) { if (!_connections.TryGetParticipant(participant.Id, out var connection)) { return; } connectionId = connection.ConnectionId; } if (_connections.TryRemoveParticipant(participant.Id, new ParticipantConnection(participant.ConferenceId, connectionId))) { _logger.LogDebug("Remove participant connection"); await _hubContext.Groups.RemoveFromGroupAsync(connectionId, CoreHubGroups.OfParticipant(participant), cancellationToken); await _hubContext.Groups.RemoveFromGroupAsync(connectionId, CoreHubGroups.OfConference(participant.ConferenceId), cancellationToken); if (await _repository.IsParticipantJoined(participant, connectionId)) { await using var @lock = await _repository.LockParticipantJoin(participant); if (await _repository.IsParticipantJoined(participant, connectionId)) { await _mediator.Publish(new ParticipantLeftNotification(participant, connectionId), @lock.HandleLostToken); } } else { _logger.LogDebug("Participant is not joined"); } } else { _logger.LogDebug("Participant connection was already removed"); } }
public async Task <Unit> Handle(JoinConferenceRequest request, CancellationToken cancellationToken) { var(participant, connectionId, meta) = request; var(conferenceId, participantId) = participant; _logger.LogDebug("Participant {participantId} is joining conference {conferenceId}", participantId, conferenceId); var previousSession = await _joinedParticipantsRepository.AddParticipant(participant, connectionId); if (previousSession != null) { _logger.LogDebug("The participant {participantId} was already joined, kick existing connection.", participantId); await _mediator.Publish(new ParticipantKickedNotification( new Participant(previousSession.ConferenceId, participantId), previousSession.ConnectionId, ParticipantKickedReason.NewSessionConnected)); } await using var @lock = await _joinedParticipantsRepository.LockParticipantJoin(participant); if (!await _joinedParticipantsRepository.IsParticipantJoined(participant, connectionId)) { throw new ConcurrencyException("Race condition on participant join."); } _logger.LogDebug("Begin joining of participant {participant}", participant); // enable messaging just after kicking client await _mediator.Publish(new ParticipantInitializedNotification(participant)); // do not merge these together as handlers for ParticipantJoinedNotification may want to send messages to the participant await _mediator.Send(new EnableParticipantMessagingRequest(participant, connectionId), cancellationToken); await _mediator.Publish(new ParticipantJoinedNotification(participant, meta)); return(Unit.Value); }
public async Task Handle(ParticipantKickedNotification notification, CancellationToken cancellationToken) { var(participant, connectionId, reason) = notification; var targetClient = connectionId != null ? _hubContext.Clients.Client(connectionId) : _hubContext.Clients.Group(CoreHubGroups.OfParticipant(participant)); await targetClient.OnRequestDisconnect(new RequestDisconnectDto(reason), cancellationToken); if (connectionId != null) { // it's very important that we publish participant left, as a new participant may be joining right after this and // we have to clean up first await using (var @lock = await _repository.LockParticipantJoin(participant)) { await _mediator.Publish(new ParticipantLeftNotification(participant, connectionId), @lock.HandleLostToken); } } await _publishEndpoint.Publish <ParticipantKicked>(notification, cancellationToken); }