Przeglądaj źródła

Removed Lazy implementation.

Greenback 4 lat temu
rodzic
commit
5cd5a7d4ce

+ 14 - 17
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<IEnumerable<IWebSocketListener>> _webSocketListeners;
+        private readonly IServerApplicationHost _appHost;
         private readonly ILogger<WebSocketManager> _logger;
         private readonly ILoggerFactory _loggerFactory;
-
         private bool _disposed = false;
 
         public WebSocketManager(
-            Lazy<IEnumerable<IWebSocketListener>> webSocketListeners,
+            IServerApplicationHost appHost,
             ILogger<WebSocketManager> logger,
             ILoggerFactory loggerFactory)
         {
-            _webSocketListeners = webSocketListeners;
+            _appHost = appHost;
             _logger = logger;
             _loggerFactory = loggerFactory;
         }
 
-        public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
-
         /// <inheritdoc />
         public async Task WebSocketRequestHandler(HttpContext context)
         {
@@ -39,6 +38,8 @@ namespace Emby.Server.Implementations.HttpServer
                 return;
             }
 
+            var listener = _appHost.Resolve<ISessionWebSocketListener>();
+
             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<IWebSocketConnection>(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<Task> GetTasks()
-            {
-                var listeners = _webSocketListeners.Value;
-                foreach (var x in listeners)
-                {
-                    yield return x.ProcessMessageAsync(result);
-                }
-            }
+            Parallel.Invoke(
+                () => _appHost.Resolve<IActivityLogWebSocketListener>(),
+                () => _appHost.Resolve<IScheduledTasksWebSocketListener>(),
+                () => _appHost.Resolve<ISessionInfoWebSocketListener>());
 
-            return Task.WhenAll(GetTasks());
+            return Task.CompletedTask;
         }
     }
 }

+ 30 - 0
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;
+
+    /// <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);
+    }
+}

+ 10 - 17
Emby.Server.Implementations/Session/SessionWebSocketListener.cs

@@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.Session
     /// <summary>
     /// Class SessionWebSocketListener.
     /// </summary>
-    public sealed class SessionWebSocketListener : IWebSocketListener, IDisposable
+    public sealed class SessionWebSocketListener : ISessionWebSocketListener, IDisposable
     {
         /// <summary>
         /// 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<SessionWebSocketListener> _logger;
         private readonly ILoggerFactory _loggerFactory;
 
-        private readonly IWebSocketManager _webSocketManager;
-
         /// <summary>
         /// The KeepAlive cancellation token.
         /// </summary>
         private CancellationTokenSource _keepAliveCancellationToken;
 
         /// <summary>
-        /// Lock used for accesing the KeepAlive cancellation token.
+        /// Lock used for accessing the KeepAlive cancellation token.
         /// </summary>
         private readonly object _keepAliveLock = new object();
 
@@ -63,7 +61,7 @@ namespace Emby.Server.Implementations.Session
         private readonly HashSet<IWebSocketConnection> _webSockets = new HashSet<IWebSocketConnection>();
 
         /// <summary>
-        /// Lock used for accesing the WebSockets watchlist.
+        /// Lock used for accessing the WebSockets watchlist.
         /// </summary>
         private readonly object _webSocketsLock = new object();
 
@@ -73,32 +71,28 @@ 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,
-            IWebSocketManager webSocketManager)
+            ILoggerFactory loggerFactory)
         {
             _logger = logger;
             _sessionManager = sessionManager;
             _loggerFactory = loggerFactory;
-            _webSocketManager = webSocketManager;
-
-            webSocketManager.WebSocketConnected += OnServerManagerWebSocketConnected;
         }
 
-        private async void OnServerManagerWebSocketConnected(object sender, GenericEventArgs<IWebSocketConnection> e)
+        /// <inheritdoc/>
+        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
         /// <inheritdoc />
         public void Dispose()
         {
-            _webSocketManager.WebSocketConnected -= OnServerManagerWebSocketConnected;
             StopKeepAlive();
         }
 

+ 1 - 1
Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs

@@ -11,7 +11,7 @@ namespace Jellyfin.Api.WebSocketListeners
     /// <summary>
     /// Class SessionInfoWebSocketListener.
     /// </summary>
-    public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<ActivityLogEntry[], WebSocketListenerState>
+    public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<ActivityLogEntry[], WebSocketListenerState>, IActivityLogWebSocketListener
     {
         /// <summary>
         /// The _kernel.

+ 10 - 0
Jellyfin.Api/WebSocketListeners/IActivityLogWebSocketListener.cs

@@ -0,0 +1,10 @@
+#pragma warning disable CA1040 // Avoid empty interfaces
+namespace Jellyfin.Api.WebSocketListeners
+{
+    /// <summary>
+    /// Defines the <see cref="IActivityLogWebSocketListener" />.
+    /// </summary>
+    public interface IActivityLogWebSocketListener
+    {
+    }
+}

+ 10 - 0
Jellyfin.Api/WebSocketListeners/IScheduledTasksWebSocketListener.cs

@@ -0,0 +1,10 @@
+#pragma warning disable CA1040 // Avoid empty interfaces
+namespace Jellyfin.Api.WebSocketListeners
+{
+    /// <summary>
+    /// Defines the <see cref="IScheduledTasksWebSocketListener" />.
+    /// </summary>
+    public interface IScheduledTasksWebSocketListener
+    {
+    }
+}

+ 10 - 0
Jellyfin.Api/WebSocketListeners/ISessionInfoWebSocketListener.cs

@@ -0,0 +1,10 @@
+#pragma warning disable CA1040 // Avoid empty interfaces
+namespace Jellyfin.Api.WebSocketListeners
+{
+    /// <summary>
+    /// Defines the <see cref="ISessionInfoWebSocketListener" />.
+    /// </summary>
+    public interface ISessionInfoWebSocketListener
+    {
+    }
+}

+ 4 - 4
Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs

@@ -12,7 +12,7 @@ namespace Jellyfin.Api.WebSocketListeners
     /// <summary>
     /// Class ScheduledTasksWebSocketListener.
     /// </summary>
-    public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState>
+    public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState>, IScheduledTasksWebSocketListener
     {
         /// <summary>
         /// 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<IScheduledTaskWorker> e)
         {
-            SendData(true);
+            SendData(true).GetAwaiter().GetResult();
             e.Argument.TaskProgress += OnTaskProgress;
         }
 
         private void OnTaskProgress(object? sender, GenericEventArgs<double> e)
         {
-            SendData(false);
+            SendData(false).GetAwaiter().GetResult();
         }
     }
 }

+ 1 - 1
Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs

@@ -11,7 +11,7 @@ namespace Jellyfin.Api.WebSocketListeners
     /// <summary>
     /// Class SessionInfoWebSocketListener.
     /// </summary>
-    public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfo>, WebSocketListenerState>
+    public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfo>, WebSocketListenerState>, ISessionInfoWebSocketListener
     {
         private readonly ISessionManager _sessionManager;
 

+ 4 - 9
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<IUserManager, UserManager>();
             ServiceCollection.AddSingleton<IDisplayPreferencesManager, DisplayPreferencesManager>();
 
-            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>>));
+            ServiceCollection.AddScoped<IActivityLogWebSocketListener, ActivityLogWebSocketListener>();
+            ServiceCollection.AddScoped<IScheduledTasksWebSocketListener, ScheduledTasksWebSocketListener>();
+            ServiceCollection.AddScoped<ISessionInfoWebSocketListener, SessionInfoWebSocketListener>();
+            ServiceCollection.AddScoped<ISessionWebSocketListener, SessionWebSocketListener>();
 
             base.RegisterServices();
         }

+ 1 - 10
Jellyfin.Server/Middleware/WebSocketHandlerMiddleware.cs

@@ -25,19 +25,10 @@ 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,
-#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)
             {

+ 0 - 5
MediaBrowser.Controller/Net/IWebSocketManager.cs

@@ -11,11 +11,6 @@ namespace MediaBrowser.Controller.Net
     /// </summary>
     public interface IWebSocketManager
     {
-        /// <summary>
-        /// Occurs when [web socket connected].
-        /// </summary>
-        event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
-
         /// <summary>
         /// The HTTP request handler.
         /// </summary>