Only checkpoint the database on shutdown instead of vacuuming and analyze

This commit is contained in:
Shadowghost committed 2026-09-08 14:08:33 +02:00
1 parent 04a93b059c
commit 0df068e36c
3 files changed
+17 -8

No files matched your search

+1 -2
View File
@@ -271,9 +271,8 @@ namespace Jellyfin.Server
// Don't throw additional exception if startup failed.
if (appHost.ServiceProvider is not null)
{
_logger.LogInformation("Optimizing the database... This might take a while");
_logger.LogInformation("Preparing the database for shutdown...");
// Deliberately untimed: a truncated optimization leaves the statistics incomplete.
var databaseProvider = appHost.ServiceProvider.GetRequiredService<IJellyfinDatabaseProvider>();
await databaseProvider.RunShutdownTask(CancellationToken.None).ConfigureAwait(false);
}
@@ -45,8 +45,10 @@ public interface IJellyfinDatabaseProvider
Task RunScheduledOptimisation(CancellationToken cancellationToken);
/// <summary>
/// If supported this should perform any actions that are required on stopping the jellyfin server, including the
/// same maintenance as <see cref="RunScheduledOptimisation(CancellationToken)"/>.
/// If supported this should perform any actions that are required on stopping the jellyfin server. This runs
/// against a deadline imposed by the service manager, so unlike
/// <see cref="RunScheduledOptimisation(CancellationToken)"/> it should only do work whose cost does not grow with
/// the size of the database.
/// </summary>
/// <param name="cancellationToken">The token that will be used to abort the operation.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
@@ -130,15 +130,23 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
/// <inheritdoc/>
public async Task RunShutdownTask(CancellationToken cancellationToken)
{
// Run before disposing the application
// Run before disposing the application. Only a checkpoint: stopping is on a deadline.
try
{
await OptimizeAsync(cancellationToken).ConfigureAwait(false);
if (DbContextFactory is not null)
{
var context = await DbContextFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
await using (context.ConfigureAwait(false))
{
await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(TRUNCATE)", cancellationToken).ConfigureAwait(false);
}
}
}
catch (Exception ex)
{
// A missed optimization only costs performance, so never fail the shutdown over this.
_logger.LogError(ex, "Error while optimizing jellyfin.db");
// A missed checkpoint only leaves a write-ahead log for the next start to replay, so never fail the
// shutdown over this.
_logger.LogError(ex, "Error while checkpointing jellyfin.db");
}
SqliteConnection.ClearAllPools();