/// <inheritdoc /> public void JoinGroup(SessionInfo session, Guid groupId, JoinGroupRequest request, CancellationToken cancellationToken) { var user = _userManager.GetUserById(session.UserId); if (user.SyncPlayAccess == SyncPlayAccess.None) { _logger.LogWarning("JoinGroup: {0} does not have access to SyncPlay.", session.Id); var error = new GroupUpdate <string>() { Type = GroupUpdateType.JoinGroupDenied }; _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None); return; } lock (_groupsLock) { ISyncPlayController group; _groups.TryGetValue(groupId, out group); if (group == null) { _logger.LogWarning("JoinGroup: {0} tried to join group {0} that does not exist.", session.Id, groupId); var error = new GroupUpdate <string>() { Type = GroupUpdateType.GroupDoesNotExist }; _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None); return; } if (!HasAccessToItem(user, group.GetPlayingItemId())) { _logger.LogWarning("JoinGroup: {0} does not have access to {1}.", session.Id, group.GetPlayingItemId()); var error = new GroupUpdate <string>() { GroupId = group.GetGroupId().ToString(), Type = GroupUpdateType.LibraryAccessDenied }; _sessionManager.SendSyncPlayGroupUpdate(session.Id, error, CancellationToken.None); return; } if (IsSessionInGroup(session)) { if (GetSessionGroup(session).Equals(groupId)) { return; } LeaveGroup(session, cancellationToken); } group.SessionJoin(session, request, cancellationToken); } }
public async Task <SignalRServerResponse> Join(JoinGroupRequest request) { if (request.IsDetector) { await AddToDetectorGroup(); } else { await AddToConsumerGroup(request.IsHDMIController); } // Here we are selecting all the IDs that are currently in the ClientID - GroupName hash and putting them in a list IReadOnlyList <string> joinedClients = _clientIDGroupNameHash.Select(cg => cg.Key) .Where(id => id != Context.ConnectionId) .ToList(); // build the counts of each group ClientGroupStats otherGroupStats = BuildClientGroupStatsResponse(); // this one contains the group that was just joined ClientGroupStats senderGroupStats = BuildClientGroupStatsResponse(true); // publish to all clients that have joined a group that there are new group stats. await Clients.Clients(joinedClients).SendAsync(nameof(ClientGroupStats), otherGroupStats); await Clients.Caller.SendAsync(nameof(ClientGroupStats), senderGroupStats); return(new SignalRServerResponse() { Success = true }); }
private async Task JoinGroupAsync(CancellationToken cancellationToken) { if (_disposeCount > 0) { throw new ObjectDisposedException($"Consumer {{GroupId:{GroupId},MemberId:{MemberId}}} is no longer valid"); } try { var protocols = _joinSemaphore.Lock(() => IsLeader ? _memberMetadata?.Values.Select(m => new JoinGroupRequest.GroupProtocol(m)) : null, cancellationToken); var request = new JoinGroupRequest(GroupId, Configuration.GroupHeartbeat, MemberId, ProtocolType, protocols, Configuration.GroupRebalanceTimeout); var response = await Router.SendAsync(request, GroupId, cancellationToken, new RequestContext(protocolType : ProtocolType), Configuration.GroupCoordinationRetry).ConfigureAwait(false); OnJoinGroup(response); await _stateChangeQueue.EnqueueAsync(ApiKey.SyncGroup, _disposeToken.Token); } catch (RequestException ex) { switch (ex.ErrorCode) { case ErrorCode.ILLEGAL_GENERATION: case ErrorCode.GROUP_AUTHORIZATION_FAILED: case ErrorCode.UNKNOWN_MEMBER_ID: case ErrorCode.INCONSISTENT_GROUP_PROTOCOL: case ErrorCode.INVALID_SESSION_TIMEOUT: Router.Log.Warn(() => LogEvent.Create(ex)); _leaveOnDispose = false; // no point in attempting to leave the group since it will fail _disposeToken.Cancel(); return; } throw; } }
/// <summary> /// Handles the specified request. /// </summary> /// <param name="request">The request.</param> public void Post(SyncPlayJoin request) { var currentSession = GetSession(_sessionContext); Guid groupId; Guid playingItemId = Guid.Empty; if (!Guid.TryParse(request.GroupId, out groupId)) { Logger.LogError("JoinGroup: {0} is not a valid format for GroupId. Ignoring request.", request.GroupId); return; } // Both null and empty strings mean that client isn't playing anything if (!string.IsNullOrEmpty(request.PlayingItemId) && !Guid.TryParse(request.PlayingItemId, out playingItemId)) { Logger.LogError("JoinGroup: {0} is not a valid format for PlayingItemId. Ignoring request.", request.PlayingItemId); return; } var joinRequest = new JoinGroupRequest() { GroupId = groupId, PlayingItemId = playingItemId }; _syncPlayManager.JoinGroup(currentSession, groupId, joinRequest, CancellationToken.None); }
public async Task <ServiceResult <object> > AgreeJoin(User owner, JoinGroupRequest request) { var owns = await OwnsGroup(owner, request.Group); if (!owns.ExtraData) { return(Unauthorized(owns.Detail)); } if (request == null) { return(NotFound("该加群申请不存在")); } Context.JoinGroupRequests.Remove(request); Context.GroupMemberships.Add(new GroupMembership { UserId = request.User.Id, ChatGroupId = request.Group.Id, Role = GroupRole.Member }); if (ConnectionService.IsOnline(request.UserId)) { await HubContext.Groups.AddToGroupAsync(ConnectionService.GetConnectionId(request.UserId), request.GroupId.ToString()); } await NotificationService.NotifyGroupMembers(request.GroupId, $"{request?.User?.Nickname ?? "未命名用户"}加入了群聊", NotificationTypeEnum.NewMemberJoined); await Context.SaveChangesAsync(); return(Success("通过加群成功")); }
/// <inheritdoc /> public void SessionJoin(SessionInfo session, JoinGroupRequest request, CancellationToken cancellationToken) { if (session.NowPlayingItem?.Id == _group.PlayingItem.Id && request.PlayingItemId == _group.PlayingItem.Id) { _group.AddSession(session); _syncPlayManager.AddSessionToGroup(session, this); var updateSession = NewSyncPlayGroupUpdate(GroupUpdateType.GroupJoined, DateToUTCString(DateTime.UtcNow)); SendGroupUpdate(session, BroadcastType.CurrentSession, updateSession, cancellationToken); var updateOthers = NewSyncPlayGroupUpdate(GroupUpdateType.UserJoined, session.UserName); SendGroupUpdate(session, BroadcastType.AllExceptCurrentSession, updateOthers, cancellationToken); // Client join and play, syncing will happen client side if (!_group.IsPaused) { var playCommand = NewSyncPlayCommand(SendCommandType.Play); SendCommand(session, BroadcastType.CurrentSession, playCommand, cancellationToken); } else { var pauseCommand = NewSyncPlayCommand(SendCommandType.Pause); SendCommand(session, BroadcastType.CurrentSession, pauseCommand, cancellationToken); } } else { var playRequest = new PlayRequest(); playRequest.ItemIds = new Guid[] { _group.PlayingItem.Id }; playRequest.StartPositionTicks = _group.PositionTicks; var update = NewSyncPlayGroupUpdate(GroupUpdateType.PrepareSession, playRequest); SendGroupUpdate(session, BroadcastType.CurrentSession, update, cancellationToken); } }
public async Task ConsumerSyncsGroupAfterJoining() { var protocol = new JoinGroupRequest.GroupProtocol(new ConsumerProtocolMetadata("mine")); var router = Substitute.For <IRouter>(); var conn = Substitute.For <IConnection>(); router.GetGroupConnectionAsync(Arg.Any <string>(), Arg.Any <CancellationToken>()) .Returns(_ => Task.FromResult(new GroupConnection(_.Arg <string>(), 0, conn))); router.SyncGroupAsync(Arg.Any <SyncGroupRequest>(), Arg.Any <IRequestContext>(), Arg.Any <IRetry>(), Arg.Any <CancellationToken>()) .Returns(_ => Task.FromResult(new SyncGroupResponse(ErrorCode.NONE, new ConsumerMemberAssignment(new [] { new TopicPartition("name", 0) })))); var request = new JoinGroupRequest(TestConfig.GroupId(), TimeSpan.FromSeconds(30), "", ConsumerEncoder.Protocol, new [] { protocol }); var memberId = Guid.NewGuid().ToString("N"); var response = new JoinGroupResponse(ErrorCode.NONE, 1, protocol.protocol_name, memberId, memberId, new [] { new JoinGroupResponse.Member(memberId, new ConsumerProtocolMetadata("mine")) }); using (new GroupConsumer(router, request.group_id, request.protocol_type, response)) { await Task.Delay(300); } #pragma warning disable 4014 router.Received().SyncGroupAsync( Arg.Is((SyncGroupRequest s) => s.group_id == request.group_id && s.member_id == memberId), Arg.Any <IRequestContext>(), Arg.Any <IRetry>(), Arg.Any <CancellationToken>()); conn.DidNotReceive().SendAsync( Arg.Is((HeartbeatRequest s) => s.group_id == request.group_id && s.member_id == memberId), Arg.Any <CancellationToken>(), Arg.Any <IRequestContext>()); #pragma warning restore 4014 }
public async Task ConsumerHeartbeatsWithinTimeLimit(int heartbeatMilliseconds, int totalMilliseconds) { var protocol = new JoinGroupRequest.GroupProtocol(new ConsumerProtocolMetadata("mine")); var router = Substitute.For <IRouter>(); var conn = Substitute.For <IConnection>(); router.GetGroupConnectionAsync(Arg.Any <string>(), Arg.Any <CancellationToken>()) .Returns(_ => Task.FromResult(new GroupConnection(_.Arg <string>(), 0, conn))); var lastHeartbeat = DateTimeOffset.UtcNow; var heartbeatIntervals = ImmutableArray <TimeSpan> .Empty; conn.SendAsync(Arg.Any <HeartbeatRequest>(), Arg.Any <CancellationToken>(), Arg.Any <IRequestContext>()) .Returns(_ => { heartbeatIntervals = heartbeatIntervals.Add(DateTimeOffset.UtcNow - lastHeartbeat); lastHeartbeat = DateTimeOffset.UtcNow; return(Task.FromResult(new HeartbeatResponse(ErrorCode.NONE))); }); var request = new JoinGroupRequest(TestConfig.GroupId(), TimeSpan.FromMilliseconds(heartbeatMilliseconds), "", ConsumerEncoder.Protocol, new [] { protocol }); var memberId = Guid.NewGuid().ToString("N"); var response = new JoinGroupResponse(ErrorCode.NONE, 1, protocol.protocol_name, memberId, memberId, new [] { new JoinGroupResponse.Member(memberId, new ConsumerProtocolMetadata("mine")) }); lastHeartbeat = DateTimeOffset.UtcNow; using (new GroupConsumer(router, request.group_id, request.protocol_type, response)) { await Task.Delay(totalMilliseconds); } foreach (var interval in heartbeatIntervals) { Assert.That((int)interval.TotalMilliseconds, Is.AtMost(heartbeatMilliseconds)); } }
public async Task <ServiceResult <object> > JoinGroup(User user, ChatGroup chatGroup) { var membership = Context.GroupMemberships.FirstOrDefault(m => m.UserId == user.Id && m.ChatGroupId == chatGroup.Id); if (membership != null) { return(Exist("您已在该群中")); } var request = Context.JoinGroupRequests.FirstOrDefault(r => r.User.Id == user.Id && r.Group.Id == chatGroup.Id); if (request != null) { return(Exist("您已经申请加群")); } request = new JoinGroupRequest { User = user, Group = chatGroup }; Context.JoinGroupRequests.Add(request); await Context.SaveChangesAsync(); UserDetailAndGroupDetail detail = new UserDetailAndGroupDetail { User = user.ToDetail(), Group = chatGroup.ToDetail(), RequestId = request.Id, }; await NotificationService.Notify(chatGroup.Creator.Id, JsonHelper.ToJson(detail), NotificationTypeEnum.JoinRequest); return(Success("加群申请成功")); }
public JoinGroupResponse JoinGroup(String groupId, String memberId, IList <String> topics) { var request = new JoinGroupRequest(groupId, memberId, topics.ToArray(), _config.JoinGroupSessionTimeout); var response = (JoinGroupResponse)_client.SubmitRequest(_coordinateBroker.ToUri(), request); response.TryThrowFirstErrorOccured(); return(response); }
public ActionResult SyncPlayJoinGroup( [FromBody, Required] JoinGroupRequestDto requestData) { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var syncPlayRequest = new JoinGroupRequest(requestData.GroupId); _syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None); return(NoContent()); }
public async Task <bool> JoinGroup([FromBody] JoinGroupRequest req) { string token = req.token; //todo:要根据业务系统的要求,判断这个用户是否能加入这个Group MsgHubClient client = new MsgHubClient(msgHubServer); await client.JoinGroupAsync(token, req.groupId); return(true); }
public async Task <IActionResult> JoinGroup(JoinGroupRequest request) { var response = await mediator.Send(request); logger.LogResponse( $"User #{HttpContext.GetCurrentUserId()} joined group #{request.GroupId} with status: {(response.Member.IsAccepted ? "ACCEPTED" : "WAITING")}", response.Error); return(this.CreateResponse(response)); }
private void OnSessionControllerConnected(object sender, SessionEventArgs e) { var session = e.SessionInfo; if (_sessionToGroupMap.TryGetValue(session.Id, out var group)) { var request = new JoinGroupRequest(group.GroupId); JoinGroup(session, request, CancellationToken.None); } }
public static async Task <JoinGroupResponse> JoinGroupAsync(this IRouter router, string groupId, string protocolType, IEnumerable <IMemberMetadata> metadata, IConsumerConfiguration configuration, CancellationToken cancellationToken) { var protocols = metadata?.Select(m => new JoinGroupRequest.GroupProtocol(m)); var request = new JoinGroupRequest(groupId, configuration.GroupHeartbeat, null, protocolType, protocols, configuration.GroupRebalanceTimeout); var response = await router.SendAsync(request, request.group_id, cancellationToken, new RequestContext(protocolType : request.protocol_type), configuration.GroupCoordinationRetry).ConfigureAwait(false); if (response == null || !response.error_code.IsSuccess()) { throw request.ExtractExceptions(response); } return(response); }
public void joinGroup() { token = PlayerPrefs.GetString("token"); JoinGroupRequest joinGroupRequest = new JoinGroupRequest(); joinGroupRequest.action = "joinGroup"; joinGroupRequest.token = token; tempGroupName = groupNameInput.text; joinGroupRequest.groupName = tempGroupName; SendWebSocketMessage(JsonUtility.ToJson(joinGroupRequest)); groupNameInput.text = ""; }
public ActionResult SyncPlayJoinGroup([FromQuery, Required] Guid groupId) { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var joinRequest = new JoinGroupRequest() { GroupId = groupId }; _syncPlayManager.JoinGroup(currentSession, groupId, joinRequest, CancellationToken.None); return(NoContent()); }
/// <summary> /// Accept player /// </summary> /// <param name="request">join request</param> private void AcceptPlayer(JoinGroupRequest request) { IPeer peer = request.Accept("SimpleGame"); // check if peer is connected if (peer.isConnected) { GameObject go = Instantiate(boxPrefab); go.SetActive(true); ServerSimpleBox component = go.GetComponent <ServerSimpleBox>(); component.id = peer.Id; boxes.Add(component.id, component); } }
public async Task <ServiceResult <object> > RejectJoin(User owner, JoinGroupRequest request) { var owns = await OwnsGroup(owner, request.Group); if (!owns.ExtraData) { return(Unauthorized(owns.Detail)); } request = Context.JoinGroupRequests.FirstOrDefault(r => r.User.Id == request.User.Id && r.Group.Id == request.Group.Id); if (request == null) { return(NotFound("该加群申请不存在")); } Context.JoinGroupRequests.Remove(request); await Context.SaveChangesAsync(); return(Success("拒绝加群成功")); }
public async Task JoinGroupAsync(JoinGroupRequest req) { string userId = this.HttpContext.User.GetUserId(); string appKey = this.HttpContext.User.GetAppKey(); string groupName = this.HttpContext.User.GetGroupName(req.groupId); string authentication = this.HttpContext.Request.Headers["Authorization"]; string token = authentication.Substring("Bearer ".Length); IDatabase db = redis.GetDatabase(); string connectionId = await db.StringGetAsync(token + "_ConnectionId"); //用groupId做组名 await this.hubContext.Groups.AddToGroupAsync(connectionId, groupName); //如果组不存在,则创建组 //如果组存在,则用新的组名覆盖旧的 //加入成员 await db.SetAddAsync($"{groupName}_Members", userId); }
/// <summary> /// Handles the specified request. /// </summary> /// <param name="request">The request.</param> public void Post(SyncPlayJoin request) { var currentSession = GetSession(_sessionContext); Guid groupId; if (!Guid.TryParse(request.GroupId, out groupId)) { Logger.LogError("JoinGroup: {0} is not a valid format for GroupId. Ignoring request.", request.GroupId); return; } var joinRequest = new JoinGroupRequest() { GroupId = groupId }; _syncPlayManager.JoinGroup(currentSession, groupId, joinRequest, CancellationToken.None); }
public async Task JoinGroup(JoinGroupRequest req) { string sessionId = req.sessionId; if (string.IsNullOrEmpty(sessionId)) { sessionId = this.GenerateSessionID(); _logger.LogInformation($"GenerateSessionID: SessionID={sessionId}"); } if (req.isEditor) { if (EditorAlreadyExistsList.Contains(sessionId)) { _logger.LogInformation($"EditorIsAlreadyExists: SessionID={sessionId}"); await Clients.Caller.SendAsync("Joined", new { Succeeded = false, SessionId = "", Message = "Editorがすでに存在します" }); return; } else { EditorAlreadyExistsList.Add(sessionId); } } await Groups.AddToGroupAsync(Context.ConnectionId, sessionId); _logger.LogInformation($"UserJoinGroup: ConnectionId={Context.ConnectionId} SessionID={sessionId} Role={(req.isEditor ? "Editor" : "Viewer")}"); await Clients.Caller.SendAsync("Joined", new { Succeeded = true, SessionId = sessionId, Message = "" }); if (!req.isEditor) { await Clients.Group(sessionId).SendAsync("JoinNotify"); } }
public void JoinGroupRequest( [Values(0, 1)] short version, [Values("test", "a groupId")] string groupId, [Values(1, 20000)] int sessionTimeout, [Values("", "an existing member")] string memberId, [Values("consumer", "other")] string protocolType, [Values(1, 10)] int protocolsPerRequest) { var protocols = new List <JoinGroupRequest.GroupProtocol>(); for (var p = 0; p < protocolsPerRequest; p++) { var bytes = new byte[protocolsPerRequest * 100]; _randomizer.NextBytes(bytes); protocols.Add(new JoinGroupRequest.GroupProtocol(protocolType + p, new ByteMember(bytes))); } var request = new JoinGroupRequest(groupId, TimeSpan.FromMilliseconds(sessionTimeout), memberId, protocolType, protocols, version >= 1 ? (TimeSpan?)TimeSpan.FromMilliseconds(sessionTimeout * 2) : null); request.AssertCanEncodeDecodeRequest(version); }
public void JoinConsumerGroupRequest( [Values("test", "a groupId")] string groupId, [Values(1, 20000)] int sessionTimeout, [Values("", "an existing member")] string memberId, [Values("consumer")] string protocolType, [Values(1, 10)] int protocolsPerRequest) { var encoder = new ConsumerEncoder(); var protocols = new List <JoinGroupRequest.GroupProtocol>(); for (var p = 0; p < protocolsPerRequest; p++) { var userData = new byte[protocolsPerRequest * 100]; _randomizer.NextBytes(userData); var metadata = new ConsumerProtocolMetadata(0, new [] { groupId, memberId, protocolType }, userData); protocols.Add(new JoinGroupRequest.GroupProtocol(protocolType + p, metadata)); } var request = new JoinGroupRequest(groupId, TimeSpan.FromMilliseconds(sessionTimeout), memberId, protocolType, protocols); request.AssertCanEncodeDecodeRequest(0, encoder); }
public async Task JoinGroupAsync(JoinGroupRequest req) { string userId = this.HttpContext.User.GetUserId(); string appKey = this.HttpContext.User.GetAppKey(); string groupName = this.HttpContext.User.GetGroupName(req.groupId); string authentication = this.HttpContext.Request.Headers["Authorization"]; string token = authentication.Substring("Bearer ".Length); //redis连接字符串格式见https://www.cnblogs.com/ArvinZhao/p/6007043.html using (ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(redisSetting.Value.Configuration)) { IDatabase db = redis.GetDatabase(redisSetting.Value.DbId);//默认是访问db0数据库,可以通过方法参数指定数字访问不同的数据库 string connectionId = await db.StringGetAsync(token + "_ConnectionId"); //用groupId做组名 await this.Context.Groups.AddToGroupAsync(connectionId, groupName); //如果组不存在,则创建组 //如果组存在,则用新的组名覆盖旧的 //加入成员 await db.SetAddAsync($"{groupName}_Members", userId); } }
public async Task ConsumerHeartbeatsAtDesiredIntervals(int expectedHeartbeats, int heartbeatMilliseconds, int totalMilliseconds) { var protocol = new JoinGroupRequest.GroupProtocol(new ConsumerProtocolMetadata("mine")); var router = Substitute.For <IRouter>(); var conn = Substitute.For <IConnection>(); router.GetConnectionAsync(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <CancellationToken>()) .Returns(_ => Task.FromResult(conn)); router.SyncGroupAsync(Arg.Any <SyncGroupRequest>(), Arg.Any <IRequestContext>(), Arg.Any <IRetry>(), Arg.Any <CancellationToken>()) .Returns(_ => Task.FromResult(new SyncGroupResponse(ErrorCode.NONE, new ConsumerMemberAssignment(new [] { new TopicPartition("name", 0) })))); conn.SendAsync(Arg.Any <HeartbeatRequest>(), Arg.Any <CancellationToken>(), Arg.Any <IRequestContext>()) .Returns(_ => Task.FromResult(new HeartbeatResponse(ErrorCode.NONE))); var config = new ConsumerConfiguration(heartbeatTimeout: TimeSpan.FromMilliseconds(heartbeatMilliseconds * 2)); var request = new JoinGroupRequest(TestConfig.GroupId(), config.GroupHeartbeat, "", ConsumerEncoder.Protocol, new [] { protocol }); var memberId = Guid.NewGuid().ToString("N"); var response = new JoinGroupResponse(ErrorCode.NONE, 1, protocol.protocol_name, memberId, memberId, new [] { new JoinGroupResponse.Member(memberId, new ConsumerProtocolMetadata("mine")) }); using (new GroupConsumer(router, request.group_id, request.protocol_type, response, config)) { await Task.Delay(totalMilliseconds); } Assert.That(conn.ReceivedCalls() .Count(c => { if (c.GetMethodInfo().Name != nameof(Connection.SendAsync)) { return(false); } var s = c.GetArguments()[0] as HeartbeatRequest; if (s == null) { return(false); } return(s.group_id == request.group_id && s.member_id == memberId && s.generation_id == response.generation_id); }), Is.InRange(expectedHeartbeats - 1, expectedHeartbeats + 1)); }
public async Task ConsumerHeartbeatsUntilDisposed(int heartbeatMilliseconds) { var protocol = new JoinGroupRequest.GroupProtocol(new ConsumerProtocolMetadata("mine")); var router = Substitute.For <IRouter>(); var conn = Substitute.For <IConnection>(); router.GetConnectionAsync(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <CancellationToken>()) .Returns(_ => Task.FromResult(conn)); router.SyncGroupAsync(Arg.Any <SyncGroupRequest>(), Arg.Any <IRequestContext>(), Arg.Any <IRetry>(), Arg.Any <CancellationToken>()) .Returns(_ => Task.FromResult(new SyncGroupResponse(ErrorCode.NONE, new ConsumerMemberAssignment(new [] { new TopicPartition("name", 0) })))); conn.SendAsync(Arg.Any <HeartbeatRequest>(), Arg.Any <CancellationToken>(), Arg.Any <IRequestContext>()) .Returns(_ => Task.FromResult(new HeartbeatResponse(ErrorCode.NETWORK_EXCEPTION))); var heartbeat = TimeSpan.FromMilliseconds(heartbeatMilliseconds); var config = new ConsumerConfiguration(heartbeatTimeout: heartbeat, coordinationRetry: Retry.Until(heartbeat, maximumDelay: TimeSpan.FromMilliseconds(50))); var request = new JoinGroupRequest(TestConfig.GroupId(), config.GroupHeartbeat, "", ConsumerEncoder.Protocol, new [] { protocol }); var memberId = Guid.NewGuid().ToString("N"); var response = new JoinGroupResponse(ErrorCode.NONE, 1, protocol.protocol_name, memberId, memberId, new [] { new JoinGroupResponse.Member(memberId, new ConsumerProtocolMetadata("mine")) }); using (new GroupConsumer(router, request.group_id, request.protocol_type, response, config)) { await Task.Delay(heartbeatMilliseconds * 3); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed conn.DidNotReceive().SendAsync( Arg.Is((LeaveGroupRequest s) => s.group_id == request.group_id && s.member_id == memberId), Arg.Any <CancellationToken>(), Arg.Any <IRequestContext>()); } conn.Received().SendAsync( Arg.Is((LeaveGroupRequest s) => s.group_id == request.group_id && s.member_id == memberId), Arg.Any <CancellationToken>(), Arg.Any <IRequestContext>()); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Assert.That(conn.ReceivedCalls().Count(c => c.GetMethodInfo().Name == nameof(Connection.SendAsync) && (c.GetArguments()[0] as HeartbeatRequest) != null), Is.AtLeast(2)); }
/// <inheritdoc /> public void JoinGroup(SessionInfo session, JoinGroupRequest request, CancellationToken cancellationToken) { if (session == null) { throw new InvalidOperationException("Session is null!"); } if (request == null) { throw new InvalidOperationException("Request is null!"); } var user = _userManager.GetUserById(session.UserId); // Locking required to access list of groups. lock (_groupsLock) { _groups.TryGetValue(request.GroupId, out Group group); if (group == null) { _logger.LogWarning("Session {SessionId} tried to join group {GroupId} that does not exist.", session.Id, request.GroupId); var error = new GroupUpdate <string>(Guid.Empty, GroupUpdateType.GroupDoesNotExist, string.Empty); _sessionManager.SendSyncPlayGroupUpdate(session, error, CancellationToken.None); return; } // Group lock required to let other requests end first. lock (group) { if (!group.HasAccessToPlayQueue(user)) { _logger.LogWarning("Session {SessionId} tried to join group {GroupId} but does not have access to some content of the playing queue.", session.Id, group.GroupId.ToString()); var error = new GroupUpdate <string>(group.GroupId, GroupUpdateType.LibraryAccessDenied, string.Empty); _sessionManager.SendSyncPlayGroupUpdate(session, error, CancellationToken.None); return; } if (_sessionToGroupMap.TryGetValue(session.Id, out var existingGroup)) { if (existingGroup.GroupId.Equals(request.GroupId)) { // Restore session. UpdateSessionsCounter(session.UserId, 1); group.SessionJoin(session, request, cancellationToken); return; } var leaveGroupRequest = new LeaveGroupRequest(); LeaveGroup(session, leaveGroupRequest, cancellationToken); } if (!_sessionToGroupMap.TryAdd(session.Id, group)) { throw new InvalidOperationException("Could not add session to group!"); } UpdateSessionsCounter(session.UserId, 1); group.SessionJoin(session, request, cancellationToken); } } }
public async Task <SignalRServerResponse> Join(JoinGroupRequest request) { await _connection.StartAsync(); return(await MutableCallSameMethodOnTheHub <SignalRServerResponse>(_connection, new object[] { request })); }
public ValueTask <JoinGroupResponse> JoinGroup(JoinGroupRequest request) => SendRequest(ApiKey.JoinGroup, 5, request, new JoinGroupRequestWriter(), new JoinGroupResponseReader());