From 16b9d26ab5e52c3c72dd24f17587ca4775ff79dd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 3 Oct 2013 14:02:23 -0400 Subject: fixes #273 - Marking/unmarking Favorite status doesn't cause a library changed notification --- .../EntryPoints/ServerEventNotifier.cs | 188 +++++++++++++++++++++ .../EntryPoints/UserDataChangeNotifier.cs | 140 +++++++++++++++ .../EntryPoints/WebSocketEvents.cs | 188 --------------------- 3 files changed, 328 insertions(+), 188 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs create mode 100644 MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs delete mode 100644 MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs (limited to 'MediaBrowser.Server.Implementations/EntryPoints') diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs new file mode 100644 index 000000000..0925ca86c --- /dev/null +++ b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -0,0 +1,188 @@ +using MediaBrowser.Common.Events; +using MediaBrowser.Common.Net; +using MediaBrowser.Common.Plugins; +using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Common.Updates; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Tasks; +using System; +using System.Threading; + +namespace MediaBrowser.Server.Implementations.EntryPoints +{ + /// + /// Class WebSocketEvents + /// + public class ServerEventNotifier : IServerEntryPoint + { + /// + /// The _server manager + /// + private readonly IServerManager _serverManager; + + /// + /// The _user manager + /// + private readonly IUserManager _userManager; + + /// + /// The _installation manager + /// + private readonly IInstallationManager _installationManager; + + /// + /// The _kernel + /// + private readonly IServerApplicationHost _appHost; + + /// + /// The _task manager + /// + private readonly ITaskManager _taskManager; + + private readonly IDtoService _dtoService; + + private readonly ISessionManager _sessionManager; + + /// + /// Initializes a new instance of the class. + /// + /// The server manager. + /// The logger. + /// The user manager. + public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService, ISessionManager sessionManager) + { + _serverManager = serverManager; + _userManager = userManager; + _installationManager = installationManager; + _appHost = appHost; + _taskManager = taskManager; + _dtoService = dtoService; + _sessionManager = sessionManager; + } + + public void Run() + { + _userManager.UserDeleted += userManager_UserDeleted; + _userManager.UserUpdated += userManager_UserUpdated; + + _appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged; + + _installationManager.PluginUninstalled += InstallationManager_PluginUninstalled; + _installationManager.PackageInstalling += _installationManager_PackageInstalling; + _installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled; + _installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted; + _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; + + _taskManager.TaskExecuting += _taskManager_TaskExecuting; + _taskManager.TaskCompleted += _taskManager_TaskCompleted; + } + + void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstalling", e.InstallationInfo); + } + + void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstallationCancelled", e.InstallationInfo); + } + + void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstallationCompleted", e.InstallationInfo); + } + + void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) + { + _serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo); + } + + void _taskManager_TaskCompleted(object sender, GenericEventArgs e) + { + _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Argument); + } + + void _taskManager_TaskExecuting(object sender, EventArgs e) + { + var task = (IScheduledTask)sender; + _serverManager.SendWebSocketMessage("ScheduledTaskStarted", task.Name); + } + + /// + /// Installations the manager_ plugin uninstalled. + /// + /// The sender. + /// The e. + void InstallationManager_PluginUninstalled(object sender, GenericEventArgs e) + { + _serverManager.SendWebSocketMessage("PluginUninstalled", e.Argument.GetPluginInfo()); + } + + /// + /// Handles the HasPendingRestartChanged event of the kernel control. + /// + /// The source of the event. + /// The instance containing the event data. + void kernel_HasPendingRestartChanged(object sender, EventArgs e) + { + _sessionManager.SendRestartRequiredNotification(CancellationToken.None); + } + + /// + /// Users the manager_ user updated. + /// + /// The sender. + /// The e. + void userManager_UserUpdated(object sender, GenericEventArgs e) + { + var dto = _dtoService.GetUserDto(e.Argument); + + _serverManager.SendWebSocketMessage("UserUpdated", dto); + } + + /// + /// Users the manager_ user deleted. + /// + /// The sender. + /// The e. + void userManager_UserDeleted(object sender, GenericEventArgs e) + { + _serverManager.SendWebSocketMessage("UserDeleted", e.Argument.Id.ToString("N")); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + _userManager.UserDeleted -= userManager_UserDeleted; + _userManager.UserUpdated -= userManager_UserUpdated; + + _installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled; + _installationManager.PackageInstalling -= _installationManager_PackageInstalling; + _installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled; + _installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted; + _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; + + _appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged; + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs new file mode 100644 index 000000000..fc35e040d --- /dev/null +++ b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -0,0 +1,140 @@ +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Session; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.EntryPoints +{ + class UserDataChangeNotifier : IServerEntryPoint + { + private readonly ISessionManager _sessionManager; + private readonly ILogger _logger; + private readonly IDtoService _dtoService; + private readonly IUserDataManager _userDataManager; + + private readonly object _syncLock = new object(); + private Timer UpdateTimer { get; set; } + private const int UpdateDuration = 2000; + + private readonly Dictionary> _changedKeys = new Dictionary>(); + + public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IDtoService dtoService, ILogger logger) + { + _userDataManager = userDataManager; + _sessionManager = sessionManager; + _dtoService = dtoService; + _logger = logger; + } + + public void Run() + { + _userDataManager.UserDataSaved += _userDataManager_UserDataSaved; + } + + void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e) + { + if (e.SaveReason == UserDataSaveReason.PlaybackProgress) + { + return; + } + + lock (_syncLock) + { + if (UpdateTimer == null) + { + UpdateTimer = new Timer(UpdateTimerCallback, null, UpdateDuration, + Timeout.Infinite); + } + else + { + UpdateTimer.Change(UpdateDuration, Timeout.Infinite); + } + + List keys; + + if (!_changedKeys.TryGetValue(e.UserId, out keys)) + { + keys = new List(); + _changedKeys[e.UserId] = keys; + } + + keys.Add(e.Key); + } + } + + private void UpdateTimerCallback(object state) + { + lock (_syncLock) + { + // Remove dupes in case some were saved multiple times + var changes = _changedKeys.ToList(); + _changedKeys.Clear(); + + SendNotifications(changes, CancellationToken.None); + + if (UpdateTimer != null) + { + UpdateTimer.Dispose(); + UpdateTimer = null; + } + } + } + + private async Task SendNotifications(List>> changes, CancellationToken cancellationToken) + { + foreach (var pair in changes) + { + var userId = pair.Key; + var userSessions = _sessionManager.Sessions + .Where(u => u.User != null && u.User.Id == userId && u.SessionController != null && u.IsActive) + .ToList(); + + if (userSessions.Count > 0) + { + var dtoList = pair.Value + .Select(i => _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(userId, i))) + .ToList(); + + var info = new UserDataChangeInfo + { + UserId = userId.ToString("N"), + + UserDataList = dtoList + }; + + foreach (var userSession in userSessions) + { + try + { + await userSession.SessionController.SendUserDataChangeInfo(info, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending UserDataChanged message", ex); + } + } + } + + } + } + + public void Dispose() + { + if (UpdateTimer != null) + { + UpdateTimer.Dispose(); + UpdateTimer = null; + } + + _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved; + } + } +} diff --git a/MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs b/MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs deleted file mode 100644 index 4349b6976..000000000 --- a/MediaBrowser.Server.Implementations/EntryPoints/WebSocketEvents.cs +++ /dev/null @@ -1,188 +0,0 @@ -using MediaBrowser.Common.Events; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Plugins; -using MediaBrowser.Common.ScheduledTasks; -using MediaBrowser.Common.Updates; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using MediaBrowser.Model.Tasks; -using System; -using System.Threading; - -namespace MediaBrowser.Server.Implementations.EntryPoints -{ - /// - /// Class WebSocketEvents - /// - public class WebSocketEvents : IServerEntryPoint - { - /// - /// The _server manager - /// - private readonly IServerManager _serverManager; - - /// - /// The _user manager - /// - private readonly IUserManager _userManager; - - /// - /// The _installation manager - /// - private readonly IInstallationManager _installationManager; - - /// - /// The _kernel - /// - private readonly IServerApplicationHost _appHost; - - /// - /// The _task manager - /// - private readonly ITaskManager _taskManager; - - private readonly IDtoService _dtoService; - - private ISessionManager _sessionManager; - - /// - /// Initializes a new instance of the class. - /// - /// The server manager. - /// The logger. - /// The user manager. - public WebSocketEvents(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService, ISessionManager sessionManager) - { - _serverManager = serverManager; - _userManager = userManager; - _installationManager = installationManager; - _appHost = appHost; - _taskManager = taskManager; - _dtoService = dtoService; - _sessionManager = sessionManager; - } - - public void Run() - { - _userManager.UserDeleted += userManager_UserDeleted; - _userManager.UserUpdated += userManager_UserUpdated; - - _appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged; - - _installationManager.PluginUninstalled += InstallationManager_PluginUninstalled; - _installationManager.PackageInstalling += _installationManager_PackageInstalling; - _installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled; - _installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted; - _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; - - _taskManager.TaskExecuting += _taskManager_TaskExecuting; - _taskManager.TaskCompleted += _taskManager_TaskCompleted; - } - - void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstalling", e.InstallationInfo); - } - - void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationCancelled", e.InstallationInfo); - } - - void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationCompleted", e.InstallationInfo); - } - - void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e) - { - _serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo); - } - - void _taskManager_TaskCompleted(object sender, GenericEventArgs e) - { - _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Argument); - } - - void _taskManager_TaskExecuting(object sender, EventArgs e) - { - var task = (IScheduledTask)sender; - _serverManager.SendWebSocketMessage("ScheduledTaskStarted", task.Name); - } - - /// - /// Installations the manager_ plugin uninstalled. - /// - /// The sender. - /// The e. - void InstallationManager_PluginUninstalled(object sender, GenericEventArgs e) - { - _serverManager.SendWebSocketMessage("PluginUninstalled", e.Argument.GetPluginInfo()); - } - - /// - /// Handles the HasPendingRestartChanged event of the kernel control. - /// - /// The source of the event. - /// The instance containing the event data. - void kernel_HasPendingRestartChanged(object sender, EventArgs e) - { - _sessionManager.SendRestartRequiredMessage(CancellationToken.None); - } - - /// - /// Users the manager_ user updated. - /// - /// The sender. - /// The e. - void userManager_UserUpdated(object sender, GenericEventArgs e) - { - var dto = _dtoService.GetUserDto(e.Argument); - - _serverManager.SendWebSocketMessage("UserUpdated", dto); - } - - /// - /// Users the manager_ user deleted. - /// - /// The sender. - /// The e. - void userManager_UserDeleted(object sender, GenericEventArgs e) - { - _serverManager.SendWebSocketMessage("UserDeleted", e.Argument.Id.ToString("N")); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - _userManager.UserDeleted -= userManager_UserDeleted; - _userManager.UserUpdated -= userManager_UserUpdated; - - _installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled; - _installationManager.PackageInstalling -= _installationManager_PackageInstalling; - _installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled; - _installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted; - _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed; - - _appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged; - } - } - } -} -- cgit v1.2.3