Duncan Tourolle a0e7663323
All checks were successful
🏗️ Build Plugin / build (push) Successful in 2m35s
🧪 Test Plugin / test (push) Successful in 1m14s
refactor to unify data fetching and define abstract API for re-use
2025-12-06 17:29:05 +01:00

83 lines
2.8 KiB
C#

using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.SRFPlay.Api;
using Jellyfin.Plugin.SRFPlay.Api.Models;
using Jellyfin.Plugin.SRFPlay.Services.Interfaces;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.SRFPlay.Services;
/// <summary>
/// Service for fetching media composition with caching support.
/// This consolidates the cache-check → API-fetch → cache-store pattern.
/// </summary>
public class MediaCompositionFetcher : IMediaCompositionFetcher
{
private readonly ILogger<MediaCompositionFetcher> _logger;
private readonly IMetadataCache _metadataCache;
private readonly ISRFApiClientFactory _apiClientFactory;
/// <summary>
/// Initializes a new instance of the <see cref="MediaCompositionFetcher"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="metadataCache">The metadata cache.</param>
/// <param name="apiClientFactory">The API client factory.</param>
public MediaCompositionFetcher(
ILogger<MediaCompositionFetcher> logger,
IMetadataCache metadataCache,
ISRFApiClientFactory apiClientFactory)
{
_logger = logger;
_metadataCache = metadataCache;
_apiClientFactory = apiClientFactory;
}
/// <inheritdoc />
public async Task<MediaComposition?> GetMediaCompositionAsync(
string urn,
CancellationToken cancellationToken,
int? cacheDurationOverride = null)
{
if (string.IsNullOrEmpty(urn))
{
_logger.LogDebug("GetMediaCompositionAsync called with null/empty URN");
return null;
}
var config = Plugin.Instance?.Configuration;
if (config == null)
{
_logger.LogWarning("Plugin configuration is null, cannot fetch media composition");
return null;
}
var cacheDuration = cacheDurationOverride ?? config.CacheDurationMinutes;
// Try cache first
var mediaComposition = _metadataCache.GetMediaComposition(urn, cacheDuration);
if (mediaComposition != null)
{
_logger.LogDebug("Cache hit for URN: {Urn}", urn);
return mediaComposition;
}
// Fetch from API
_logger.LogDebug("Cache miss for URN: {Urn}, fetching from API", urn);
using var apiClient = _apiClientFactory.CreateClient();
mediaComposition = await apiClient.GetMediaCompositionByUrnAsync(urn, cancellationToken).ConfigureAwait(false);
if (mediaComposition != null)
{
_metadataCache.SetMediaComposition(urn, mediaComposition);
_logger.LogDebug("Cached media composition for URN: {Urn}", urn);
}
else
{
_logger.LogWarning("Failed to fetch media composition for URN: {Urn}", urn);
}
return mediaComposition;
}
}