diff options
| author | cvium <clausvium@gmail.com> | 2020-11-28 09:50:16 +0100 |
|---|---|---|
| committer | cvium <clausvium@gmail.com> | 2020-11-28 09:50:16 +0100 |
| commit | 1a0d8aef80a066fdefec4d757d5dcba0dfe0a03c (patch) | |
| tree | 5b1fafe68e6d8207fdbdb29541e43a40f55494cc | |
| parent | 5cd5a7d4cebe134d8256d4a1b6eadff760fbb2a7 (diff) | |
Revert "Removed Lazy implementation."
12 files changed, 64 insertions, 95 deletions
diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index 5518fb95a..71ece80a7 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -4,9 +4,7 @@ using System; using System.Collections.Generic; using System.Net.WebSockets; using System.Threading.Tasks; -using Emby.Server.Implementations.Session; -using Jellyfin.Api.WebSocketListeners; -using MediaBrowser.Controller; +using Jellyfin.Data.Events; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; @@ -15,21 +13,24 @@ namespace Emby.Server.Implementations.HttpServer { public class WebSocketManager : IWebSocketManager { - private readonly IServerApplicationHost _appHost; + private readonly Lazy<IEnumerable<IWebSocketListener>> _webSocketListeners; private readonly ILogger<WebSocketManager> _logger; private readonly ILoggerFactory _loggerFactory; + private bool _disposed = false; public WebSocketManager( - IServerApplicationHost appHost, + Lazy<IEnumerable<IWebSocketListener>> webSocketListeners, ILogger<WebSocketManager> logger, ILoggerFactory loggerFactory) { - _appHost = appHost; + _webSocketListeners = webSocketListeners; _logger = logger; _loggerFactory = loggerFactory; } + public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected; + /// <inheritdoc /> public async Task WebSocketRequestHandler(HttpContext context) { @@ -38,8 +39,6 @@ namespace Emby.Server.Implementations.HttpServer return; } - var listener = _appHost.Resolve<ISessionWebSocketListener>(); - try { _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress); @@ -55,7 +54,7 @@ namespace Emby.Server.Implementations.HttpServer OnReceive = ProcessWebSocketMessageReceived }; - listener?.ProcessWebSocketConnected(connection); + WebSocketConnected?.Invoke(this, new GenericEventArgs<IWebSocketConnection>(connection)); await connection.ProcessAsync().ConfigureAwait(false); _logger.LogInformation("WS {IP} closed", context.Connection.RemoteIpAddress); @@ -81,12 +80,16 @@ namespace Emby.Server.Implementations.HttpServer return Task.CompletedTask; } - Parallel.Invoke( - () => _appHost.Resolve<IActivityLogWebSocketListener>(), - () => _appHost.Resolve<IScheduledTasksWebSocketListener>(), - () => _appHost.Resolve<ISessionInfoWebSocketListener>()); + IEnumerable<Task> GetTasks() + { + var listeners = _webSocketListeners.Value; + foreach (var x in listeners) + { + yield return x.ProcessMessageAsync(result); + } + } - return Task.CompletedTask; + return Task.WhenAll(GetTasks()); } } } diff --git a/Emby.Server.Implementations/Session/ISessionWebSocketListener.cs b/Emby.Server.Implementations/Session/ISessionWebSocketListener.cs deleted file mode 100644 index 9b0b28e6e..000000000 --- a/Emby.Server.Implementations/Session/ISessionWebSocketListener.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace Emby.Server.Implementations.Session -{ - using System.Threading.Tasks; - using Jellyfin.Data.Events; - using MediaBrowser.Controller.Net; - - /// <summary> - /// Defines the <see cref="ISessionWebSocketListener" />. - /// </summary> - public interface ISessionWebSocketListener - { - /// <summary> - /// Runs processes due to a WebSocket connection event. - /// </summary> - /// <param name="websocketConnection">The <see cref="IWebSocketConnection"/> instance.</param> - void ProcessWebSocketConnected(IWebSocketConnection websocketConnection); - - /// <summary> - /// Disposes the object. - /// </summary> - void Dispose(); - - /// <summary> - /// Processes a message. - /// </summary> - /// <param name="message">The <see cref="WebSocketMessageInfo"/>.</param> - /// <returns>A <see cref="Task"/>.</returns> - Task ProcessMessageAsync(WebSocketMessageInfo message); - } -} diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index 8f81ee194..a5f847953 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Session /// <summary> /// Class SessionWebSocketListener. /// </summary> - public sealed class SessionWebSocketListener : ISessionWebSocketListener, IDisposable + public sealed class SessionWebSocketListener : IWebSocketListener, IDisposable { /// <summary> /// The timeout in seconds after which a WebSocket is considered to be lost. @@ -45,13 +45,15 @@ namespace Emby.Server.Implementations.Session private readonly ILogger<SessionWebSocketListener> _logger; private readonly ILoggerFactory _loggerFactory; + private readonly IWebSocketManager _webSocketManager; + /// <summary> /// The KeepAlive cancellation token. /// </summary> private CancellationTokenSource _keepAliveCancellationToken; /// <summary> - /// Lock used for accessing the KeepAlive cancellation token. + /// Lock used for accesing the KeepAlive cancellation token. /// </summary> private readonly object _keepAliveLock = new object(); @@ -61,7 +63,7 @@ namespace Emby.Server.Implementations.Session private readonly HashSet<IWebSocketConnection> _webSockets = new HashSet<IWebSocketConnection>(); /// <summary> - /// Lock used for accessing the WebSockets watchlist. + /// Lock used for accesing the WebSockets watchlist. /// </summary> private readonly object _webSocketsLock = new object(); @@ -71,28 +73,32 @@ namespace Emby.Server.Implementations.Session /// <param name="logger">The logger.</param> /// <param name="sessionManager">The session manager.</param> /// <param name="loggerFactory">The logger factory.</param> + /// <param name="webSocketManager">The HTTP server.</param> public SessionWebSocketListener( ILogger<SessionWebSocketListener> logger, ISessionManager sessionManager, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + IWebSocketManager webSocketManager) { _logger = logger; _sessionManager = sessionManager; _loggerFactory = loggerFactory; + _webSocketManager = webSocketManager; + + webSocketManager.WebSocketConnected += OnServerManagerWebSocketConnected; } - /// <inheritdoc/> - public async void ProcessWebSocketConnected(IWebSocketConnection websocketConnection) + private async void OnServerManagerWebSocketConnected(object sender, GenericEventArgs<IWebSocketConnection> e) { - var session = GetSession(websocketConnection.QueryString, websocketConnection.RemoteEndPoint.ToString()); + var session = GetSession(e.Argument.QueryString, e.Argument.RemoteEndPoint.ToString()); if (session != null) { - EnsureController(session, websocketConnection); - await KeepAliveWebSocket(websocketConnection).ConfigureAwait(false); + EnsureController(session, e.Argument); + await KeepAliveWebSocket(e.Argument).ConfigureAwait(false); } else { - _logger.LogWarning("Unable to determine session based on query string: {Querystring}", websocketConnection.QueryString); + _logger.LogWarning("Unable to determine session based on query string: {0}", e.Argument.QueryString); } } @@ -116,6 +122,7 @@ namespace Emby.Server.Implementations.Session /// <inheritdoc /> public void Dispose() { + _webSocketManager.WebSocketConnected -= OnServerManagerWebSocketConnected; StopKeepAlive(); } diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs index 3dc45b145..288e03fcf 100644 --- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs @@ -11,7 +11,7 @@ namespace Jellyfin.Api.WebSocketListeners /// <summary> /// Class SessionInfoWebSocketListener. /// </summary> - public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<ActivityLogEntry[], WebSocketListenerState>, IActivityLogWebSocketListener + public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<ActivityLogEntry[], WebSocketListenerState> { /// <summary> /// The _kernel. diff --git a/Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs deleted file mode 100644 index b23022e71..000000000 --- a/Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs +++ /dev/null @@ -1,10 +0,0 @@ -#pragma warning disable CA1040 // Avoid empty interfaces -namespace Jellyfin.Api.WebSocketListeners -{ - /// <summary> - /// Defines the <see cref="IActivityLogWebSocketListener" />. - /// </summary> - public interface IActivityLogWebSocketListener - { - } -} diff --git a/Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs deleted file mode 100644 index 425d61dfa..000000000 --- a/Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs +++ /dev/null @@ -1,10 +0,0 @@ -#pragma warning disable CA1040 // Avoid empty interfaces -namespace Jellyfin.Api.WebSocketListeners -{ - /// <summary> - /// Defines the <see cref="IScheduledTasksWebSocketListener" />. - /// </summary> - public interface IScheduledTasksWebSocketListener - { - } -} diff --git a/Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs deleted file mode 100644 index 33636dc06..000000000 --- a/Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs +++ /dev/null @@ -1,10 +0,0 @@ -#pragma warning disable CA1040 // Avoid empty interfaces -namespace Jellyfin.Api.WebSocketListeners -{ - /// <summary> - /// Defines the <see cref="ISessionInfoWebSocketListener" />. - /// </summary> - public interface ISessionInfoWebSocketListener - { - } -} diff --git a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs index eafa9c71f..94df23e56 100644 --- a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs @@ -12,7 +12,7 @@ namespace Jellyfin.Api.WebSocketListeners /// <summary> /// Class ScheduledTasksWebSocketListener. /// </summary> - public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState>, IScheduledTasksWebSocketListener + public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState> { /// <summary> /// Gets or sets the task manager. @@ -66,19 +66,19 @@ namespace Jellyfin.Api.WebSocketListeners private void OnTaskCompleted(object? sender, TaskCompletionEventArgs e) { - SendData(true).GetAwaiter().GetResult(); + SendData(true); e.Task.TaskProgress -= OnTaskProgress; } private void OnTaskExecuting(object? sender, GenericEventArgs<IScheduledTaskWorker> e) { - SendData(true).GetAwaiter().GetResult(); + SendData(true); e.Argument.TaskProgress += OnTaskProgress; } private void OnTaskProgress(object? sender, GenericEventArgs<double> e) { - SendData(false).GetAwaiter().GetResult(); + SendData(false); } } } diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs index be701be45..d996ac69f 100644 --- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs @@ -11,7 +11,7 @@ namespace Jellyfin.Api.WebSocketListeners /// <summary> /// Class SessionInfoWebSocketListener. /// </summary> - public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfo>, WebSocketListenerState>, ISessionInfoWebSocketListener + public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfo>, WebSocketListenerState> { private readonly ISessionManager _sessionManager; diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 100f3619a..4b44537a5 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,6 +11,7 @@ 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; @@ -81,10 +82,14 @@ namespace Jellyfin.Server ServiceCollection.AddSingleton<IUserManager, UserManager>(); ServiceCollection.AddSingleton<IDisplayPreferencesManager, DisplayPreferencesManager>(); - ServiceCollection.AddScoped<IActivityLogWebSocketListener, ActivityLogWebSocketListener>(); - ServiceCollection.AddScoped<IScheduledTasksWebSocketListener, ScheduledTasksWebSocketListener>(); - ServiceCollection.AddScoped<ISessionInfoWebSocketListener, SessionInfoWebSocketListener>(); - ServiceCollection.AddScoped<ISessionWebSocketListener, SessionWebSocketListener>(); + ServiceCollection.AddScoped<IWebSocketListener, ActivityLogWebSocketListener>(); + ServiceCollection.AddScoped<IWebSocketListener, ScheduledTasksWebSocketListener>(); + ServiceCollection.AddScoped<IWebSocketListener, SessionInfoWebSocketListener>(); + // This one has to be last as DI will select it for parameterization. + ServiceCollection.AddScoped<IWebSocketListener, SessionWebSocketListener>(); + + // TODO fix circular dependency on IWebSocketManager + ServiceCollection.AddScoped(serviceProvider => new Lazy<IEnumerable<IWebSocketListener>>(serviceProvider.GetRequiredService<IEnumerable<IWebSocketListener>>)); base.RegisterServices(); } diff --git a/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs b/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs index ba0abfbdd..53f32bebd 100644 --- a/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs +++ b/Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs @@ -25,10 +25,19 @@ namespace Jellyfin.Server.Middleware /// </summary> /// <param name="httpContext">The current HTTP context.</param> /// <param name="webSocketManager">The WebSocket connection manager.</param> + /// <param name="websocketListener">Session manager instance.</param> /// <returns>The async task.</returns> public async Task Invoke( HttpContext httpContext, - IWebSocketManager webSocketManager) + 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 { if (!httpContext.WebSockets.IsWebSocketRequest) { diff --git a/MediaBrowser.Controller/Net/IWebSocketManager.cs b/MediaBrowser.Controller/Net/IWebSocketManager.cs index d3f31de7c..ce74173e7 100644 --- a/MediaBrowser.Controller/Net/IWebSocketManager.cs +++ b/MediaBrowser.Controller/Net/IWebSocketManager.cs @@ -12,6 +12,11 @@ namespace MediaBrowser.Controller.Net public interface IWebSocketManager { /// <summary> + /// Occurs when [web socket connected]. + /// </summary> + event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected; + + /// <summary> /// The HTTP request handler. /// </summary> /// <param name="context">The current HTTP context.</param> |
