aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJPVenson <github@jpb.email>2025-01-15 20:12:41 +0000
committerJPVenson <github@jpb.email>2025-01-15 20:12:41 +0000
commitb33810534b85f96702035a54a4c661cc4d31d928 (patch)
treea8d7007df3bd8c65b2d268adc6d2e0033ac27435
parentd716a53ec2433c6af43dfbce7f92fc9c2927592a (diff)
Applied review comments
-rw-r--r--Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs14
-rw-r--r--Emby.Server.Implementations/Library/UserDataManager.cs12
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.cs19
-rw-r--r--Jellyfin.Server.Implementations/Item/ChapterRepository.cs2
-rw-r--r--Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs15
-rw-r--r--src/Jellyfin.Drawing/ImageProcessor.cs10
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/LibraryStructureControllerTests.cs2
7 files changed, 44 insertions, 30 deletions
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<string> 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();
}
- /// <inheritdoc cref="IItemRepository"/>
+ /// <inheritdoc />
public IReadOnlyList<Guid> GetItemIdsList(InternalItemsQuery filter)
{
ArgumentNullException.ThrowIfNull(filter);
@@ -201,7 +201,7 @@ public sealed class BaseItemRepository
_itemTypeLookup.MusicGenreTypes);
}
- /// <inheritdoc cref="IItemRepository"/>
+ /// <inheritdoc />
public QueryResult<BaseItemDto> GetItems(InternalItemsQuery filter)
{
ArgumentNullException.ThrowIfNull(filter);
@@ -235,7 +235,7 @@ public sealed class BaseItemRepository
return result;
}
- /// <inheritdoc cref="IItemRepository"/>
+ /// <inheritdoc />
public IReadOnlyList<BaseItemDto> 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));
}
- /// <inheritdoc cref="IItemRepository" />
+ /// <inheritdoc />
public void SaveImages(BaseItemDto item)
{
ArgumentNullException.ThrowIfNull(item);
@@ -373,13 +375,13 @@ public sealed class BaseItemRepository
transaction.Commit();
}
- /// <inheritdoc cref="IItemRepository" />
+ /// <inheritdoc />
public void SaveItems(IReadOnlyList<BaseItemDto> items, CancellationToken cancellationToken)
{
UpdateOrInsertItems(items, cancellationToken);
}
- /// <inheritdoc cref="IItemRepository" />
+ /// <inheritdoc />
public void UpdateOrInsertItems(IReadOnlyList<BaseItemDto> items, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(items);
@@ -479,7 +481,7 @@ public sealed class BaseItemRepository
transaction.Commit();
}
- /// <inheritdoc cref="IItemRepository" />
+ /// <inheritdoc />
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
/// <summary>
/// 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
/// <inheritdoc />
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
- => (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+ => GetImageCacheTag(item.Path, image.DateModified);
/// <inheritdoc />
public string GetImageCacheTag(BaseItemDto item, ItemImageInfo image)
- => (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+ => GetImageCacheTag(item.Path, image.DateModified);
/// <inheritdoc />
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);
}
/// <inheritdoc />
@@ -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<JellyfinAppl
}
[Fact]
- [Priority(0)]
+ [Priority(-2)]
public async Task UpdateLibraryOptions_Invalid_NotFound()
{
var client = _factory.CreateClient();