Removed Lazy implementation.
This commit is contained in:
parent
a59aeb12e0
commit
5cd5a7d4ce
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue
Block a user