mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-22 10:04:44 +01:00
Merge branch 'master' into network-rewrite
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
|
||||
namespace MediaBrowser.Controller.BaseItemManager
|
||||
@@ -15,8 +14,6 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
{
|
||||
private readonly IServerConfigurationManager _serverConfigurationManager;
|
||||
|
||||
private int _metadataRefreshConcurrency;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BaseItemManager"/> class.
|
||||
/// </summary>
|
||||
@@ -24,16 +21,8 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
public BaseItemManager(IServerConfigurationManager serverConfigurationManager)
|
||||
{
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
|
||||
_metadataRefreshConcurrency = GetMetadataRefreshConcurrency();
|
||||
SetupMetadataThrottler();
|
||||
|
||||
_serverConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public SemaphoreSlim MetadataRefreshThrottler { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsMetadataFetcherEnabled(BaseItem baseItem, TypeOptions? libraryTypeOptions, string name)
|
||||
{
|
||||
@@ -51,12 +40,11 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
|
||||
if (libraryTypeOptions is not null)
|
||||
{
|
||||
return libraryTypeOptions.MetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
return libraryTypeOptions.MetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, baseItem.GetType().Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return itemConfig is null || !itemConfig.DisabledMetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
var itemConfig = _serverConfigurationManager.GetMetadataOptionsForType(baseItem.GetType().Name);
|
||||
return itemConfig is null || !itemConfig.DisabledMetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -76,50 +64,11 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
|
||||
if (libraryTypeOptions is not null)
|
||||
{
|
||||
return libraryTypeOptions.ImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
return libraryTypeOptions.ImageFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, baseItem.GetType().Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return itemConfig is null || !itemConfig.DisabledImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the configuration is updated.
|
||||
/// It will refresh the metadata throttler if the relevant config changed.
|
||||
/// </summary>
|
||||
private void OnConfigurationUpdated(object? sender, EventArgs e)
|
||||
{
|
||||
int newMetadataRefreshConcurrency = GetMetadataRefreshConcurrency();
|
||||
if (_metadataRefreshConcurrency != newMetadataRefreshConcurrency)
|
||||
{
|
||||
_metadataRefreshConcurrency = newMetadataRefreshConcurrency;
|
||||
SetupMetadataThrottler();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the metadata refresh throttler.
|
||||
/// </summary>
|
||||
[MemberNotNull(nameof(MetadataRefreshThrottler))]
|
||||
private void SetupMetadataThrottler()
|
||||
{
|
||||
MetadataRefreshThrottler = new SemaphoreSlim(_metadataRefreshConcurrency);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the metadata refresh concurrency.
|
||||
/// </summary>
|
||||
private int GetMetadataRefreshConcurrency()
|
||||
{
|
||||
var concurrency = _serverConfigurationManager.Configuration.LibraryMetadataRefreshConcurrency;
|
||||
|
||||
if (concurrency <= 0)
|
||||
{
|
||||
concurrency = Environment.ProcessorCount;
|
||||
}
|
||||
|
||||
return concurrency;
|
||||
var itemConfig = _serverConfigurationManager.GetMetadataOptionsForType(baseItem.GetType().Name);
|
||||
return itemConfig is null || !itemConfig.DisabledImageFetchers.Contains(name, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,6 @@ namespace MediaBrowser.Controller.BaseItemManager
|
||||
/// </summary>
|
||||
public interface IBaseItemManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the semaphore used to limit the amount of concurrent metadata refreshes.
|
||||
/// </summary>
|
||||
SemaphoreSlim MetadataRefreshThrottler { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Is metadata fetcher enabled.
|
||||
/// </summary>
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
{
|
||||
if (IsAccessedByName)
|
||||
{
|
||||
return new List<BaseItem>();
|
||||
return Enumerable.Empty<BaseItem>();
|
||||
}
|
||||
|
||||
return base.Children;
|
||||
|
||||
@@ -1244,14 +1244,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken);
|
||||
}
|
||||
|
||||
protected virtual void TriggerOnRefreshStart()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void TriggerOnRefreshComplete()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the base implementation to refresh metadata for local trailers.
|
||||
/// </summary>
|
||||
@@ -1260,8 +1252,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <returns>true if a provider reports we changed.</returns>
|
||||
public async Task<ItemUpdateType> RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken)
|
||||
{
|
||||
TriggerOnRefreshStart();
|
||||
|
||||
var requiresSave = false;
|
||||
|
||||
if (SupportsOwnedItems)
|
||||
@@ -1281,21 +1271,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var refreshOptions = requiresSave
|
||||
? new MetadataRefreshOptions(options)
|
||||
{
|
||||
ForceSave = true
|
||||
}
|
||||
: options;
|
||||
var refreshOptions = requiresSave
|
||||
? new MetadataRefreshOptions(options)
|
||||
{
|
||||
ForceSave = true
|
||||
}
|
||||
: options;
|
||||
|
||||
return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TriggerOnRefreshComplete();
|
||||
}
|
||||
return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected bool IsVisibleStandaloneInternal(User user, bool checkFolders)
|
||||
@@ -1367,7 +1350,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||
{
|
||||
var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
|
||||
var newExtraIds = extras.Select(i => i.Id).ToArray();
|
||||
var newExtraIds = Array.ConvertAll(extras, x => x.Id);
|
||||
var extrasChanged = !item.ExtraIds.SequenceEqual(newExtraIds);
|
||||
|
||||
if (!extrasChanged && !options.ReplaceAllMetadata && options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
|
||||
|
||||
@@ -301,14 +301,6 @@ namespace MediaBrowser.Controller.Entities
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
protected override void TriggerOnRefreshStart()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void TriggerOnRefreshComplete()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the children internal.
|
||||
/// </summary>
|
||||
@@ -510,26 +502,17 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
private async Task RefreshAllMetadataForContainer(IMetadataContainer container, MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
// limit the amount of concurrent metadata refreshes
|
||||
await ProviderManager.RunMetadataRefresh(
|
||||
async () =>
|
||||
{
|
||||
var series = container as Series;
|
||||
if (series is not null)
|
||||
{
|
||||
await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
if (container is Series series)
|
||||
{
|
||||
await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false);
|
||||
},
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task RefreshChildMetadata(BaseItem child, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
var container = child as IMetadataContainer;
|
||||
|
||||
if (container is not null)
|
||||
if (child is IMetadataContainer container)
|
||||
{
|
||||
await RefreshAllMetadataForContainer(container, refreshOptions, progress, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
@@ -537,10 +520,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
if (refreshOptions.RefreshItem(child))
|
||||
{
|
||||
// limit the amount of concurrent metadata refreshes
|
||||
await ProviderManager.RunMetadataRefresh(
|
||||
async () => await child.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
await child.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (recursive && child is Folder folder)
|
||||
@@ -586,7 +566,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
|
||||
var fanoutConcurrency = ConfigurationManager.Configuration.LibraryScanFanoutConcurrency;
|
||||
var parallelism = fanoutConcurrency == 0 ? Environment.ProcessorCount : fanoutConcurrency;
|
||||
var parallelism = fanoutConcurrency > 0 ? fanoutConcurrency : 2 * Environment.ProcessorCount;
|
||||
|
||||
var actionBlock = new ActionBlock<int>(
|
||||
async i =>
|
||||
@@ -618,7 +598,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
actionBlock.Post(i);
|
||||
await actionBlock.SendAsync(i).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
actionBlock.Complete();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CS1591
|
||||
|
||||
using System;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
|
||||
namespace MediaBrowser.Controller.Library
|
||||
@@ -10,8 +10,15 @@ namespace MediaBrowser.Controller.Library
|
||||
public static class MetadataConfigurationExtensions
|
||||
{
|
||||
public static MetadataConfiguration GetMetadataConfiguration(this IConfigurationManager config)
|
||||
{
|
||||
return config.GetConfiguration<MetadataConfiguration>("metadata");
|
||||
}
|
||||
=> config.GetConfiguration<MetadataConfiguration>("metadata");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="MetadataOptions" /> for the specified type.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="IServerConfigurationManager"/>.</param>
|
||||
/// <param name="type">The type to get the <see cref="MetadataOptions" /> for.</param>
|
||||
/// <returns>The <see cref="MetadataOptions" /> for the specified type or <c>null</c>.</returns>
|
||||
public static MetadataOptions? GetMetadataOptionsForType(this IServerConfigurationManager config, string type)
|
||||
=> Array.Find(config.Configuration.MetadataOptions, i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,14 +54,6 @@ namespace MediaBrowser.Controller.Providers
|
||||
/// <returns>Task.</returns>
|
||||
Task<ItemUpdateType> RefreshSingleItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Runs multiple metadata refreshes concurrently.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to run.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the result of the asynchronous operation.</returns>
|
||||
Task RunMetadataRefresh(Func<Task> action, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the image.
|
||||
/// </summary>
|
||||
@@ -207,15 +199,6 @@ namespace MediaBrowser.Controller.Providers
|
||||
where TItemType : BaseItem, new()
|
||||
where TLookupType : ItemLookupInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the search image.
|
||||
/// </summary>
|
||||
/// <param name="providerName">Name of the provider.</param>
|
||||
/// <param name="url">The URL.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{HttpResponseInfo}.</returns>
|
||||
Task<HttpResponseMessage> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
|
||||
|
||||
HashSet<Guid> GetRefreshQueue();
|
||||
|
||||
void OnRefreshStart(BaseItem item);
|
||||
|
||||
Reference in New Issue
Block a user