From a3ecf6c2b7760935de541568cfdfa3c1c09edda9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 21 May 2013 23:42:25 -0400 Subject: localize library changed messages per user --- .../EntryPoints/LibraryChangedNotifier.cs | 164 ++++++++++++++++----- 1 file changed, 130 insertions(+), 34 deletions(-) (limited to 'MediaBrowser.ServerApplication/EntryPoints/LibraryChangedNotifier.cs') diff --git a/MediaBrowser.ServerApplication/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.ServerApplication/EntryPoints/LibraryChangedNotifier.cs index 62c1e17f9..715492aac 100644 --- a/MediaBrowser.ServerApplication/EntryPoints/LibraryChangedNotifier.cs +++ b/MediaBrowser.ServerApplication/EntryPoints/LibraryChangedNotifier.cs @@ -1,8 +1,12 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; +using MoreLinq; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading; @@ -17,17 +21,19 @@ namespace MediaBrowser.ServerApplication.EntryPoints private readonly ISessionManager _sessionManager; private readonly IServerManager _serverManager; - + private readonly IUserManager _userManager; + /// /// The _library changed sync lock /// private readonly object _libraryChangedSyncLock = new object(); - /// - /// Gets or sets the library update info. - /// - /// The library update info. - private LibraryUpdateInfo LibraryUpdateInfo { get; set; } + private readonly List _foldersAddedTo = new List(); + private readonly List _foldersRemovedFrom = new List(); + + private readonly List _itemsAdded = new List(); + private readonly List _itemsRemoved = new List(); + private readonly List _itemsUpdated = new List(); /// /// Gets or sets the library update timer. @@ -40,11 +46,12 @@ namespace MediaBrowser.ServerApplication.EntryPoints /// private const int LibraryUpdateDuration = 60000; - public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IServerManager serverManager) + public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IServerManager serverManager, IUserManager userManager) { _libraryManager = libraryManager; _sessionManager = sessionManager; _serverManager = serverManager; + _userManager = userManager; } public void Run() @@ -64,11 +71,6 @@ namespace MediaBrowser.ServerApplication.EntryPoints { lock (_libraryChangedSyncLock) { - if (LibraryUpdateInfo == null) - { - LibraryUpdateInfo = new LibraryUpdateInfo(); - } - if (LibraryUpdateTimer == null) { LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, @@ -81,10 +83,10 @@ namespace MediaBrowser.ServerApplication.EntryPoints if (e.Item.Parent != null) { - LibraryUpdateInfo.FoldersAddedTo.Add(e.Item.Parent.Id); + _foldersAddedTo.Add(e.Item.Parent); } - LibraryUpdateInfo.ItemsAdded.Add(e.Item.Id); + _itemsAdded.Add(e.Item); } } @@ -97,11 +99,6 @@ namespace MediaBrowser.ServerApplication.EntryPoints { lock (_libraryChangedSyncLock) { - if (LibraryUpdateInfo == null) - { - LibraryUpdateInfo = new LibraryUpdateInfo(); - } - if (LibraryUpdateTimer == null) { LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, @@ -112,7 +109,7 @@ namespace MediaBrowser.ServerApplication.EntryPoints LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); } - LibraryUpdateInfo.ItemsUpdated.Add(e.Item.Id); + _itemsUpdated.Add(e.Item); } } @@ -125,11 +122,6 @@ namespace MediaBrowser.ServerApplication.EntryPoints { lock (_libraryChangedSyncLock) { - if (LibraryUpdateInfo == null) - { - LibraryUpdateInfo = new LibraryUpdateInfo(); - } - if (LibraryUpdateTimer == null) { LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, @@ -142,10 +134,10 @@ namespace MediaBrowser.ServerApplication.EntryPoints if (e.Item.Parent != null) { - LibraryUpdateInfo.FoldersRemovedFrom.Add(e.Item.Parent.Id); + _foldersRemovedFrom.Add(e.Item.Parent); } - LibraryUpdateInfo.ItemsRemoved.Add(e.Item.Id); + _itemsRemoved.Add(e.Item); } } @@ -158,16 +150,16 @@ namespace MediaBrowser.ServerApplication.EntryPoints lock (_libraryChangedSyncLock) { // Remove dupes in case some were saved multiple times - LibraryUpdateInfo.FoldersAddedTo = LibraryUpdateInfo.FoldersAddedTo.Distinct().ToList(); + var foldersAddedTo = _foldersAddedTo.DistinctBy(i => i.Id).ToList(); - LibraryUpdateInfo.FoldersRemovedFrom = LibraryUpdateInfo.FoldersRemovedFrom.Distinct().ToList(); + var foldersRemovedFrom = _foldersRemovedFrom.DistinctBy(i => i.Id).ToList(); - LibraryUpdateInfo.ItemsUpdated = LibraryUpdateInfo.ItemsUpdated - .Where(i => !LibraryUpdateInfo.ItemsAdded.Contains(i)) - .Distinct() + var itemsUpdated = _itemsUpdated + .Where(i => !_itemsAdded.Contains(i)) + .DistinctBy(i => i.Id) .ToList(); - _serverManager.SendWebSocketMessage("LibraryChanged", LibraryUpdateInfo); + SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None); if (LibraryUpdateTimer != null) { @@ -175,8 +167,112 @@ namespace MediaBrowser.ServerApplication.EntryPoints LibraryUpdateTimer = null; } - LibraryUpdateInfo = null; + _itemsAdded.Clear(); + _itemsRemoved.Clear(); + _itemsUpdated.Clear(); + _foldersAddedTo.Clear(); + _foldersRemovedFrom.Clear(); + } + } + + /// + /// Sends the change notifications. + /// + /// The items added. + /// The items updated. + /// The items removed. + /// The folders added to. + /// The folders removed from. + /// The cancellation token. + private async void SendChangeNotifications(IEnumerable itemsAdded, IEnumerable itemsUpdated, IEnumerable itemsRemoved, IEnumerable foldersAddedTo, IEnumerable foldersRemovedFrom, CancellationToken cancellationToken) + { + var currentSessions = _sessionManager.Sessions.ToList(); + + var users = currentSessions.Select(i => i.UserId ?? Guid.Empty).Where(i => i != Guid.Empty).Distinct().ToList(); + + foreach (var userId in users) + { + var id = userId; + var webSockets = currentSessions.Where(u => u.UserId.HasValue && u.UserId.Value == id).SelectMany(i => i.WebSockets).ToList(); + + await _serverManager.SendWebSocketMessageAsync("LibraryChanged", () => GetLibraryUpdateInfo(itemsAdded, itemsUpdated, itemsRemoved, foldersAddedTo, foldersRemovedFrom, id), webSockets, cancellationToken).ConfigureAwait(false); + } + } + + /// + /// Gets the library update info. + /// + /// The items added. + /// The items updated. + /// The items removed. + /// The folders added to. + /// The folders removed from. + /// The user id. + /// LibraryUpdateInfo. + private LibraryUpdateInfo GetLibraryUpdateInfo(IEnumerable itemsAdded, IEnumerable itemsUpdated, IEnumerable itemsRemoved, IEnumerable foldersAddedTo, IEnumerable foldersRemovedFrom, Guid userId) + { + var user = _userManager.GetUserById(userId); + + var collections = user.RootFolder.GetChildren(user).ToList(); + + var allRecursiveChildren = user.RootFolder.GetRecursiveChildren(user).ToDictionary(i => i.Id); + + return new LibraryUpdateInfo + { + ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList(), + + ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList(), + + ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList(), + + FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList(), + + FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList() + }; + } + + /// + /// Translates the physical item to user library. + /// + /// + /// The item. + /// The user. + /// The collections. + /// All recursive children. + /// IEnumerable{``0}. + private IEnumerable TranslatePhysicalItemToUserLibrary(T item, User user, List collections, Dictionary allRecursiveChildren) + where T : BaseItem + { + // If the physical root changed, return the user root + if (item is AggregateFolder) + { + return new T[] { user.RootFolder as T }; + } + + // Need to find what user collection folder this belongs to + if (item.Parent is AggregateFolder) + { + return new T[] { user.RootFolder as T }; + } + + // If it's a user root, return it only if it's the right one + if (item is UserRootFolder) + { + if (item.Id == user.RootFolder.Id) + { + return new T[] { item }; + } + + return new T[] { }; } + + // Return it only if it's in the user's library + if (allRecursiveChildren.ContainsKey(item.Id)) + { + return new T[] { item }; + } + + return new T[] { }; } /// -- cgit v1.2.3