mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Applied review comments
This commit is contained in:
parent
d716a53ec2
commit
b33810534b
@ -67,10 +67,16 @@ namespace Emby.Server.Implementations.Data
|
|||||||
progress.Report(percent * 100);
|
progress.Report(percent * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
using var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
|
var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
|
||||||
using var transaction = await context.Database.BeginTransactionAsync(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 context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false);
|
||||||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
progress.Report(100);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
|
@ -146,8 +146,8 @@ namespace Emby.Server.Implementations.Library
|
|||||||
{
|
{
|
||||||
ItemId = itemId,
|
ItemId = itemId,
|
||||||
CustomDataKey = dto.Key,
|
CustomDataKey = dto.Key,
|
||||||
Item = null!,
|
Item = null,
|
||||||
User = null!,
|
User = null,
|
||||||
AudioStreamIndex = dto.AudioStreamIndex,
|
AudioStreamIndex = dto.AudioStreamIndex,
|
||||||
IsFavorite = dto.IsFavorite,
|
IsFavorite = dto.IsFavorite,
|
||||||
LastPlayedDate = dto.LastPlayedDate,
|
LastPlayedDate = dto.LastPlayedDate,
|
||||||
@ -181,7 +181,13 @@ namespace Emby.Server.Implementations.Library
|
|||||||
private UserItemData? GetUserData(User user, Guid itemId, List<string> keys)
|
private UserItemData? GetUserData(User user, Guid itemId, List<string> keys)
|
||||||
{
|
{
|
||||||
var cacheKey = GetCacheKey(user.InternalId, itemId);
|
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)
|
if (data is null)
|
||||||
{
|
{
|
||||||
|
@ -125,7 +125,7 @@ public sealed class BaseItemRepository
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IItemRepository"/>
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<Guid> GetItemIdsList(InternalItemsQuery filter)
|
public IReadOnlyList<Guid> GetItemIdsList(InternalItemsQuery filter)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(filter);
|
ArgumentNullException.ThrowIfNull(filter);
|
||||||
@ -201,7 +201,7 @@ public sealed class BaseItemRepository
|
|||||||
_itemTypeLookup.MusicGenreTypes);
|
_itemTypeLookup.MusicGenreTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IItemRepository"/>
|
/// <inheritdoc />
|
||||||
public QueryResult<BaseItemDto> GetItems(InternalItemsQuery filter)
|
public QueryResult<BaseItemDto> GetItems(InternalItemsQuery filter)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(filter);
|
ArgumentNullException.ThrowIfNull(filter);
|
||||||
@ -235,7 +235,7 @@ public sealed class BaseItemRepository
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IItemRepository"/>
|
/// <inheritdoc />
|
||||||
public IReadOnlyList<BaseItemDto> GetItemList(InternalItemsQuery filter)
|
public IReadOnlyList<BaseItemDto> GetItemList(InternalItemsQuery filter)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(filter);
|
ArgumentNullException.ThrowIfNull(filter);
|
||||||
@ -354,12 +354,14 @@ public sealed class BaseItemRepository
|
|||||||
{
|
{
|
||||||
ArgumentException.ThrowIfNullOrEmpty(typeName);
|
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()
|
return _typeMap.GetOrAdd(typeName, k => AppDomain.CurrentDomain.GetAssemblies()
|
||||||
.Select(a => a.GetType(k))
|
.Select(a => a.GetType(k))
|
||||||
.FirstOrDefault(t => t is not null));
|
.FirstOrDefault(t => t is not null));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IItemRepository" />
|
/// <inheritdoc />
|
||||||
public void SaveImages(BaseItemDto item)
|
public void SaveImages(BaseItemDto item)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(item);
|
ArgumentNullException.ThrowIfNull(item);
|
||||||
@ -373,13 +375,13 @@ public sealed class BaseItemRepository
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IItemRepository" />
|
/// <inheritdoc />
|
||||||
public void SaveItems(IReadOnlyList<BaseItemDto> items, CancellationToken cancellationToken)
|
public void SaveItems(IReadOnlyList<BaseItemDto> items, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
UpdateOrInsertItems(items, cancellationToken);
|
UpdateOrInsertItems(items, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IItemRepository" />
|
/// <inheritdoc />
|
||||||
public void UpdateOrInsertItems(IReadOnlyList<BaseItemDto> items, CancellationToken cancellationToken)
|
public void UpdateOrInsertItems(IReadOnlyList<BaseItemDto> items, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(items);
|
ArgumentNullException.ThrowIfNull(items);
|
||||||
@ -479,7 +481,7 @@ public sealed class BaseItemRepository
|
|||||||
transaction.Commit();
|
transaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IItemRepository" />
|
/// <inheritdoc />
|
||||||
public BaseItemDto? RetrieveItem(Guid id)
|
public BaseItemDto? RetrieveItem(Guid id)
|
||||||
{
|
{
|
||||||
if (id.IsEmpty())
|
if (id.IsEmpty())
|
||||||
@ -890,8 +892,7 @@ public sealed class BaseItemRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var dataAsStream = new MemoryStream(Encoding.UTF8.GetBytes(baseItemEntity.Data!));
|
dto = JsonSerializer.Deserialize(baseItemEntity.Data, type, JsonDefaults.Options) as BaseItemDto;
|
||||||
dto = JsonSerializer.Deserialize(dataAsStream, type, JsonDefaults.Options) as BaseItemDto;
|
|
||||||
}
|
}
|
||||||
catch (JsonException ex)
|
catch (JsonException ex)
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,7 @@ public class ChapterRepository : IChapterRepository
|
|||||||
chapter = e,
|
chapter = e,
|
||||||
baseItemPath = e.Item.Path
|
baseItemPath = e.Item.Path
|
||||||
})
|
})
|
||||||
.ToList()
|
.AsEnumerable()
|
||||||
.Select(e => Map(e.chapter, e.baseItemPath!))
|
.Select(e => Map(e.chapter, e.baseItemPath!))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#pragma warning disable RS0030 // Do not use banned APIs
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
@ -21,7 +23,6 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Chapter = Jellyfin.Data.Entities.Chapter;
|
using Chapter = Jellyfin.Data.Entities.Chapter;
|
||||||
|
|
||||||
namespace Jellyfin.Server.Migrations.Routines;
|
namespace Jellyfin.Server.Migrations.Routines;
|
||||||
#pragma warning disable RS0030 // Do not use banned APIs
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The migration routine for migrating the userdata database to EF Core.
|
/// The migration routine for migrating the userdata database to EF Core.
|
||||||
@ -80,7 +81,7 @@ public class MigrateLibraryDb : IMigrationRoutine
|
|||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
|
|
||||||
_logger.LogInformation("Start moving TypedBaseItem.");
|
_logger.LogInformation("Start moving TypedBaseItem.");
|
||||||
var typedBaseItemsQuery = """
|
const string typedBaseItemsQuery = """
|
||||||
SELECT guid, type, data, StartDate, EndDate, ChannelId, IsMovie,
|
SELECT guid, type, data, StartDate, EndDate, ChannelId, IsMovie,
|
||||||
IsSeries, EpisodeTitle, IsRepeat, CommunityRating, CustomRating, IndexNumber, IsLocked, PreferredMetadataLanguage,
|
IsSeries, EpisodeTitle, IsRepeat, CommunityRating, CustomRating, IndexNumber, IsLocked, PreferredMetadataLanguage,
|
||||||
PreferredMetadataCountryCode, Width, Height, DateLastRefreshed, Name, Path, PremiereDate, Overview, ParentIndexNumber,
|
PreferredMetadataCountryCode, Width, Height, DateLastRefreshed, Name, Path, PremiereDate, Overview, ParentIndexNumber,
|
||||||
@ -111,7 +112,7 @@ public class MigrateLibraryDb : IMigrationRoutine
|
|||||||
|
|
||||||
_logger.LogInformation("Start moving ItemValues.");
|
_logger.LogInformation("Start moving ItemValues.");
|
||||||
// do not migrate inherited types as they are now properly mapped in search and lookup.
|
// 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
|
SELECT ItemId, Type, Value, CleanValue FROM ItemValues
|
||||||
WHERE Type <> 6 AND EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = ItemValues.ItemId)
|
WHERE Type <> 6 AND EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = ItemValues.ItemId)
|
||||||
@ -187,7 +188,7 @@ public class MigrateLibraryDb : IMigrationRoutine
|
|||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
_logger.LogInformation("Start moving MediaStreamInfos.");
|
_logger.LogInformation("Start moving MediaStreamInfos.");
|
||||||
var mediaStreamQuery = """
|
const string mediaStreamQuery = """
|
||||||
SELECT ItemId, StreamIndex, StreamType, Codec, Language, ChannelLayout, Profile, AspectRatio, Path,
|
SELECT ItemId, StreamIndex, StreamType, Codec, Language, ChannelLayout, Profile, AspectRatio, Path,
|
||||||
IsInterlaced, BitRate, Channels, SampleRate, IsDefault, IsForced, IsExternal, Height, Width,
|
IsInterlaced, BitRate, Channels, SampleRate, IsDefault, IsForced, IsExternal, Height, Width,
|
||||||
AverageFrameRate, RealFrameRate, Level, PixelFormat, BitDepth, IsAnamorphic, RefFrames, CodecTag,
|
AverageFrameRate, RealFrameRate, Level, PixelFormat, BitDepth, IsAnamorphic, RefFrames, CodecTag,
|
||||||
@ -211,7 +212,7 @@ public class MigrateLibraryDb : IMigrationRoutine
|
|||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
|
|
||||||
_logger.LogInformation("Start moving People.");
|
_logger.LogInformation("Start moving People.");
|
||||||
var personsQuery = """
|
const string personsQuery = """
|
||||||
SELECT ItemId, Name, Role, PersonType, SortOrder FROM People
|
SELECT ItemId, Name, Role, PersonType, SortOrder FROM People
|
||||||
WHERE EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = People.ItemId)
|
WHERE EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = People.ItemId)
|
||||||
""";
|
""";
|
||||||
@ -268,7 +269,7 @@ public class MigrateLibraryDb : IMigrationRoutine
|
|||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
|
|
||||||
_logger.LogInformation("Start moving Chapters.");
|
_logger.LogInformation("Start moving Chapters.");
|
||||||
var chapterQuery = """
|
const string chapterQuery = """
|
||||||
SELECT ItemId,StartPositionTicks,Name,ImagePath,ImageDateModified,ChapterIndex from Chapters2
|
SELECT ItemId,StartPositionTicks,Name,ImagePath,ImageDateModified,ChapterIndex from Chapters2
|
||||||
WHERE EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = Chapters2.ItemId)
|
WHERE EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = Chapters2.ItemId)
|
||||||
""";
|
""";
|
||||||
@ -287,7 +288,7 @@ public class MigrateLibraryDb : IMigrationRoutine
|
|||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
|
|
||||||
_logger.LogInformation("Start moving AncestorIds.");
|
_logger.LogInformation("Start moving AncestorIds.");
|
||||||
var ancestorIdsQuery = """
|
const string ancestorIdsQuery = """
|
||||||
SELECT ItemId, AncestorId, AncestorIdText FROM AncestorIds
|
SELECT ItemId, AncestorId, AncestorIdText FROM AncestorIds
|
||||||
WHERE
|
WHERE
|
||||||
EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = AncestorIds.ItemId)
|
EXISTS(SELECT 1 FROM TypedBaseItems WHERE TypedBaseItems.guid = AncestorIds.ItemId)
|
||||||
|
@ -4,6 +4,7 @@ using System.Globalization;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Mime;
|
using System.Net.Mime;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -410,11 +411,11 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
|
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
|
||||||
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
=> GetImageCacheTag(item.Path, image.DateModified);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetImageCacheTag(BaseItemDto item, ItemImageInfo image)
|
public string GetImageCacheTag(BaseItemDto item, ItemImageInfo image)
|
||||||
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
=> GetImageCacheTag(item.Path, image.DateModified);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string? GetImageCacheTag(BaseItemDto item, ChapterInfo chapter)
|
public string? GetImageCacheTag(BaseItemDto item, ChapterInfo chapter)
|
||||||
@ -424,7 +425,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (item.Path + chapter.ImageDateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
return GetImageCacheTag(item.Path, chapter.ImageDateModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -451,8 +452,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (user.ProfileImage.Path + user.ProfileImage.LastModified.Ticks).GetMD5()
|
return GetImageCacheTag(user.ProfileImage.Path, user.ProfileImage.LastModified);
|
||||||
.ToString("N", CultureInfo.InvariantCulture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
|
private Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
|
||||||
|
@ -45,7 +45,7 @@ public sealed class LibraryStructureControllerTests : IClassFixture<JellyfinAppl
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[Priority(0)]
|
[Priority(-2)]
|
||||||
public async Task UpdateLibraryOptions_Invalid_NotFound()
|
public async Task UpdateLibraryOptions_Invalid_NotFound()
|
||||||
{
|
{
|
||||||
var client = _factory.CreateClient();
|
var client = _factory.CreateClient();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user