diff --git a/src/API/src/Program.cs b/src/API/src/Program.cs index 980e6dd..5bcb8fb 100644 --- a/src/API/src/Program.cs +++ b/src/API/src/Program.cs @@ -43,7 +43,8 @@ static async Task Main(string[] args) builder.Services.AddCaching(opts => opts .UseHybrid("metadata", opts => opts.SQLite.DatabasePath = "metadata.sqlite") - .UseInMemory("watchlist")); + .UseInMemory("watchlist") + .UseInMemory("plex-graphql")); builder.Services.AddFetcharr(); builder.Services.AddControllers(); diff --git a/src/Cache/InMemory/src/InMemoryCachingProvider.cs b/src/Cache/InMemory/src/InMemoryCachingProvider.cs index 5f2d696..f3da4d0 100644 --- a/src/Cache/InMemory/src/InMemoryCachingProvider.cs +++ b/src/Cache/InMemory/src/InMemoryCachingProvider.cs @@ -79,6 +79,8 @@ public override async Task SetAsync(string key, T value, TimeSpan? expiration { this._database[key] = new InMemoryCacheItem(value, _expiration); + Interlocked.Increment(ref this.CacheSize); + if(options.Value.SizeLimit > 0 && Interlocked.Read(ref this.CacheSize) >= options.Value.SizeLimit) { int itemsToRemove = (int) (Interlocked.Read(ref this.CacheSize) - options.Value.SizeLimit); diff --git a/src/Provider.Plex/src/PlexWatchlistClient.cs b/src/Provider.Plex/src/PlexWatchlistClient.cs index 58602a5..7b5c20e 100644 --- a/src/Provider.Plex/src/PlexWatchlistClient.cs +++ b/src/Provider.Plex/src/PlexWatchlistClient.cs @@ -7,6 +7,7 @@ using Flurl.Http; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Fetcharr.Provider.Plex @@ -16,12 +17,14 @@ namespace Fetcharr.Provider.Plex /// public class PlexWatchlistClient( IOptions configuration, - [FromKeyedServices("watchlist")] ICachingProvider cachingProvider) + [FromKeyedServices("watchlist")] ICachingProvider cachingProvider, + ILogger logger) { private readonly FlurlClient _client = new FlurlClient("https://metadata.provider.plex.tv/library/sections/watchlist/") .WithHeader("X-Plex-Token", configuration.Value.Plex.ApiToken) - .WithHeader("X-Plex-Client-Identifier", "fetcharr"); + .WithHeader("X-Plex-Client-Identifier", "fetcharr") + .AllowHttpStatus((int) HttpStatusCode.NotModified); /// /// If not , contains the E-Tag value of the last watchlist request. @@ -48,10 +51,17 @@ public async Task> FetchWatchlistAsync(int of CacheValue> cacheValue = await cachingProvider.GetAsync>("watchlist"); - if(cacheValue.HasValue) + // If Plex returned NotModified, but the cache is empty, it must've been evicted + // which means we have to resend the request without E-Tag caching. + if(!cacheValue.HasValue) { - return cacheValue.Value; + logger.LogInformation("Watchlist cache has been evicted; re-sending request..."); + + this.lastEtag = null; + return await this.FetchWatchlistAsync(offset, limit); } + + return cacheValue.Value; } MediaResponse watchlistContainer = await response