mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-04 06:48:35 +01:00
close ffmpeg more gracefully
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using System.Collections.Concurrent;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.Channels;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
@@ -23,7 +24,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.Channels
|
||||
{
|
||||
public class ChannelManager : IChannelManager
|
||||
public class ChannelManager : IChannelManager, IDisposable
|
||||
{
|
||||
private IChannel[] _channels;
|
||||
private IChannelFactory[] _factories;
|
||||
@@ -39,6 +40,9 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
|
||||
private readonly ILocalizationManager _localization;
|
||||
private readonly ConcurrentDictionary<Guid, bool> _refreshedItems = new ConcurrentDictionary<Guid, bool>();
|
||||
|
||||
private Timer _refreshTimer;
|
||||
|
||||
public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager, IJsonSerializer jsonSerializer, ILocalizationManager localization)
|
||||
{
|
||||
@@ -51,6 +55,8 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
_userDataManager = userDataManager;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_localization = localization;
|
||||
|
||||
_refreshTimer = new Timer(s => _refreshedItems.Clear(), null, TimeSpan.FromHours(3), TimeSpan.FromHours(3));
|
||||
}
|
||||
|
||||
private TimeSpan CacheLength
|
||||
@@ -203,8 +209,8 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
|
||||
if (requiresCallback != null)
|
||||
{
|
||||
results = await requiresCallback.GetChannelItemMediaInfo(item.ExternalId, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -221,6 +227,31 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
return sources;
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<string, Tuple<DateTime, List<ChannelMediaInfo>>> _channelItemMediaInfo =
|
||||
new ConcurrentDictionary<string, Tuple<DateTime, List<ChannelMediaInfo>>>();
|
||||
|
||||
private async Task<IEnumerable<ChannelMediaInfo>> GetChannelItemMediaSourcesInternal(IRequiresMediaInfoCallback channel, string id, CancellationToken cancellationToken)
|
||||
{
|
||||
Tuple<DateTime, List<ChannelMediaInfo>> cachedInfo;
|
||||
|
||||
if (_channelItemMediaInfo.TryGetValue(id, out cachedInfo))
|
||||
{
|
||||
if ((DateTime.UtcNow - cachedInfo.Item1).TotalMinutes < 5)
|
||||
{
|
||||
return cachedInfo.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
var mediaInfo = await channel.GetChannelItemMediaInfo(id, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
var list = mediaInfo.ToList();
|
||||
|
||||
var item2 = new Tuple<DateTime, List<ChannelMediaInfo>>(DateTime.UtcNow, list);
|
||||
_channelItemMediaInfo.AddOrUpdate(id, item2, (key, oldValue) => item2);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(string id)
|
||||
{
|
||||
var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
|
||||
@@ -515,11 +546,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await indexable.GetLatestMedia(new ChannelLatestMediaSearch
|
||||
{
|
||||
UserId = userId
|
||||
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
var result = await GetLatestItems(indexable, i, userId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var resultItems = result.ToList();
|
||||
|
||||
@@ -585,6 +612,65 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<ChannelItemInfo>> GetLatestItems(ISupportsLatestMedia indexable, IChannel channel, string userId, CancellationToken cancellationToken)
|
||||
{
|
||||
var cacheLength = TimeSpan.FromHours(12);
|
||||
var cachePath = GetChannelDataCachePath(channel, userId, "channelmanager-latest", null, false);
|
||||
|
||||
try
|
||||
{
|
||||
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
return _jsonSerializer.DeserializeFromFile<List<ChannelItemInfo>>(cachePath);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
await _resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
return _jsonSerializer.DeserializeFromFile<List<ChannelItemInfo>>(cachePath);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
var result = await indexable.GetLatestMedia(new ChannelLatestMediaSearch
|
||||
{
|
||||
UserId = userId
|
||||
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var resultItems = result.ToList();
|
||||
|
||||
CacheResponse(resultItems, cachePath);
|
||||
|
||||
return resultItems;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_resourcePool.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<QueryResult<BaseItemDto>> GetAllMedia(AllChannelMediaQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
var user = string.IsNullOrWhiteSpace(query.UserId)
|
||||
@@ -614,11 +700,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await indexable.GetAllMedia(new InternalAllChannelMediaQuery
|
||||
{
|
||||
UserId = userId
|
||||
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
var result = await GetAllItems(indexable, i, userId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return new Tuple<IChannel, ChannelItemResult>(i, result);
|
||||
}
|
||||
@@ -677,6 +759,63 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<ChannelItemResult> GetAllItems(IIndexableChannel indexable, IChannel channel, string userId, CancellationToken cancellationToken)
|
||||
{
|
||||
var cacheLength = TimeSpan.FromHours(12);
|
||||
var cachePath = GetChannelDataCachePath(channel, userId, "channelmanager-allitems", null, false);
|
||||
|
||||
try
|
||||
{
|
||||
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
await _resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
var result = await indexable.GetAllMedia(new InternalAllChannelMediaQuery
|
||||
{
|
||||
UserId = userId
|
||||
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
CacheResponse(result, cachePath);
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_resourcePool.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken)
|
||||
{
|
||||
var queryChannelId = query.ChannelId;
|
||||
@@ -764,11 +903,9 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
{
|
||||
if (!startIndex.HasValue && !limit.HasValue)
|
||||
{
|
||||
var channelItemResult = _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
|
||||
|
||||
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
return channelItemResult;
|
||||
return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -789,11 +926,9 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
{
|
||||
if (!startIndex.HasValue && !limit.HasValue)
|
||||
{
|
||||
var channelItemResult = _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
|
||||
|
||||
if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow)
|
||||
{
|
||||
return channelItemResult;
|
||||
return _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -837,7 +972,7 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
}
|
||||
}
|
||||
|
||||
private void CacheResponse(ChannelItemResult result, string path)
|
||||
private void CacheResponse(object result, string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -993,8 +1128,8 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
item.ProductionYear = info.ProductionYear;
|
||||
item.ProviderIds = info.ProviderIds;
|
||||
|
||||
item.DateCreated = info.DateCreated.HasValue ?
|
||||
info.DateCreated.Value :
|
||||
item.DateCreated = info.DateCreated.HasValue ?
|
||||
info.DateCreated.Value :
|
||||
DateTime.UtcNow;
|
||||
}
|
||||
|
||||
@@ -1042,14 +1177,14 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
|
||||
private async Task RefreshIfNeeded(BaseItem program, CancellationToken cancellationToken)
|
||||
{
|
||||
//if (_refreshedPrograms.ContainsKey(program.Id))
|
||||
if (_refreshedItems.ContainsKey(program.Id))
|
||||
{
|
||||
//return;
|
||||
return;
|
||||
}
|
||||
|
||||
await program.RefreshMetadata(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
//_refreshedPrograms.TryAdd(program.Id, true);
|
||||
_refreshedItems.TryAdd(program.Id, true);
|
||||
}
|
||||
|
||||
internal IChannel GetChannelProvider(Channel channel)
|
||||
@@ -1155,5 +1290,14 @@ namespace MediaBrowser.Server.Implementations.Channels
|
||||
var name = _localization.GetLocalizedString("ViewTypeChannels");
|
||||
return await _libraryManager.GetNamedView(name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_refreshTimer != null)
|
||||
{
|
||||
_refreshTimer.Dispose();
|
||||
_refreshTimer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user