<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MorseL.Common;
using MorseL.Common.Serialization;
using MorseL.Internal;
using MorseL.Scaleout;
using MorseL.Sockets;

namespace MorseL
{
    public class HubWebSocketHandler<THub> : HubWebSocketHandler<THub, IClientInvoker> where THub : Hub<IClientInvoker>
    {
        public HubWebSocketHandler(IServiceProvider services, ILoggerFactory loggerFactory, IServiceScopeFactory serviceScopeFactory)
            : base(services, loggerFactory)
        {
        }
    }

    public class HubWebSocketHandler<THub, TClient> : WebSocketHandler where THub : Hub<TClient>
    {
        private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase);

        private readonly IServiceProvider _services;
        private readonly IServiceScopeFactory _serviceScopeFactory;
        private readonly ILogger<HubWebSocketHandler<THub, TClient>> _logger;
        private readonly IAuthorizeData[] _authorizeData;
        private readonly IScaleoutBackPlane _scaleoutBackPlane;

        public HubWebSocketHandler(IServiceProvider services, ILoggerFactory loggerFactory) : base(services, loggerFactory)
        {
            _services = services;
            _logger = loggerFactory.CreateLogger<HubWebSocketHandler<THub, TClient>>();
            _serviceScopeFactory = services.GetRequiredService<IServiceScopeFactory>();
            _scaleoutBackPlane = services.GetService<IScaleoutBackPlane>();

            _authorizeData = typeof(THub).GetTypeInfo().GetCustomAttributes().OfType<IAuthorizeData>().ToArray();
            DiscoverHubMethods();
        }

        public override async Task OnConnectedAsync(Connection connection)
        {
            try
            {
                using (var scope = _serviceScopeFactory.CreateScope())
                {
                    var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, TClient>>();
                    var hub = hubActivator.Create();
                    try
                    {
                        InitializeHub(hub, connection);
                        await hub.OnConnectedAsync(connection);
                    }
                    finally
                    {
                        hubActivator.Release(hub);
                    }
                }

                await _scaleoutBackPlane.Register(connection);
            }
            catch (Exception ex)
            {
                _logger.LogError(0, ex, $"Error when invoking OnConnectedAsync on hub for {connection.Id}");
                throw;
            }
        }

        public override async Task OnDisconnectedAsync(Connection connection, Exception exception)
        {
            try
            {
                using (var scope = _serviceScopeFactory.CreateScope())
                {
                    var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, TClient>>();
                    var hub = hubActivator.Create();
                    try
                    {
                        InitializeHub(hub, connection);
                        await hub.OnDisconnectedAsync(exception);
                    }
                    finally
                    {
                        hubActivator.Release(hub);
                    }
                }

                await _scaleoutBackPlane.UnRegister(connection);
            }
            catch (Exception ex)
            {
                _logger.LogError(0, ex, $"Error when invoking OnDisconnectedAsync on hub for {connection.Id}");
                throw;
            }
        }

        private void InitializeHub(THub hub, Connection connection)
        {
            hub.Clients = ActivatorUtilities.CreateInstance<ClientsDispatcher>(_services);
            hub.Context = new HubCallerContext(connection);
            hub.Groups = new GroupsManager();
        }

        private void DiscoverHubMethods()
        {
            var hubType = typeof(THub);<commit_msg>Pushing scaleout unregister call to finally in OnDisconnectAsync<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MorseL.Common;
using MorseL.Common.Serialization;
using MorseL.Internal;
using MorseL.Scaleout;
using MorseL.Sockets;

namespace MorseL
{
    public class HubWebSocketHandler<THub> : HubWebSocketHandler<THub, IClientInvoker> where THub : Hub<IClientInvoker>
    {
        public HubWebSocketHandler(IServiceProvider services, ILoggerFactory loggerFactory, IServiceScopeFactory serviceScopeFactory)
            : base(services, loggerFactory)
        {
        }
    }

    public class HubWebSocketHandler<THub, TClient> : WebSocketHandler where THub : Hub<TClient>
    {
        private readonly Dictionary<string, HubMethodDescriptor> _methods = new Dictionary<string, HubMethodDescriptor>(StringComparer.OrdinalIgnoreCase);

        private readonly IServiceProvider _services;
        private readonly IServiceScopeFactory _serviceScopeFactory;
        private readonly ILogger<HubWebSocketHandler<THub, TClient>> _logger;
        private readonly IAuthorizeData[] _authorizeData;
        private readonly IScaleoutBackPlane _scaleoutBackPlane;

        public HubWebSocketHandler(IServiceProvider services, ILoggerFactory loggerFactory) : base(services, loggerFactory)
        {
            _services = services;
            _logger = loggerFactory.CreateLogger<HubWebSocketHandler<THub, TClient>>();
            _serviceScopeFactory = services.GetRequiredService<IServiceScopeFactory>();
            _scaleoutBackPlane = services.GetService<IScaleoutBackPlane>();

            _authorizeData = typeof(THub).GetTypeInfo().GetCustomAttributes().OfType<IAuthorizeData>().ToArray();
            DiscoverHubMethods();
        }

        public override async Task OnConnectedAsync(Connection connection)
        {
            try
            {
                using (var scope = _serviceScopeFactory.CreateScope())
                {
                    var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, TClient>>();
                    var hub = hubActivator.Create();
                    try
                    {
                        InitializeHub(hub, connection);
                        await hub.OnConnectedAsync(connection);
                    }
                    finally
                    {
                        hubActivator.Release(hub);
                    }
                }

                await _scaleoutBackPlane.Register(connection);
            }
            catch (Exception ex)
            {
                _logger.LogError(0, ex, $"Error when invoking OnConnectedAsync on hub for {connection.Id}");
                throw;
            }
        }

        public override async Task OnDisconnectedAsync(Connection connection, Exception exception)
        {
            try
            {
                using (var scope = _serviceScopeFactory.CreateScope())
                {
                    var hubActivator = scope.ServiceProvider.GetRequiredService<IHubActivator<THub, TClient>>();
                    var hub = hubActivator.Create();
                    try
                    {
                        InitializeHub(hub, connection);
                        await hub.OnDisconnectedAsync(exception);
                    }
                    finally
                    {
                        hubActivator.Release(hub);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(0, ex, $"Error when invoking OnDisconnectedAsync on hub for {connection.Id}");
                throw;
            }
            finally
            {
                await _scaleoutBackPlane.UnRegister(connection);
            }
        }

        private void InitializeHub(THub hub, Connection connection)
        {
            hub.Clients = ActivatorUtilities.CreateInstance<ClientsDispatcher>(_services);
            hub.Context = new HubCallerContext(connection);
            hub.Groups = new GroupsManager();
        }

        private void DiscoverHubMethods()
        {
            var hubType = typeof(THub);
{'fraction_non_alphanumeric': 0.07177252923641367, 'fraction_numerical': 0.00045861041045631735, 'mean_word_length': 1.9409979770734997, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3608534', 'n_tokens_mistral': 2086, 'n_tokens_neox': 2017, 'n_words': 421}