aboutsummaryrefslogtreecommitdiff
path: root/src/Jellyfin.Database
diff options
context:
space:
mode:
authorShadowghost <Ghost_of_Stone@web.de>2026-09-05 17:33:47 +0200
committerShadowghost <Ghost_of_Stone@web.de>2026-09-05 17:33:47 +0200
commit74ce774effac4d70728e231e6de7c1c5d82a2685 (patch)
tree949c4f2e05e7da7c16f7dd6c98dd2b95899ec2f6 /src/Jellyfin.Database
parent5465e0c69423506d6836f2a6b8aacfce8cb0501e (diff)
Revert to doing after migration and on shutdown
Diffstat (limited to 'src/Jellyfin.Database')
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs5
-rw-r--r--src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs45
2 files changed, 35 insertions, 15 deletions
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs
index a7b2aa493b..77abb45f2a 100644
--- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs
@@ -38,14 +38,15 @@ public interface IJellyfinDatabaseProvider
/// <summary>
/// If supported this should run any periodic maintaince tasks, reclaiming unused space and refreshing the query
- /// planner statistics. Also runs on startup once all migrations have been applied.
+ /// planner statistics. Also used after migrations have modified the database.
/// </summary>
/// <param name="cancellationToken">The token to abort the operation.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task RunScheduledOptimisation(CancellationToken cancellationToken);
/// <summary>
- /// If supported this should perform any actions that are required on stopping the jellyfin server.
+ /// If supported this should perform any actions that are required on stopping the jellyfin server, including the
+ /// same maintenance as <see cref="RunScheduledOptimisation(CancellationToken)"/>.
/// </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>
diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs
index 6103ecd992..f11cde7e48 100644
--- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs
+++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs
@@ -103,18 +103,9 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
}
/// <inheritdoc/>
- public async Task RunScheduledOptimisation(CancellationToken cancellationToken)
+ public Task RunScheduledOptimisation(CancellationToken cancellationToken)
{
- var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
- await using (context.ConfigureAwait(false))
- {
- await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(TRUNCATE)", cancellationToken).ConfigureAwait(false);
- await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false);
- await context.Database.ExecuteSqlRawAsync("PRAGMA analysis_limit=0", cancellationToken).ConfigureAwait(false);
- await context.Database.ExecuteSqlRawAsync("ANALYZE", cancellationToken).ConfigureAwait(false);
- await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(TRUNCATE)", cancellationToken).ConfigureAwait(false);
- _logger.LogInformation("jellyfin.db optimized successfully!");
- }
+ return OptimizeAsync(cancellationToken);
}
/// <inheritdoc/>
@@ -124,11 +115,39 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
}
/// <inheritdoc/>
- public Task RunShutdownTask(CancellationToken cancellationToken)
+ public async Task RunShutdownTask(CancellationToken cancellationToken)
{
// Run before disposing the application
+ try
+ {
+ await OptimizeAsync(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");
+ }
+
SqliteConnection.ClearAllPools();
- return Task.CompletedTask;
+ }
+
+ private async Task OptimizeAsync(CancellationToken cancellationToken)
+ {
+ if (DbContextFactory is null)
+ {
+ return;
+ }
+
+ var context = await DbContextFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
+ await using (context.ConfigureAwait(false))
+ {
+ await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(TRUNCATE)", cancellationToken).ConfigureAwait(false);
+ await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false);
+ await context.Database.ExecuteSqlRawAsync("PRAGMA analysis_limit=0", cancellationToken).ConfigureAwait(false);
+ await context.Database.ExecuteSqlRawAsync("ANALYZE", cancellationToken).ConfigureAwait(false);
+ await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(TRUNCATE)", cancellationToken).ConfigureAwait(false);
+ _logger.LogInformation("jellyfin.db optimized successfully!");
+ }
}
/// <inheritdoc/>