fix cache serialization fallback for Jellyfin metadata

This commit is contained in:
2026-04-06 03:28:12 -04:00
parent 7550d01667
commit 885c86358d
2 changed files with 143 additions and 10 deletions
+91
View File
@@ -4,6 +4,9 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Text.Json;
using allstarr.Models.Domain;
using allstarr.Models.Spotify;
using allstarr.Services.Common;
using allstarr.Models.Settings;
@@ -337,6 +340,94 @@ public class RedisCacheServiceTests
Assert.False(exists);
}
[Fact]
public async Task SetAsync_WhenSongContainsRawJellyfinMetadata_CachesSerializedValueInMemory()
{
var service = CreateService();
var songs = new List<Song> { CreateLocalSongWithRawJellyfinMetadata() };
var setResult = await service.SetAsync("test:songs:raw-jellyfin", songs);
var cachedValue = await service.GetAsync<List<Song>>("test:songs:raw-jellyfin");
Assert.False(setResult);
Assert.NotNull(cachedValue);
var roundTrippedSong = Assert.Single(cachedValue!);
Assert.True(JellyfinItemSnapshotHelper.TryGetClonedRawItemSnapshot(roundTrippedSong, out var rawItem));
Assert.Equal("song-1", ((JsonElement)rawItem["Id"]!).GetString());
var mediaSources = Assert.IsType<JsonElement>(roundTrippedSong.JellyfinMetadata!["MediaSources"]);
Assert.Equal(JsonValueKind.Array, mediaSources.ValueKind);
Assert.Equal(2234068710L, mediaSources[0].GetProperty("RunTimeTicks").GetInt64());
}
[Fact]
public async Task SetAsync_WhenMatchedTracksContainRawJellyfinMetadata_CachesSerializedValueInMemory()
{
var service = CreateService();
var matchedTracks = new List<MatchedTrack>
{
new()
{
Position = 0,
SpotifyId = "spotify-1",
SpotifyTitle = "Track",
SpotifyArtist = "Artist",
MatchType = "fuzzy",
MatchedSong = CreateLocalSongWithRawJellyfinMetadata()
}
};
var setResult = await service.SetAsync("test:matched:raw-jellyfin", matchedTracks);
var cachedValue = await service.GetAsync<List<MatchedTrack>>("test:matched:raw-jellyfin");
Assert.False(setResult);
Assert.NotNull(cachedValue);
var roundTrippedMatch = Assert.Single(cachedValue!);
Assert.True(
JellyfinItemSnapshotHelper.TryGetClonedRawItemSnapshot(roundTrippedMatch.MatchedSong, out var rawItem));
Assert.Equal("song-1", ((JsonElement)rawItem["Id"]!).GetString());
var mediaSources =
Assert.IsType<JsonElement>(roundTrippedMatch.MatchedSong.JellyfinMetadata!["MediaSources"]);
Assert.Equal(JsonValueKind.Array, mediaSources.ValueKind);
Assert.Equal("song-1", mediaSources[0].GetProperty("Id").GetString());
}
private static Song CreateLocalSongWithRawJellyfinMetadata()
{
var song = new Song
{
Id = "song-1",
Title = "Track",
Artist = "Artist",
Album = "Album",
IsLocal = true
};
using var doc = JsonDocument.Parse("""
{
"Id": "song-1",
"ServerId": "c17d351d3af24c678a6d8049c212d522",
"RunTimeTicks": 2234068710,
"MediaSources": [
{
"Id": "song-1",
"RunTimeTicks": 2234068710
}
]
}
""");
JellyfinItemSnapshotHelper.StoreRawItemSnapshot(song, doc.RootElement);
song.JellyfinMetadata ??= new Dictionary<string, object?>();
song.JellyfinMetadata["MediaSources"] =
JsonSerializer.Deserialize<object>(doc.RootElement.GetProperty("MediaSources").GetRawText());
return song;
}
private class TestObject
{
public int Id { get; set; }