From b9c0fc69e8fee820b06da2fed9e7136711d8028d Mon Sep 17 00:00:00 2001 From: gnattu Date: Sat, 25 May 2024 01:12:00 +0800 Subject: [PATCH] Add Env Var to disable second level cache This is an attempt to track down possible causes of remaining database lockups. Add an environment variable to disable the second-level cache entirely to see if it works better on systems that still experience lockups. Signed-off-by: gnattu --- .../ConfigurationOptions.cs | 3 ++- .../Extensions/ServiceCollectionExtensions.cs | 25 +++++++++++------- .../Extensions/WebHostBuilderExtensions.cs | 2 +- Jellyfin.Server/Startup.cs | 7 +++-- .../Extensions/ConfigurationExtensions.cs | 26 +++++++++++++++++++ 5 files changed, 50 insertions(+), 13 deletions(-) diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index f0c26762795..c06cd851093 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -19,7 +19,8 @@ public static class ConfigurationOptions { FfmpegAnalyzeDurationKey, "200M" }, { PlaylistsAllowDuplicatesKey, bool.FalseString }, { BindToUnixSocketKey, bool.FalseString }, - { SqliteCacheSizeKey, "20000" } + { SqliteCacheSizeKey, "20000" }, + { SqliteDisableSecondLevelCacheKey, bool.FalseString } }; } } diff --git a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs index 3d747f2ea90..a8898984067 100644 --- a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs @@ -16,21 +16,28 @@ public static class ServiceCollectionExtensions /// Adds the interface to the service collection with second level caching enabled. /// /// An instance of the interface. + /// Whether second level cache disabled.. /// The updated service collection. - public static IServiceCollection AddJellyfinDbContext(this IServiceCollection serviceCollection) + public static IServiceCollection AddJellyfinDbContext(this IServiceCollection serviceCollection, bool disableSecondLevelCache) { - serviceCollection.AddEFSecondLevelCache(options => - options.UseMemoryCacheProvider() - .CacheAllQueries(CacheExpirationMode.Sliding, TimeSpan.FromMinutes(10)) - .UseCacheKeyPrefix("EF_") - // Don't cache null values. Remove this optional setting if it's not necessary. - .SkipCachingResults(result => result.Value is null or EFTableRows { RowsCount: 0 })); + if (!disableSecondLevelCache) + { + serviceCollection.AddEFSecondLevelCache(options => + options.UseMemoryCacheProvider() + .CacheAllQueries(CacheExpirationMode.Sliding, TimeSpan.FromMinutes(10)) + .UseCacheKeyPrefix("EF_") + // Don't cache null values. Remove this optional setting if it's not necessary. + .SkipCachingResults(result => result.Value is null or EFTableRows { RowsCount: 0 })); + } serviceCollection.AddPooledDbContextFactory((serviceProvider, opt) => { var applicationPaths = serviceProvider.GetRequiredService(); - opt.UseSqlite($"Filename={Path.Combine(applicationPaths.DataPath, "jellyfin.db")}") - .AddInterceptors(serviceProvider.GetRequiredService()); + var dbOpt = opt.UseSqlite($"Filename={Path.Combine(applicationPaths.DataPath, "jellyfin.db")}"); + if (!disableSecondLevelCache) + { + dbOpt.AddInterceptors(serviceProvider.GetRequiredService()); + } }); return serviceCollection; diff --git a/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs b/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs index 6b95770ed58..858df6728b5 100644 --- a/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs +++ b/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs @@ -85,6 +85,6 @@ public static IWebHostBuilder ConfigureWebHostBuilder( logger.LogInformation("Kestrel listening to unix socket {SocketPath}", socketPath); } }) - .UseStartup(_ => new Startup(appHost)); + .UseStartup(_ => new Startup(appHost, startupConfig)); } } diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index e9fb3e4c276..2ff3774036e 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -40,15 +40,18 @@ public class Startup { private readonly CoreAppHost _serverApplicationHost; private readonly IServerConfigurationManager _serverConfigurationManager; + private readonly IConfiguration _startupConfig; /// /// Initializes a new instance of the class. /// /// The server application host. - public Startup(CoreAppHost appHost) + /// The server startupConfig. + public Startup(CoreAppHost appHost, IConfiguration startupConfig) { _serverApplicationHost = appHost; _serverConfigurationManager = appHost.ConfigurationManager; + _startupConfig = startupConfig; } /// @@ -67,7 +70,7 @@ public void ConfigureServices(IServiceCollection services) // TODO remove once this is fixed upstream https://github.com/dotnet/aspnetcore/issues/34371 services.AddSingleton, SymlinkFollowingPhysicalFileResultExecutor>(); services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration()); - services.AddJellyfinDbContext(); + services.AddJellyfinDbContext(_startupConfig.GetSqliteSecondLevelCacheDisabled()); services.AddJellyfinApiSwagger(); // configure custom legacy authentication diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs index 6c58064ce93..d6517e6264e 100644 --- a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -64,6 +64,11 @@ public static class ConfigurationExtensions /// public const string SqliteCacheSizeKey = "sqlite:cacheSize"; + /// + /// Disable second level cache of sqlite. + /// + public const string SqliteDisableSecondLevelCacheKey = "sqlite:disableSecondLevelCache"; + /// /// Gets a value indicating whether the application should host static web content from the . /// @@ -128,5 +133,26 @@ public static bool UseUnixSocket(this IConfiguration configuration) /// The sqlite cache size. public static int? GetSqliteCacheSize(this IConfiguration configuration) => configuration.GetValue(SqliteCacheSizeKey); + + /// + /// Gets whether second level cache disabled from the . + /// + /// The configuration to read the setting from. + /// Whether second level cache disabled. + public static bool GetSqliteSecondLevelCacheDisabled(this IConfiguration configuration) + { + var disableSecondLevelCacheConfig = configuration.GetValue(SqliteDisableSecondLevelCacheKey); + var disableSecondLevelCache = false; + if (disableSecondLevelCacheConfig is not null) + { + disableSecondLevelCache = disableSecondLevelCacheConfig.ToUpperInvariant() switch + { + "FALSE" or "NO" or "0" => false, + _ => true + }; + } + + return disableSecondLevelCache; + } } }