Updated contributors, upgraded to AsyncKeyedLocker 6.3.0 which now supports non-keyed locking using a similar interface and changed SemaphoreSlim-based locks to using AsyncNonKeyedLocker.

This commit is contained in:
Mark Cilia Vincenti
2024-01-14 12:11:16 +01:00
parent 6a257e1b40
commit e47144e7c7
14 changed files with 126 additions and 149 deletions

View File

@@ -7,6 +7,7 @@ using System.Net.Mime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AsyncKeyedLock;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
@@ -38,7 +39,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
private readonly IServerApplicationPaths _appPaths;
private readonly IImageEncoder _imageEncoder;
private readonly SemaphoreSlim _parallelEncodingLimit;
private readonly AsyncNonKeyedLocker _parallelEncodingLimit;
private bool _disposed;
@@ -68,7 +69,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
semaphoreCount = 2 * Environment.ProcessorCount;
}
_parallelEncodingLimit = new(semaphoreCount, semaphoreCount);
_parallelEncodingLimit = new(semaphoreCount);
}
private string ResizedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "resized-images");
@@ -193,18 +194,13 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
{
if (!File.Exists(cacheFilePath))
{
// Limit number of parallel (more precisely: concurrent) image encodings to prevent a high memory usage
await _parallelEncodingLimit.WaitAsync().ConfigureAwait(false);
string resultPath;
try
// Limit number of parallel (more precisely: concurrent) image encodings to prevent a high memory usage
using (await _parallelEncodingLimit.LockAsync().ConfigureAwait(false))
{
resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
}
finally
{
_parallelEncodingLimit.Release();
}
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
{

View File

@@ -21,4 +21,8 @@
<Compile Include="..\..\SharedVersion.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncKeyedLock" />
</ItemGroup>
</Project>

View File

@@ -8,6 +8,7 @@ using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using AsyncKeyedLock;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
@@ -50,7 +51,7 @@ namespace Jellyfin.LiveTv.Channels
private readonly IFileSystem _fileSystem;
private readonly IProviderManager _providerManager;
private readonly IMemoryCache _memoryCache;
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
private readonly AsyncNonKeyedLocker _resourcePool = new(1);
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private bool _disposed = false;
@@ -832,9 +833,7 @@ namespace Jellyfin.LiveTv.Channels
{
}
await _resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
using (await _resourcePool.LockAsync(cancellationToken).ConfigureAwait(false))
{
try
{
@@ -881,10 +880,6 @@ namespace Jellyfin.LiveTv.Channels
return result;
}
finally
{
_resourcePool.Release();
}
}
private async Task CacheResponse(ChannelItemResult result, string path)

View File

@@ -14,6 +14,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using AsyncKeyedLock;
using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
using Jellyfin.Extensions;
@@ -68,7 +69,7 @@ namespace Jellyfin.LiveTv.EmbyTV
private readonly ConcurrentDictionary<string, EpgChannelData> _epgChannels =
new ConcurrentDictionary<string, EpgChannelData>(StringComparer.OrdinalIgnoreCase);
private readonly SemaphoreSlim _recordingDeleteSemaphore = new SemaphoreSlim(1, 1);
private readonly AsyncNonKeyedLocker _recordingDeleteSemaphore = new(1);
private bool _disposed;
@@ -1447,9 +1448,7 @@ namespace Jellyfin.LiveTv.EmbyTV
return;
}
await _recordingDeleteSemaphore.WaitAsync().ConfigureAwait(false);
try
using (await _recordingDeleteSemaphore.LockAsync().ConfigureAwait(false))
{
if (_disposed)
{
@@ -1502,10 +1501,6 @@ namespace Jellyfin.LiveTv.EmbyTV
}
}
}
finally
{
_recordingDeleteSemaphore.Release();
}
}
private void DeleteLibraryItemsForTimers(List<TimerInfo> timers)

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -11,6 +11,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncKeyedLock" />
<PackageReference Include="Jellyfin.XmlTv" />
<PackageReference Include="System.Linq.Async" />
</ItemGroup>

View File

@@ -16,6 +16,7 @@ using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using AsyncKeyedLock;
using Jellyfin.Extensions;
using Jellyfin.Extensions.Json;
using Jellyfin.LiveTv.Listings.SchedulesDirectDtos;
@@ -35,7 +36,7 @@ namespace Jellyfin.LiveTv.Listings
private readonly ILogger<SchedulesDirect> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1);
private readonly AsyncNonKeyedLocker _tokenLock = new(1);
private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new ConcurrentDictionary<string, NameValuePair>();
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
@@ -573,27 +574,25 @@ namespace Jellyfin.LiveTv.Listings
}
}
await _tokenSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
using (await _tokenLock.LockAsync(cancellationToken).ConfigureAwait(false))
{
var result = await GetTokenInternal(username, password, cancellationToken).ConfigureAwait(false);
savedToken.Name = result;
savedToken.Value = DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture);
return result;
}
catch (HttpRequestException ex)
{
if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest)
try
{
_tokens.Clear();
_lastErrorResponse = DateTime.UtcNow;
var result = await GetTokenInternal(username, password, cancellationToken).ConfigureAwait(false);
savedToken.Name = result;
savedToken.Value = DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture);
return result;
}
catch (HttpRequestException ex)
{
if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest)
{
_tokens.Clear();
_lastErrorResponse = DateTime.UtcNow;
}
throw;
}
finally
{
_tokenSemaphore.Release();
throw;
}
}
}
@@ -801,7 +800,7 @@ namespace Jellyfin.LiveTv.Listings
if (disposing)
{
_tokenSemaphore?.Dispose();
_tokenLock?.Dispose();
}
_disposed = true;