using System;
using System.Collections.Concurrent;
using Jellyfin.Plugin.SRFPlay.Api.Models;
using Jellyfin.Plugin.SRFPlay.Services.Interfaces;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.SRFPlay.Services;
///
/// Service for caching metadata from SRF API.
///
public sealed class MetadataCache : IMetadataCache
{
private readonly ILogger _logger;
private readonly ConcurrentDictionary> _mediaCompositionCache;
///
/// Initializes a new instance of the class.
///
/// The logger instance.
public MetadataCache(ILogger logger)
{
_logger = logger;
_mediaCompositionCache = new ConcurrentDictionary>();
}
///
/// Gets cached media composition by URN.
///
/// The URN.
/// The cache duration in minutes.
/// The cached media composition, or null if not found or expired.
public MediaComposition? GetMediaComposition(string urn, int cacheDurationMinutes)
{
if (string.IsNullOrEmpty(urn))
{
return null;
}
if (_mediaCompositionCache.TryGetValue(urn, out var entry))
{
if (entry.IsValid(cacheDurationMinutes))
{
_logger.LogDebug("Cache hit for URN: {Urn}", urn);
return entry.Value;
}
_logger.LogDebug("Cache entry expired for URN: {Urn}", urn);
}
return null;
}
///
/// Sets media composition in cache.
///
/// The URN.
/// The media composition to cache.
public void SetMediaComposition(string urn, MediaComposition mediaComposition)
{
if (string.IsNullOrEmpty(urn) || mediaComposition == null)
{
return;
}
var entry = new CacheEntry(mediaComposition);
_mediaCompositionCache.AddOrUpdate(urn, entry, (key, oldValue) => entry);
_logger.LogDebug("Cached media composition for URN: {Urn}", urn);
}
///
/// Clears all cached data.
///
public void Clear()
{
_mediaCompositionCache.Clear();
_logger.LogInformation("Cleared metadata cache");
}
///
/// Represents a cached entry with timestamp.
///
/// The type of cached value.
private sealed class CacheEntry
{
///
/// Initializes a new instance of the class.
///
/// The value to cache.
public CacheEntry(T value)
{
Value = value;
Timestamp = DateTime.UtcNow;
}
///
/// Gets the cached value.
///
public T Value { get; }
///
/// Gets the timestamp when the entry was created.
///
public DateTime Timestamp { get; }
///
/// Checks if the cache entry is still valid.
///
/// The cache duration in minutes.
/// True if the entry is still valid.
public bool IsValid(int cacheDurationMinutes)
{
var expirationTime = Timestamp.AddMinutes(cacheDurationMinutes);
return DateTime.UtcNow < expirationTime;
}
}
}