diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index c54c0a8737..f4d4826ebf 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -283,8 +283,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager var url = options.Url; var urlHash = url.ToLower().GetMD5().ToString("N"); - var semaphore = GetLock(url); - + var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash); response = await GetCachedResponse(responseCachePath, options.CacheLength, url).ConfigureAwait(false); @@ -293,6 +292,8 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager return response; } + var semaphore = GetLock(url); + await semaphore.WaitAsync(options.CancellationToken).ConfigureAwait(false); try diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index f8d5e18680..5ee49ae5a3 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -13,6 +13,7 @@ namespace MediaBrowser.Controller.Entities { public string ViewType { get; set; } public Guid ParentId { get; set; } + public Guid DisplayParentId { get; set; } public Guid? UserId { get; set; } @@ -28,7 +29,11 @@ namespace MediaBrowser.Controller.Entities { var parent = this as Folder; - if (ParentId != Guid.Empty) + if (DisplayParentId != Guid.Empty) + { + parent = LibraryManager.GetItemById(DisplayParentId) as Folder ?? parent; + } + else if (ParentId != Guid.Empty) { parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent; } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 843fba0d0b..980a3bbb53 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -385,6 +385,21 @@ namespace MediaBrowser.Controller.Library string uniqueId, CancellationToken cancellationToken); + /// + /// Gets the shadow view. + /// + /// The parent. + /// Type of the view. + /// Name of the sort. + /// The unique identifier. + /// The cancellation token. + /// Task<UserView>. + Task GetShadowView(BaseItem parent, + string viewType, + string sortName, + string uniqueId, + CancellationToken cancellationToken); + /// /// Determines whether [is video file] [the specified path]. /// diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index f36fca77c8..c8361ea04c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -216,10 +216,10 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - using (var processWrapper = new ProcessWrapper(process, this, _logger)) { + await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + try { StartProcess(processWrapper); @@ -536,10 +536,10 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - using (var processWrapper = new ProcessWrapper(process, this, _logger)) { + await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + bool ranToCompletion; var memoryStream = new MemoryStream(); diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 20526b3606..c39c2ed685 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -353,14 +353,27 @@ namespace MediaBrowser.Providers.Movies return mainResult; } + private static long _lastRequestTicks; + /// /// Gets the movie db response. /// - internal Task GetMovieDbResponse(HttpRequestOptions options) + internal async Task GetMovieDbResponse(HttpRequestOptions options) { - options.ResourcePool = MovieDbResourcePool; + var requestIntervalMs = 250; + var delayTicks = (requestIntervalMs * 10000) - (DateTime.UtcNow.Ticks - _lastRequestTicks); + var delayMs = Math.Min(delayTicks / 10000, requestIntervalMs); - return _httpClient.Get(options); + if (delayMs > 0) + { + _logger.Debug("Throttling Tmdb by {0} ms", delayMs); + await Task.Delay(Convert.ToInt32(delayMs)).ConfigureAwait(false); + } + + options.ResourcePool = MovieDbResourcePool; + _lastRequestTicks = DateTime.UtcNow.Ticks; + + return await _httpClient.Get(options).ConfigureAwait(false); } public TheMovieDbOptions GetTheMovieDbOptions() diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index 70946db36e..978d611a8c 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -300,7 +300,7 @@ namespace MediaBrowser.Providers.Music if (!isSearch) { options.CacheMode = CacheMode.Unconditional; - options.CacheLength = TimeSpan.FromDays(7); + options.CacheLength = TimeSpan.FromDays(3); } using (var xml = await _httpClient.Get(options).ConfigureAwait(false)) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index ce2dbb5261..eff05ba73f 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1792,7 +1792,7 @@ namespace MediaBrowser.Server.Implementations.Library if (!string.IsNullOrWhiteSpace(parentId)) { - item.ParentId = new Guid(parentId); + item.DisplayParentId = new Guid(parentId); } await CreateItem(item, cancellationToken).ConfigureAwait(false); @@ -1826,6 +1826,75 @@ namespace MediaBrowser.Server.Implementations.Library return item; } + public async Task GetShadowView(BaseItem parent, + string viewType, + string sortName, + string uniqueId, + CancellationToken cancellationToken) + { + if (parent == null) + { + throw new ArgumentNullException("parent"); + } + + var name = parent.Name; + var parentId = parent.Id; + + var idValues = "37_namedview_" + name + parentId + (viewType ?? string.Empty); + if (!string.IsNullOrWhiteSpace(uniqueId)) + { + idValues += uniqueId; + } + + var id = GetNewItemId(idValues, typeof(UserView)); + + var path = parent.Path; + + var item = GetItemById(id) as UserView; + + var isNew = false; + + if (item == null) + { + _fileSystem.CreateDirectory(path); + + item = new UserView + { + Path = path, + Id = id, + DateCreated = DateTime.UtcNow, + Name = name, + ViewType = viewType, + ForcedSortName = sortName + }; + + item.DisplayParentId = parentId; + + await CreateItem(item, cancellationToken).ConfigureAwait(false); + + isNew = true; + } + + if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) + { + item.ViewType = viewType; + await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); + } + + var refresh = isNew || (DateTime.UtcNow - item.DateLastRefreshed) >= _viewRefreshInterval; + + if (refresh) + { + _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) + { + // Need to force save to increment DateLastSaved + ForceSave = true + }); + } + + return item; + } + public async Task GetNamedView(string name, string parentId, string viewType, @@ -1868,7 +1937,7 @@ namespace MediaBrowser.Server.Implementations.Library if (!string.IsNullOrWhiteSpace(parentId)) { - item.ParentId = new Guid(parentId); + item.DisplayParentId = new Guid(parentId); } await CreateItem(item, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index c2518f2b76..ffbc89c940 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -74,11 +74,11 @@ namespace MediaBrowser.Server.Implementations.Library } else if (plainFolderIds.Contains(folder.Id)) { - list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, false, string.Empty, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(folder, folderViewType, false, string.Empty, cancellationToken).ConfigureAwait(false)); } else if (!string.IsNullOrWhiteSpace(folderViewType)) { - list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, cancellationToken).ConfigureAwait(false)); + list.Add(await GetUserView(folder, folderViewType, true, string.Empty, cancellationToken).ConfigureAwait(false)); } else { @@ -209,23 +209,18 @@ namespace MediaBrowser.Server.Implementations.Library public async Task GetUserView(List parents, List currentViews, string viewType, string sortName, User user, CancellationToken cancellationToken) { - var name = _localizationManager.GetLocalizedString("ViewType" + viewType); var enableUserViews = _config.Configuration.EnableUserViews; if (parents.Count == 1 && parents.All(i => string.Equals((enableUserViews ? i.GetViewType(user) : i.CollectionType), viewType, StringComparison.OrdinalIgnoreCase))) { - if (!string.IsNullOrWhiteSpace(parents[0].Name)) - { - name = parents[0].Name; - } - var parentId = parents[0].Id; var enableRichView = !user.Configuration.PlainFolderViews.Contains(parentId.ToString("N"), StringComparer.OrdinalIgnoreCase); - return await GetUserView(parentId, name, viewType, enableRichView, string.Empty, cancellationToken).ConfigureAwait(false); + return await GetUserView((Folder)parents[0], viewType, enableRichView, string.Empty, cancellationToken).ConfigureAwait(false); } + var name = _localizationManager.GetLocalizedString("ViewType" + viewType); return await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false); } @@ -235,10 +230,11 @@ namespace MediaBrowser.Server.Implementations.Library return _libraryManager.GetNamedView(user, name, parentId.ToString("N"), viewType, sortName, null, cancellationToken); } - public Task GetUserView(Guid parentId, string name, string viewType, bool enableRichView, string sortName, CancellationToken cancellationToken) + public Task GetUserView(Folder parent, string viewType, bool enableRichView, string sortName, CancellationToken cancellationToken) { viewType = enableRichView ? viewType : null; - return _libraryManager.GetNamedView(name, parentId.ToString("N"), viewType, sortName, null, cancellationToken); + + return _libraryManager.GetShadowView(parent, viewType, sortName, null, cancellationToken); } public List>> GetLatestItems(LatestItemsQuery request)