From 01d834f21abcb65d246b18762b79001929fe845b Mon Sep 17 00:00:00 2001 From: JPVenson <6794763+JPVenson@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:20:42 +0000 Subject: Fixed (most) tests --- .../Controllers/LibraryStructureControllerTests.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index bf3bfdad4..02a77516f 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -13,7 +13,7 @@ using Xunit.Priority; namespace Jellyfin.Server.Integration.Tests.Controllers; -[TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] +// [TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] public sealed class LibraryStructureControllerTests : IClassFixture { private readonly JellyfinApplicationFactory _factory; @@ -62,12 +62,23 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Thu, 10 Oct 2024 00:49:06 +0000 Subject: Fixed tests --- .../Item/BaseItemRepository.cs | 89 ++++++++++++---------- .../Controllers/LibraryStructureControllerTests.cs | 14 ++-- 2 files changed, 56 insertions(+), 47 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs index d42581ef4..d82de097c 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs @@ -930,19 +930,19 @@ public sealed class BaseItemRepository(IDbContextFactory dbPr if (filter.HasDeadParentId.HasValue && filter.HasDeadParentId.Value) { baseQuery = baseQuery - .Where(e => e.ParentId.HasValue && context.BaseItems.Any(f => f.Id == e.ParentId.Value)); + .Where(e => e.ParentId.HasValue && !context.BaseItems.Any(f => f.Id == e.ParentId.Value)); } if (filter.IsDeadArtist.HasValue && filter.IsDeadArtist.Value) { baseQuery = baseQuery - .Where(e => e.ItemValues!.Any(f => (f.Type == 0 || f.Type == ItemValueType.AlbumArtist) && f.CleanValue == e.CleanName)); + .Where(e => !e.ItemValues!.Any(f => (f.Type == ItemValueType.Artist || f.Type == ItemValueType.AlbumArtist) && f.CleanValue == e.CleanName)); } if (filter.IsDeadStudio.HasValue && filter.IsDeadStudio.Value) { baseQuery = baseQuery - .Where(e => e.ItemValues!.Any(f => f.Type == ItemValueType.Studios && f.CleanValue == e.CleanName)); + .Where(e => !e.ItemValues!.Any(f => f.Type == ItemValueType.Studios && f.CleanValue == e.CleanName)); } if (filter.IsDeadPerson.HasValue && filter.IsDeadPerson.Value) @@ -1252,53 +1252,61 @@ public sealed class BaseItemRepository(IDbContextFactory dbPr tuples[i] = (item, ancestorIds, topParent, userdataKey, inheritedTags); } - using var context = dbProvider.CreateDbContext(); - using var transaction = context.Database.BeginTransaction(); - foreach (var item in tuples) + try { - var entity = Map(item.Item); - if (!context.BaseItems.Any(e => e.Id == entity.Id)) + using var context = dbProvider.CreateDbContext(); + using var transaction = context.Database.BeginTransaction(); + foreach (var item in tuples) { - context.BaseItems.Add(entity); - } - else - { - context.BaseItems.Attach(entity).State = EntityState.Modified; - } + var entity = Map(item.Item); + if (!context.BaseItems.Any(e => e.Id == entity.Id)) + { + context.BaseItems.Add(entity); + } + else + { + context.BaseItems.Attach(entity).State = EntityState.Modified; + } - context.AncestorIds.Where(e => e.ItemId == entity.Id).ExecuteDelete(); - if (item.Item.SupportsAncestors && item.AncestorIds != null) - { - entity.AncestorIds = new List(); - foreach (var ancestorId in item.AncestorIds) + context.AncestorIds.Where(e => e.ItemId == entity.Id).ExecuteDelete(); + if (item.Item.SupportsAncestors && item.AncestorIds != null) { - entity.AncestorIds.Add(new AncestorId() + entity.AncestorIds = new List(); + foreach (var ancestorId in item.AncestorIds) { - ParentItemId = ancestorId, - ItemId = entity.Id - }); + entity.AncestorIds.Add(new AncestorId() + { + ParentItemId = ancestorId, + ItemId = entity.Id + }); + } } - } - var itemValues = GetItemValuesToSave(item.Item, item.InheritedTags); - context.ItemValues.Where(e => e.ItemId == entity.Id).ExecuteDelete(); - entity.ItemValues = new List(); + var itemValues = GetItemValuesToSave(item.Item, item.InheritedTags); + context.ItemValues.Where(e => e.ItemId == entity.Id).ExecuteDelete(); + entity.ItemValues = new List(); - foreach (var itemValue in itemValues) - { - entity.ItemValues.Add(new() + foreach (var itemValue in itemValues) { - Item = entity, - Type = (ItemValueType)itemValue.MagicNumber, - Value = itemValue.Value, - CleanValue = GetCleanValue(itemValue.Value), - ItemId = entity.Id - }); + entity.ItemValues.Add(new() + { + Item = entity, + Type = (ItemValueType)itemValue.MagicNumber, + Value = itemValue.Value, + CleanValue = GetCleanValue(itemValue.Value), + ItemId = entity.Id + }); + } } - } - context.SaveChanges(); - transaction.Commit(); + context.SaveChanges(); + transaction.Commit(); + } + catch (System.Exception) + { + System.Console.WriteLine(); + throw; + } } /// @@ -1484,7 +1492,8 @@ public sealed class BaseItemRepository(IDbContextFactory dbPr Type = dto.GetType().ToString(), Id = dto.Id }; - entity.ParentId = dto.ParentId; + + entity.ParentId = !dto.ParentId.IsEmpty() ? dto.ParentId : null; entity.Path = GetPathToSave(dto.Path); entity.EndDate = dto.EndDate.GetValueOrDefault(); entity.CommunityRating = dto.CommunityRating; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 02a77516f..190621085 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -13,7 +13,7 @@ using Xunit.Priority; namespace Jellyfin.Server.Integration.Tests.Controllers; -// [TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] +[TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] public sealed class LibraryStructureControllerTests : IClassFixture { private readonly JellyfinApplicationFactory _factory; @@ -62,13 +62,13 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Thu, 10 Oct 2024 15:23:34 +0000 Subject: Fixed tests --- .../Controllers/LibraryStructureControllerTests.cs | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 190621085..bf3bfdad4 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -68,17 +68,6 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Sun, 10 Nov 2024 20:18:36 +0000 Subject: Fixed out of order unittests --- .../Controllers/LibraryStructureControllerTests.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index bf3bfdad4..0376f57cc 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -62,12 +62,23 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Thu, 14 Nov 2024 09:04:35 +0000 Subject: Added Pipeline debug code --- Jellyfin.Api/Controllers/LibraryStructureController.cs | 10 +++++++++- .../Controllers/LibraryStructureControllerTests.cs | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/Jellyfin.Api/Controllers/LibraryStructureController.cs b/Jellyfin.Api/Controllers/LibraryStructureController.cs index 93c2393f3..c52068000 100644 --- a/Jellyfin.Api/Controllers/LibraryStructureController.cs +++ b/Jellyfin.Api/Controllers/LibraryStructureController.cs @@ -106,7 +106,15 @@ public class LibraryStructureController : BaseJellyfinApiController [FromQuery] string name, [FromQuery] bool refreshLibrary = false) { - await _libraryManager.RemoveVirtualFolder(name, refreshLibrary).ConfigureAwait(false); + try + { + await _libraryManager.RemoveVirtualFolder(name, refreshLibrary).ConfigureAwait(false); + } + catch (Exception ex) + { + return BadRequest(ex.ToString()); + } + return NoContent(); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 0376f57cc..9d39b4bfa 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -120,6 +120,14 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Thu, 14 Nov 2024 09:20:12 +0000 Subject: Updated test dbg message --- .../Controllers/LibraryStructureControllerTests.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 9d39b4bfa..acb330ca7 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -120,14 +120,6 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Thu, 14 Nov 2024 09:25:55 +0000 Subject: Fixed tests message --- .../Controllers/LibraryStructureControllerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index acb330ca7..dc8c33c73 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -120,6 +120,6 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Thu, 14 Nov 2024 10:14:41 +0000 Subject: Deterministic tests my *** --- Jellyfin.Api/Controllers/LibraryStructureController.cs | 9 ++++++++- Jellyfin.Server.Implementations/Item/BaseItemRepository.cs | 4 ++-- .../Controllers/LibraryStructureControllerTests.cs | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/Jellyfin.Api/Controllers/LibraryStructureController.cs b/Jellyfin.Api/Controllers/LibraryStructureController.cs index c3e3b659b..7838c2f61 100644 --- a/Jellyfin.Api/Controllers/LibraryStructureController.cs +++ b/Jellyfin.Api/Controllers/LibraryStructureController.cs @@ -88,7 +88,14 @@ public class LibraryStructureController : BaseJellyfinApiController libraryOptions.PathInfos = Array.ConvertAll(paths, i => new MediaPathInfo(i)); } - await _libraryManager.AddVirtualFolder(name, collectionType, libraryOptions, refreshLibrary).ConfigureAwait(false); + try + { + await _libraryManager.AddVirtualFolder(name, collectionType, libraryOptions, refreshLibrary).ConfigureAwait(false); + } + catch (System.Exception ex) + { + return BadRequest(ex.ToString()); + } return NoContent(); } diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs index 14300d237..f62d6fc1a 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs @@ -83,7 +83,7 @@ public sealed class BaseItemRepository( context.Peoples.Where(e => e.BaseItems!.Count == 0).ExecuteDelete(); context.Chapters.Where(e => e.ItemId == id).ExecuteDelete(); context.MediaStreamInfos.Where(e => e.ItemId == id).ExecuteDelete(); - context.AncestorIds.Where(e => e.ItemId == id).ExecuteDelete(); + context.AncestorIds.Where(e => e.ItemId == id || e.ParentItemId == id).ExecuteDelete(); context.ItemValuesMap.Where(e => e.ItemId == id).ExecuteDelete(); context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDelete(); context.BaseItemImageInfos.Where(e => e.ItemId == id).ExecuteDelete(); @@ -1292,7 +1292,7 @@ public sealed class BaseItemRepository( { if (!context.BaseItems.Any(f => f.Id == ancestorId)) { - throw new InvalidOperationException($"Cannot link non-existent parent: {ancestorId}"); + continue; } context.AncestorIds.Add(new AncestorId() diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index dc8c33c73..6b749f0a8 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -77,7 +77,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Thu, 14 Nov 2024 10:25:49 +0000 Subject: reverted dbg code --- Jellyfin.Api/Controllers/LibraryStructureController.cs | 11 +++-------- .../Controllers/LibraryStructureControllerTests.cs | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/Jellyfin.Api/Controllers/LibraryStructureController.cs b/Jellyfin.Api/Controllers/LibraryStructureController.cs index 7838c2f61..55000fc91 100644 --- a/Jellyfin.Api/Controllers/LibraryStructureController.cs +++ b/Jellyfin.Api/Controllers/LibraryStructureController.cs @@ -88,14 +88,7 @@ public class LibraryStructureController : BaseJellyfinApiController libraryOptions.PathInfos = Array.ConvertAll(paths, i => new MediaPathInfo(i)); } - try - { - await _libraryManager.AddVirtualFolder(name, collectionType, libraryOptions, refreshLibrary).ConfigureAwait(false); - } - catch (System.Exception ex) - { - return BadRequest(ex.ToString()); - } + await _libraryManager.AddVirtualFolder(name, collectionType, libraryOptions, refreshLibrary).ConfigureAwait(false); return NoContent(); } @@ -106,6 +99,7 @@ public class LibraryStructureController : BaseJellyfinApiController /// The name of the folder. /// Whether to refresh the library. /// Folder removed. + /// Folder not found. /// A . [HttpDelete] [ProducesResponseType(StatusCodes.Status204NoContent)] @@ -113,6 +107,7 @@ public class LibraryStructureController : BaseJellyfinApiController [FromQuery] string name, [FromQuery] bool refreshLibrary = false) { + // TODO: refactor! this relies on an FileNotFound exception to return NotFound when attempting to remove a library that does not exist. await _libraryManager.RemoveVirtualFolder(name, refreshLibrary).ConfigureAwait(false); return NoContent(); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 6b749f0a8..0376f57cc 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -77,7 +77,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Wed, 15 Jan 2025 20:12:41 +0000 Subject: Applied review comments --- .../Data/CleanDatabaseScheduledTask.cs | 14 ++++++++++---- .../Library/UserDataManager.cs | 12 +++++++++--- .../Item/BaseItemRepository.cs | 19 ++++++++++--------- .../Item/ChapterRepository.cs | 2 +- .../Migrations/Routines/MigrateLibraryDb.cs | 15 ++++++++------- src/Jellyfin.Drawing/ImageProcessor.cs | 10 +++++----- .../Controllers/LibraryStructureControllerTests.cs | 2 +- 7 files changed, 44 insertions(+), 30 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs index aceff8b53..7ea863d76 100644 --- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs +++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs @@ -67,10 +67,16 @@ namespace Emby.Server.Implementations.Data progress.Report(percent * 100); } - using var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); - using var transaction = await context.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false); - await context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); + var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + await using (context.ConfigureAwait(false)) + { + var transaction = await context.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false); + await using (transaction.ConfigureAwait(false)) + { + await context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); + } + } progress.Report(100); } diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 9b3a0c1f9..cc45f2fcb 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -146,8 +146,8 @@ namespace Emby.Server.Implementations.Library { ItemId = itemId, CustomDataKey = dto.Key, - Item = null!, - User = null!, + Item = null, + User = null, AudioStreamIndex = dto.AudioStreamIndex, IsFavorite = dto.IsFavorite, LastPlayedDate = dto.LastPlayedDate, @@ -181,7 +181,13 @@ namespace Emby.Server.Implementations.Library private UserItemData? GetUserData(User user, Guid itemId, List keys) { var cacheKey = GetCacheKey(user.InternalId, itemId); - var data = GetUserDataInternal(user.Id, itemId, keys); + + if (_userData.TryGetValue(cacheKey, out var data)) + { + return data; + } + + data = GetUserDataInternal(user.Id, itemId, keys); if (data is null) { diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs index 01e23f56d..1eca0713d 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs @@ -125,7 +125,7 @@ public sealed class BaseItemRepository transaction.Commit(); } - /// + /// public IReadOnlyList GetItemIdsList(InternalItemsQuery filter) { ArgumentNullException.ThrowIfNull(filter); @@ -201,7 +201,7 @@ public sealed class BaseItemRepository _itemTypeLookup.MusicGenreTypes); } - /// + /// public QueryResult GetItems(InternalItemsQuery filter) { ArgumentNullException.ThrowIfNull(filter); @@ -235,7 +235,7 @@ public sealed class BaseItemRepository return result; } - /// + /// public IReadOnlyList GetItemList(InternalItemsQuery filter) { ArgumentNullException.ThrowIfNull(filter); @@ -354,12 +354,14 @@ public sealed class BaseItemRepository { ArgumentException.ThrowIfNullOrEmpty(typeName); + // TODO: this isn't great. Refactor later to be both globally handled by a dedicated service not just an static variable and be loaded eagar. + // currently this is done so that plugins may introduce their own type of baseitems as we dont know when we are first called, before or after plugins are loaded return _typeMap.GetOrAdd(typeName, k => AppDomain.CurrentDomain.GetAssemblies() .Select(a => a.GetType(k)) .FirstOrDefault(t => t is not null)); } - /// + /// public void SaveImages(BaseItemDto item) { ArgumentNullException.ThrowIfNull(item); @@ -373,13 +375,13 @@ public sealed class BaseItemRepository transaction.Commit(); } - /// + /// public void SaveItems(IReadOnlyList items, CancellationToken cancellationToken) { UpdateOrInsertItems(items, cancellationToken); } - /// + /// public void UpdateOrInsertItems(IReadOnlyList items, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(items); @@ -479,7 +481,7 @@ public sealed class BaseItemRepository transaction.Commit(); } - /// + /// public BaseItemDto? RetrieveItem(Guid id) { if (id.IsEmpty()) @@ -890,8 +892,7 @@ public sealed class BaseItemRepository { try { - using var dataAsStream = new MemoryStream(Encoding.UTF8.GetBytes(baseItemEntity.Data!)); - dto = JsonSerializer.Deserialize(dataAsStream, type, JsonDefaults.Options) as BaseItemDto; + dto = JsonSerializer.Deserialize(baseItemEntity.Data, type, JsonDefaults.Options) as BaseItemDto; } catch (JsonException ex) { diff --git a/Jellyfin.Server.Implementations/Item/ChapterRepository.cs b/Jellyfin.Server.Implementations/Item/ChapterRepository.cs index 16e8c205d..fc6f04d56 100644 --- a/Jellyfin.Server.Implementations/Item/ChapterRepository.cs +++ b/Jellyfin.Server.Implementations/Item/ChapterRepository.cs @@ -71,7 +71,7 @@ public class ChapterRepository : IChapterRepository chapter = e, baseItemPath = e.Item.Path }) - .ToList() + .AsEnumerable() .Select(e => Map(e.chapter, e.baseItemPath!)) .ToArray(); } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs index 8b2664ecd..d0360a56d 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs @@ -1,3 +1,5 @@ +#pragma warning disable RS0030 // Do not use banned APIs + using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -21,7 +23,6 @@ using Microsoft.Extensions.Logging; using Chapter = Jellyfin.Data.Entities.Chapter; namespace Jellyfin.Server.Migrations.Routines; -#pragma warning disable RS0030 // Do not use banned APIs /// /// The migration routine for migrating the userdata database to EF Core. @@ -80,7 +81,7 @@ public class MigrateLibraryDb : IMigrationRoutine stopwatch.Restart(); _logger.LogInformation("Start moving TypedBaseItem."); - var typedBaseItemsQuery = """ + const string typedBaseItemsQuery = """ SELECT guid, type, data, StartDate, EndDate, ChannelId, IsMovie, IsSeries, EpisodeTitle, IsRepeat, CommunityRating, CustomRating, IndexNumber, IsLocked, PreferredMetadataLanguage, PreferredMetadataCountryCode, Width, Height, DateLastRefreshed, Name, Path, PremiereDate, Overview, ParentIndexNumber, @@ -111,7 +112,7 @@ public class MigrateLibraryDb : IMigrationRoutine _logger.LogInformation("Start moving ItemValues."); // do not migrate inherited types as they are now properly mapped in search and lookup. - var itemValueQuery = + const string itemValueQuery = """ SELECT ItemId, Type, Value, CleanValue FROM ItemValues WHERE Type <> 6 AND EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = ItemValues.ItemId) @@ -187,7 +188,7 @@ public class MigrateLibraryDb : IMigrationRoutine dbContext.SaveChanges(); _logger.LogInformation("Start moving MediaStreamInfos."); - var mediaStreamQuery = """ + const string mediaStreamQuery = """ SELECT ItemId, StreamIndex, StreamType, Codec, Language, ChannelLayout, Profile, AspectRatio, Path, IsInterlaced, BitRate, Channels, SampleRate, IsDefault, IsForced, IsExternal, Height, Width, AverageFrameRate, RealFrameRate, Level, PixelFormat, BitDepth, IsAnamorphic, RefFrames, CodecTag, @@ -211,7 +212,7 @@ public class MigrateLibraryDb : IMigrationRoutine stopwatch.Restart(); _logger.LogInformation("Start moving People."); - var personsQuery = """ + const string personsQuery = """ SELECT ItemId, Name, Role, PersonType, SortOrder FROM People WHERE EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = People.ItemId) """; @@ -268,7 +269,7 @@ public class MigrateLibraryDb : IMigrationRoutine stopwatch.Restart(); _logger.LogInformation("Start moving Chapters."); - var chapterQuery = """ + const string chapterQuery = """ SELECT ItemId,StartPositionTicks,Name,ImagePath,ImageDateModified,ChapterIndex from Chapters2 WHERE EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = Chapters2.ItemId) """; @@ -287,7 +288,7 @@ public class MigrateLibraryDb : IMigrationRoutine stopwatch.Restart(); _logger.LogInformation("Start moving AncestorIds."); - var ancestorIdsQuery = """ + const string ancestorIdsQuery = """ SELECT ItemId, AncestorId, AncestorIdText FROM AncestorIds WHERE EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = AncestorIds.ItemId) diff --git a/src/Jellyfin.Drawing/ImageProcessor.cs b/src/Jellyfin.Drawing/ImageProcessor.cs index 7ba9ff172..0bd3b8920 100644 --- a/src/Jellyfin.Drawing/ImageProcessor.cs +++ b/src/Jellyfin.Drawing/ImageProcessor.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net.Mime; +using System.Reflection.Metadata.Ecma335; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -410,11 +411,11 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable /// public string GetImageCacheTag(BaseItem item, ItemImageInfo image) - => (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture); + => GetImageCacheTag(item.Path, image.DateModified); /// public string GetImageCacheTag(BaseItemDto item, ItemImageInfo image) - => (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture); + => GetImageCacheTag(item.Path, image.DateModified); /// public string? GetImageCacheTag(BaseItemDto item, ChapterInfo chapter) @@ -424,7 +425,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable return null; } - return (item.Path + chapter.ImageDateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture); + return GetImageCacheTag(item.Path, chapter.ImageDateModified); } /// @@ -451,8 +452,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable return null; } - return (user.ProfileImage.Path + user.ProfileImage.LastModified.Ticks).GetMD5() - .ToString("N", CultureInfo.InvariantCulture); + return GetImageCacheTag(user.ProfileImage.Path, user.ProfileImage.LastModified); } private Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified) diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 0376f57cc..e7166d424 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -45,7 +45,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Sun, 19 Jan 2025 12:29:14 +0000 Subject: Applied review comments --- Jellyfin.Server.Implementations/Item/BaseItemRepository.cs | 8 +------- .../Controllers/LibraryStructureControllerTests.cs | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs index 970eaa3ba..a4e3f75ec 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs @@ -1216,13 +1216,7 @@ public sealed class BaseItemRepository if (hasSearch) { - List<(ItemSortBy, SortOrder)> prepend = new List<(ItemSortBy, SortOrder)>(4); - if (hasSearch) - { - prepend.Add((ItemSortBy.SortName, SortOrder.Ascending)); - } - - orderBy = filter.OrderBy = [.. prepend, .. orderBy]; + orderBy = filter.OrderBy = [(ItemSortBy.SortName, SortOrder.Ascending), .. orderBy]; } else if (orderBy.Count == 0) { diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index e7166d424..0f318f5a0 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -62,7 +62,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture Date: Sun, 19 Jan 2025 12:41:11 +0000 Subject: Fixed tests again --- .../Controllers/LibraryStructureControllerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs') diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs index 0f318f5a0..e7166d424 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs @@ -62,7 +62,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture