Apply review suggestions

This commit is contained in:
Shadowghost 2026-04-11 18:00:41 +02:00
parent e0f50f504a
commit 60e01e1f22
3 changed files with 36 additions and 5 deletions

View file

@ -21,4 +21,11 @@ public interface ISchedulesDirectService
/// </summary>
/// <returns><c>true</c> if the image limit has been hit and has not yet reset; otherwise <c>false</c>.</returns>
bool IsImageDailyLimitActive();
/// <summary>
/// Gets a value indicating whether the Schedules Direct service is available.
/// Returns <c>false</c> if a permanent account error has occurred or a transient backoff is active.
/// </summary>
/// <returns><c>true</c> if the service can accept requests; otherwise <c>false</c>.</returns>
bool IsServiceAvailable();
}

View file

@ -738,6 +738,14 @@ public class GuideManager : IGuideManager
_cacheParallelOptions,
async (program, cancellationToken) =>
{
// Re-check: limit may have been set by a parallel task since the LINQ filter ran.
if (_schedulesDirectService.IsImageDailyLimitActive()
&& program.ImageInfos.All(
img => img.IsLocalFile || img.Path.Contains("schedulesdirect", StringComparison.OrdinalIgnoreCase)))
{
return;
}
for (var i = 0; i < program.ImageInfos.Length; i++)
{
if (cancellationToken.IsCancellationRequested)

View file

@ -45,8 +45,8 @@ namespace Jellyfin.LiveTv.Listings
private readonly ConcurrentDictionary<string, NameValuePair> _tokens = new();
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private DateTime _lastErrorResponse;
private bool _accountError;
private long _lastErrorResponseTicks;
private volatile bool _accountError;
private bool _disposed = false;
private byte[] _countriesCache;
@ -594,7 +594,7 @@ namespace Jellyfin.LiveTv.Listings
}
// Avoid hammering SD after transient login failures (e.g. max attempts / temporary lockout)
if ((DateTime.UtcNow - _lastErrorResponse).TotalMinutes < 30)
if ((DateTime.UtcNow - new DateTime(Interlocked.Read(ref _lastErrorResponseTicks), DateTimeKind.Utc)).TotalMinutes < 30)
{
return null;
}
@ -635,7 +635,7 @@ namespace Jellyfin.LiveTv.Listings
&& (int)ex.StatusCode.Value < 500)
{
_tokens.Clear();
_lastErrorResponse = DateTime.UtcNow;
Interlocked.Exchange(ref _lastErrorResponseTicks, DateTime.UtcNow.Ticks);
}
throw;
@ -695,7 +695,7 @@ namespace Jellyfin.LiveTv.Listings
{
// Transient login errors — back off for 30 minutes, then allow retry.
_tokens.Clear();
_lastErrorResponse = DateTime.UtcNow;
Interlocked.Exchange(ref _lastErrorResponseTicks, DateTime.UtcNow.Ticks);
}
else if (sdCode is SdErrorCode.MaxImageDownloads)
{
@ -876,6 +876,22 @@ namespace Jellyfin.LiveTv.Listings
return null;
}
/// <inheritdoc />
public bool IsServiceAvailable()
{
if (_accountError)
{
return false;
}
if ((DateTime.UtcNow - new DateTime(Interlocked.Read(ref _lastErrorResponseTicks), DateTimeKind.Utc)).TotalMinutes < 30)
{
return false;
}
return true;
}
/// <inheritdoc />
public bool IsImageDailyLimitActive()
{