Procházet zdrojové kódy

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 <gnattuoc@me.com>
gnattu před 1 rokem
rodič
revize
b9c0fc69e8

+ 2 - 1
Emby.Server.Implementations/ConfigurationOptions.cs

@@ -19,7 +19,8 @@ namespace Emby.Server.Implementations
             { FfmpegAnalyzeDurationKey, "200M" },
             { PlaylistsAllowDuplicatesKey, bool.FalseString },
             { BindToUnixSocketKey, bool.FalseString },
-            { SqliteCacheSizeKey, "20000" }
+            { SqliteCacheSizeKey, "20000" },
+            { SqliteDisableSecondLevelCacheKey, bool.FalseString }
         };
     }
 }

+ 16 - 9
Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs

@@ -16,21 +16,28 @@ public static class ServiceCollectionExtensions
     /// Adds the <see cref="IDbContextFactory{TContext}"/> interface to the service collection with second level caching enabled.
     /// </summary>
     /// <param name="serviceCollection">An instance of the <see cref="IServiceCollection"/> interface.</param>
+    /// <param name="disableSecondLevelCache">Whether second level cache disabled..</param>
     /// <returns>The updated service collection.</returns>
-    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<JellyfinDbContext>((serviceProvider, opt) =>
         {
             var applicationPaths = serviceProvider.GetRequiredService<IApplicationPaths>();
-            opt.UseSqlite($"Filename={Path.Combine(applicationPaths.DataPath, "jellyfin.db")}")
-                .AddInterceptors(serviceProvider.GetRequiredService<SecondLevelCacheInterceptor>());
+            var dbOpt = opt.UseSqlite($"Filename={Path.Combine(applicationPaths.DataPath, "jellyfin.db")}");
+            if (!disableSecondLevelCache)
+            {
+                dbOpt.AddInterceptors(serviceProvider.GetRequiredService<SecondLevelCacheInterceptor>());
+            }
         });
 
         return serviceCollection;

+ 1 - 1
Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs

@@ -85,6 +85,6 @@ public static class WebHostBuilderExtensions
                     logger.LogInformation("Kestrel listening to unix socket {SocketPath}", socketPath);
                 }
             })
-            .UseStartup(_ => new Startup(appHost));
+            .UseStartup(_ => new Startup(appHost, startupConfig));
     }
 }

+ 5 - 2
Jellyfin.Server/Startup.cs

@@ -40,15 +40,18 @@ namespace Jellyfin.Server
     {
         private readonly CoreAppHost _serverApplicationHost;
         private readonly IServerConfigurationManager _serverConfigurationManager;
+        private readonly IConfiguration _startupConfig;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="Startup" /> class.
         /// </summary>
         /// <param name="appHost">The server application host.</param>
-        public Startup(CoreAppHost appHost)
+        /// <param name="startupConfig">The server startupConfig.</param>
+        public Startup(CoreAppHost appHost, IConfiguration startupConfig)
         {
             _serverApplicationHost = appHost;
             _serverConfigurationManager = appHost.ConfigurationManager;
+            _startupConfig = startupConfig;
         }
 
         /// <summary>
@@ -67,7 +70,7 @@ namespace Jellyfin.Server
             // TODO remove once this is fixed upstream https://github.com/dotnet/aspnetcore/issues/34371
             services.AddSingleton<IActionResultExecutor<PhysicalFileResult>, SymlinkFollowingPhysicalFileResultExecutor>();
             services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration());
-            services.AddJellyfinDbContext();
+            services.AddJellyfinDbContext(_startupConfig.GetSqliteSecondLevelCacheDisabled());
             services.AddJellyfinApiSwagger();
 
             // configure custom legacy authentication

+ 26 - 0
MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs

@@ -64,6 +64,11 @@ namespace MediaBrowser.Controller.Extensions
         /// </summary>
         public const string SqliteCacheSizeKey = "sqlite:cacheSize";
 
+        /// <summary>
+        /// Disable second level cache of sqlite.
+        /// </summary>
+        public const string SqliteDisableSecondLevelCacheKey = "sqlite:disableSecondLevelCache";
+
         /// <summary>
         /// Gets a value indicating whether the application should host static web content from the <see cref="IConfiguration"/>.
         /// </summary>
@@ -128,5 +133,26 @@ namespace MediaBrowser.Controller.Extensions
         /// <returns>The sqlite cache size.</returns>
         public static int? GetSqliteCacheSize(this IConfiguration configuration)
             => configuration.GetValue<int?>(SqliteCacheSizeKey);
+
+        /// <summary>
+        /// Gets whether second level cache disabled from the <see cref="IConfiguration" />.
+        /// </summary>
+        /// <param name="configuration">The configuration to read the setting from.</param>
+        /// <returns>Whether second level cache disabled.</returns>
+        public static bool GetSqliteSecondLevelCacheDisabled(this IConfiguration configuration)
+        {
+            var disableSecondLevelCacheConfig = configuration.GetValue<string?>(SqliteDisableSecondLevelCacheKey);
+            var disableSecondLevelCache = false;
+            if (disableSecondLevelCacheConfig is not null)
+            {
+                disableSecondLevelCache = disableSecondLevelCacheConfig.ToUpperInvariant() switch
+                {
+                    "FALSE" or "NO" or "0" => false,
+                    _ => true
+                };
+            }
+
+            return disableSecondLevelCache;
+        }
     }
 }