From 5cd5a7d4cebe134d8256d4a1b6eadff760fbb2a7 Mon Sep 17 00:00:00 2001 From: Greenback Date: Sat, 28 Nov 2020 00:25:20 +0000 Subject: [PATCH] Removed Lazy implementation. --- .../HttpServer/WebSocketManager.cs | 31 +++++++++---------- .../Session/ISessionWebSocketListener.cs | 30 ++++++++++++++++++ .../Session/SessionWebSocketListener.cs | 27 ++++++---------- .../ActivityLogWebSocketListener.cs | 2 +- .../IActivityLogWebSocketListener.cs | 10 ++++++ .../IScheduledTasksWebSocketListener.cs | 10 ++++++ .../ISessionInfoWebSocketListener.cs | 10 ++++++ .../ScheduledTasksWebSocketListener.cs | 8 ++--- .../SessionInfoWebSocketListener.cs | 2 +- Jellyfin.Server/CoreAppHost.cs | 13 +++----- .../Middleware/WebSocketHandlerMiddleware.cs | 11 +------ .../Net/IWebSocketManager.cs | 5 --- 12 files changed, 95 insertions(+), 64 deletions(-) create mode 100644 Emby.Server.Implementations/Session/ISessionWebSocketListener.cs create mode 100644 Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs create mode 100644 Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs create mode 100644 Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index 71ece80a75..5518fb95aa 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -4,7 +4,9 @@ using System; using System.Collections.Generic; using System.Net.WebSockets; using System.Threading.Tasks; -using Jellyfin.Data.Events; +using Emby.Server.Implementations.Session; +using Jellyfin.Api.WebSocketListeners; +using MediaBrowser.Controller; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; @@ -13,24 +15,21 @@ namespace Emby.Server.Implementations.HttpServer { public class WebSocketManager : IWebSocketManager { - private readonly Lazy> _webSocketListeners; + private readonly IServerApplicationHost _appHost; private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; - private bool _disposed = false; public WebSocketManager( - Lazy> webSocketListeners, + IServerApplicationHost appHost, ILogger logger, ILoggerFactory loggerFactory) { - _webSocketListeners = webSocketListeners; + _appHost = appHost; _logger = logger; _loggerFactory = loggerFactory; } - public event EventHandler> WebSocketConnected; - /// public async Task WebSocketRequestHandler(HttpContext context) { @@ -39,6 +38,8 @@ namespace Emby.Server.Implementations.HttpServer return; } + var listener = _appHost.Resolve(); + try { _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress); @@ -54,7 +55,7 @@ namespace Emby.Server.Implementations.HttpServer OnReceive = ProcessWebSocketMessageReceived }; - WebSocketConnected?.Invoke(this, new GenericEventArgs(connection)); + listener?.ProcessWebSocketConnected(connection); await connection.ProcessAsync().ConfigureAwait(false); _logger.LogInformation("WS {IP} closed", context.Connection.RemoteIpAddress); @@ -80,16 +81,12 @@ namespace Emby.Server.Implementations.HttpServer return Task.CompletedTask; } - IEnumerable GetTasks() - { - var listeners = _webSocketListeners.Value; - foreach (var x in listeners) - { - yield return x.ProcessMessageAsync(result); - } - } + Parallel.Invoke( + () => _appHost.Resolve(), + () => _appHost.Resolve(), + () => _appHost.Resolve()); - return Task.WhenAll(GetTasks()); + return Task.CompletedTask; } } } diff --git a/Emby.Server.Implementations/Session/ISessionWebSocketListener.cs b/Emby.Server.Implementations/Session/ISessionWebSocketListener.cs new file mode 100644 index 0000000000..9b0b28e6ee --- /dev/null +++ b/Emby.Server.Implementations/Session/ISessionWebSocketListener.cs @@ -0,0 +1,30 @@ +namespace Emby.Server.Implementations.Session +{ + using System.Threading.Tasks; + using Jellyfin.Data.Events; + using MediaBrowser.Controller.Net; + + /// + /// Defines the . + /// + public interface ISessionWebSocketListener + { + /// + /// Runs processes due to a WebSocket connection event. + /// + /// The instance. + void ProcessWebSocketConnected(IWebSocketConnection websocketConnection); + + /// + /// Disposes the object. + /// + void Dispose(); + + /// + /// Processes a message. + /// + /// The . + /// A . + Task ProcessMessageAsync(WebSocketMessageInfo message); + } +} diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index a5f8479537..8f81ee1948 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Session /// /// Class SessionWebSocketListener. /// - public sealed class SessionWebSocketListener : IWebSocketListener, IDisposable + public sealed class SessionWebSocketListener : ISessionWebSocketListener, IDisposable { /// /// The timeout in seconds after which a WebSocket is considered to be lost. @@ -45,15 +45,13 @@ namespace Emby.Server.Implementations.Session private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; - private readonly IWebSocketManager _webSocketManager; - /// /// The KeepAlive cancellation token. /// private CancellationTokenSource _keepAliveCancellationToken; /// - /// Lock used for accesing the KeepAlive cancellation token. + /// Lock used for accessing the KeepAlive cancellation token. /// private readonly object _keepAliveLock = new object(); @@ -63,7 +61,7 @@ namespace Emby.Server.Implementations.Session private readonly HashSet _webSockets = new HashSet(); /// - /// Lock used for accesing the WebSockets watchlist. + /// Lock used for accessing the WebSockets watchlist. /// private readonly object _webSocketsLock = new object(); @@ -73,32 +71,28 @@ namespace Emby.Server.Implementations.Session /// The logger. /// The session manager. /// The logger factory. - /// The HTTP server. public SessionWebSocketListener( ILogger logger, ISessionManager sessionManager, - ILoggerFactory loggerFactory, - IWebSocketManager webSocketManager) + ILoggerFactory loggerFactory) { _logger = logger; _sessionManager = sessionManager; _loggerFactory = loggerFactory; - _webSocketManager = webSocketManager; - - webSocketManager.WebSocketConnected += OnServerManagerWebSocketConnected; } - private async void OnServerManagerWebSocketConnected(object sender, GenericEventArgs e) + /// + public async void ProcessWebSocketConnected(IWebSocketConnection websocketConnection) { - var session = GetSession(e.Argument.QueryString, e.Argument.RemoteEndPoint.ToString()); + var session = GetSession(websocketConnection.QueryString, websocketConnection.RemoteEndPoint.ToString()); if (session != null) { - EnsureController(session, e.Argument); - await KeepAliveWebSocket(e.Argument).ConfigureAwait(false); + EnsureController(session, websocketConnection); + await KeepAliveWebSocket(websocketConnection).ConfigureAwait(false); } else { - _logger.LogWarning("Unable to determine session based on query string: {0}", e.Argument.QueryString); + _logger.LogWarning("Unable to determine session based on query string: {Querystring}", websocketConnection.QueryString); } } @@ -122,7 +116,6 @@ namespace Emby.Server.Implementations.Session /// public void Dispose() { - _webSocketManager.WebSocketConnected -= OnServerManagerWebSocketConnected; StopKeepAlive(); } diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs index 288e03fcff..3dc45b1459 100644 --- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs @@ -11,7 +11,7 @@ namespace Jellyfin.Api.WebSocketListeners /// /// Class SessionInfoWebSocketListener. /// - public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener + public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener, IActivityLogWebSocketListener { /// /// The _kernel. diff --git a/Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs new file mode 100644 index 0000000000..b23022e71d --- /dev/null +++ b/Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs @@ -0,0 +1,10 @@ +#pragma warning disable CA1040 // Avoid empty interfaces +namespace Jellyfin.Api.WebSocketListeners +{ + /// + /// Defines the . + /// + public interface IActivityLogWebSocketListener + { + } +} diff --git a/Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs new file mode 100644 index 0000000000..425d61dfa4 --- /dev/null +++ b/Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs @@ -0,0 +1,10 @@ +#pragma warning disable CA1040 // Avoid empty interfaces +namespace Jellyfin.Api.WebSocketListeners +{ + /// + /// Defines the . + /// + public interface IScheduledTasksWebSocketListener + { + } +} diff --git a/Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs new file mode 100644 index 0000000000..33636dc06d --- /dev/null +++ b/Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs @@ -0,0 +1,10 @@ +#pragma warning disable CA1040 // Avoid empty interfaces +namespace Jellyfin.Api.WebSocketListeners +{ + /// + /// Defines the . + /// + public interface ISessionInfoWebSocketListener + { + } +} diff --git a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs index 94df23e569..eafa9c71f0 100644 --- a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs @@ -12,7 +12,7 @@ namespace Jellyfin.Api.WebSocketListeners /// /// Class ScheduledTasksWebSocketListener. /// - public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> + public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState>, IScheduledTasksWebSocketListener { /// /// Gets or sets the task manager. @@ -66,19 +66,19 @@ namespace Jellyfin.Api.WebSocketListeners private void OnTaskCompleted(object? sender, TaskCompletionEventArgs e) { - SendData(true); + SendData(true).GetAwaiter().GetResult(); e.Task.TaskProgress -= OnTaskProgress; } private void OnTaskExecuting(object? sender, GenericEventArgs e) { - SendData(true); + SendData(true).GetAwaiter().GetResult(); e.Argument.TaskProgress += OnTaskProgress; } private void OnTaskProgress(object? sender, GenericEventArgs e) { - SendData(false); + SendData(false).GetAwaiter().GetResult(); } } } diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs index d996ac69f9..be701be45e 100644 --- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs @@ -11,7 +11,7 @@ namespace Jellyfin.Api.WebSocketListeners /// /// Class SessionInfoWebSocketListener. /// - public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> + public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState>, ISessionInfoWebSocketListener { private readonly ISessionManager _sessionManager; diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 4b44537a59..100f3619a6 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,7 +11,6 @@ using Jellyfin.Server.Implementations; using Jellyfin.Server.Implementations.Activity; using Jellyfin.Server.Implementations.Events; using Jellyfin.Server.Implementations.Users; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.BaseItemManager; using MediaBrowser.Controller.Drawing; @@ -82,14 +81,10 @@ namespace Jellyfin.Server ServiceCollection.AddSingleton(); ServiceCollection.AddSingleton(); - ServiceCollection.AddScoped(); - ServiceCollection.AddScoped(); - ServiceCollection.AddScoped(); - // This one has to be last as DI will select it for parameterization. - ServiceCollection.AddScoped(); - - // TODO fix circular dependency on IWebSocketManager - ServiceCollection.AddScoped(serviceProvider => new Lazy>(serviceProvider.GetRequiredService>)); + ServiceCollection.AddScoped(); + ServiceCollection.AddScoped(); + ServiceCollection.AddScoped(); + ServiceCollection.AddScoped(); base.RegisterServices(); } diff --git a/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs b/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs index 53f32bebd1..ba0abfbdd4 100644 --- a/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs +++ b/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs @@ -25,19 +25,10 @@ namespace Jellyfin.Server.Middleware /// /// The current HTTP context. /// The WebSocket connection manager. - /// Session manager instance. /// The async task. public async Task Invoke( HttpContext httpContext, - IWebSocketManager webSocketManager, -#pragma warning disable CA1801 -#pragma warning disable IDE0060 - // TODO: Workaround. see https://github.com/jellyfin/jellyfin/pull/3194 - // Do not remove this parameter. It uses DI to create a SessionWebSocketListener which is - // required for webSocketManager events. - IWebSocketListener websocketListener) -#pragma warning restore IDE0060 // Remove unused parameter -#pragma warning restore CA1801 + IWebSocketManager webSocketManager) { if (!httpContext.WebSockets.IsWebSocketRequest) { diff --git a/MediaBrowser.Controller/Net/IWebSocketManager.cs b/MediaBrowser.Controller/Net/IWebSocketManager.cs index ce74173e70..d3f31de7c8 100644 --- a/MediaBrowser.Controller/Net/IWebSocketManager.cs +++ b/MediaBrowser.Controller/Net/IWebSocketManager.cs @@ -11,11 +11,6 @@ namespace MediaBrowser.Controller.Net /// public interface IWebSocketManager { - /// - /// Occurs when [web socket connected]. - /// - event EventHandler> WebSocketConnected; - /// /// The HTTP request handler. ///