Skip to content

Commit

Permalink
Add Env Var to disable second level cache
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
gnattu committed May 24, 2024
1 parent 06a5ddd commit b9c0fc6
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 13 deletions.
3 changes: 2 additions & 1 deletion Emby.Server.Implementations/ConfigurationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public static class ConfigurationOptions
{ FfmpegAnalyzeDurationKey, "200M" },
{ PlaylistsAllowDuplicatesKey, bool.FalseString },
{ BindToUnixSocketKey, bool.FalseString },
{ SqliteCacheSizeKey, "20000" }
{ SqliteCacheSizeKey, "20000" },
{ SqliteDisableSecondLevelCacheKey, bool.FalseString }
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
7 changes: 5 additions & 2 deletions Jellyfin.Server/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,18 @@ public class Startup
{
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>
Expand All @@ -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<IActionResultExecutor<PhysicalFileResult>, SymlinkFollowingPhysicalFileResultExecutor>();
services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration());
services.AddJellyfinDbContext();
services.AddJellyfinDbContext(_startupConfig.GetSqliteSecondLevelCacheDisabled());
services.AddJellyfinApiSwagger();

// configure custom legacy authentication
Expand Down
26 changes: 26 additions & 0 deletions MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ public static class ConfigurationExtensions
/// </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>
Expand Down Expand Up @@ -128,5 +133,26 @@ public static bool UseUnixSocket(this IConfiguration configuration)
/// <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;
}
}
}

0 comments on commit b9c0fc6

Please sign in to comment.