public override Task OnDisconnectedAsync(HubConnectionContext connection)
        {
            _connections.Remove(connection);

            var tasks = new List <Task>();

            var feature = connection.Features.Get <IRedisFeature>();

            var redisSubscriptions = feature.Subscriptions;

            if (redisSubscriptions != null)
            {
                foreach (var subscription in redisSubscriptions)
                {
                    RedisLog.Unsubscribe(_logger, subscription);
                    tasks.Add(_bus.UnsubscribeAsync(subscription));
                }
            }

            var groupNames = feature.Groups;

            if (groupNames != null)
            {
                // Copy the groups to an array here because they get removed from this collection
                // in RemoveGroupAsync
                foreach (var group in groupNames.ToArray())
                {
                    // Use RemoveGroupAsyncCore because the connection is local and we don't want to
                    // accidentally go to other servers with our remove request.
                    tasks.Add(RemoveGroupAsyncCore(connection, group));
                }
            }

            return(Task.WhenAll(tasks));
        }
예제 #2
0
        public override Task OnDisconnectedAsync(HubConnectionContext connection)
        {
            _connections.Remove(connection);

            var tasks = new List <Task>();

            var connectionChannel = _channels.Connection(connection.ConnectionId);

            RedisLog.Unsubscribe(_logger, connectionChannel);
            tasks.Add(_bus.UnsubscribeAsync(connectionChannel));

            var feature    = connection.Features.Get <IRedisFeature>();
            var groupNames = feature.Groups;

            if (groupNames != null)
            {
                // Copy the groups to an array here because they get removed from this collection
                // in RemoveFromGroupAsync
                foreach (var group in groupNames.ToArray())
                {
                    // Use RemoveGroupAsyncCore because the connection is local and we don't want to
                    // accidentally go to other servers with our remove request.
                    tasks.Add(RemoveGroupAsyncCore(connection, group));
                }
            }

            if (!string.IsNullOrEmpty(connection.UserIdentifier))
            {
                tasks.Add(RemoveUserAsync(connection));
            }

            return(Task.WhenAll(tasks));
        }
예제 #3
0
        private Task RemoveUserAsync(HubConnectionContext connection)
        {
            var userChannel = _channels.User(connection.UserIdentifier);

            return(_users.RemoveSubscriptionAsync(userChannel, connection, async channelName =>
            {
                RedisLog.Unsubscribe(_logger, channelName);
                await _bus.UnsubscribeAsync(channelName);
            }));
        }
예제 #4
0
        /// <summary>
        /// This takes <see cref="HubConnectionContext"/> because we want to remove the connection from the
        /// _connections list in OnDisconnectedAsync and still be able to remove groups with this method.
        /// </summary>
        private async Task RemoveGroupAsyncCore(HubConnectionContext connection, string groupName)
        {
            var groupChannel = _channels.Group(groupName);

            await _groups.RemoveSubscriptionAsync(groupChannel, connection, async channelName =>
            {
                RedisLog.Unsubscribe(_logger, channelName);
                await _bus.UnsubscribeAsync(channelName);
            });

            var feature    = connection.Features.Get <IRedisFeature>();
            var groupNames = feature.Groups;

            if (groupNames != null)
            {
                lock (groupNames)
                {
                    groupNames.Remove(groupName);
                }
            }
        }
        /// <summary>
        /// This takes <see cref="HubConnectionContext"/> because we want to remove the connection from the
        /// _connections list in OnDisconnectedAsync and still be able to remove groups with this method.
        /// </summary>
        private async Task RemoveGroupAsyncCore(HubConnectionContext connection, string groupName)
        {
            var groupChannel = _channels.Group(groupName);

            if (!_groups.TryGetValue(groupChannel, out var group))
            {
                return;
            }

            var feature    = connection.Features.Get <IRedisFeature>();
            var groupNames = feature.Groups;

            if (groupNames != null)
            {
                lock (groupNames)
                {
                    groupNames.Remove(groupName);
                }
            }

            await group.Lock.WaitAsync();

            try
            {
                if (group.Connections.Count > 0)
                {
                    group.Connections.Remove(connection);

                    if (group.Connections.Count == 0)
                    {
                        RedisLog.Unsubscribe(_logger, groupChannel);
                        await _bus.UnsubscribeAsync(groupChannel);
                    }
                }
            }
            finally
            {
                group.Lock.Release();
            }
        }