Implement PostgreSqlDatabaseProvider methods and DI registration (#6)
* Initial plan * feat: implement PostgreSqlDatabaseProvider all methods + DI registration Co-authored-by: ZoltyMat <177592743+ZoltyMat@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ZoltyMat <177592743+ZoltyMat@users.noreply.github.com>
This commit is contained in:
@@ -6,6 +6,7 @@ using System.Reflection;
|
||||
using Jellyfin.Database.Implementations;
|
||||
using Jellyfin.Database.Implementations.DbConfiguration;
|
||||
using Jellyfin.Database.Implementations.Locking;
|
||||
using Jellyfin.Database.Providers.PostgreSQL;
|
||||
using Jellyfin.Database.Providers.Sqlite;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
@@ -24,6 +25,7 @@ public static class ServiceCollectionExtensions
|
||||
private static IEnumerable<Type> DatabaseProviderTypes()
|
||||
{
|
||||
yield return typeof(SqliteDatabaseProvider);
|
||||
yield return typeof(PostgreSqlDatabaseProvider);
|
||||
}
|
||||
|
||||
private static IDictionary<string, JellyfinDbProviderFactory> GetSupportedDbProviders()
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
|
||||
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
||||
<ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj" />
|
||||
<ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Providers.PostgreSQL\Jellyfin.Database.Providers.PostgreSQL.csproj" />
|
||||
<ProjectReference Include="..\src\Jellyfin.Database\Jellyfin.Database.Providers.Sqlite\Jellyfin.Database.Providers.Sqlite.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+42
-8
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Database.Implementations;
|
||||
@@ -14,13 +15,28 @@ namespace Jellyfin.Database.Providers.PostgreSQL;
|
||||
[JellyfinDatabaseProviderKey("Jellyfin-PostgreSQL")]
|
||||
public sealed class PostgreSqlDatabaseProvider : IJellyfinDatabaseProvider
|
||||
{
|
||||
private const string BackupNotSupportedMessage =
|
||||
"Automated migration backups are not supported for PostgreSQL. Use the jellyfin-pg-backup CronJob for nightly S3 backups.";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IDbContextFactory<JellyfinDbContext>? DbContextFactory { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Initialise(DbContextOptionsBuilder options, DatabaseConfigurationOptions databaseConfiguration)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var connectionString =
|
||||
Environment.GetEnvironmentVariable("POSTGRES_CONNECTION_STRING")
|
||||
?? databaseConfiguration.CustomProviderOptions?.Options
|
||||
?.FirstOrDefault(o => o.Key.Equals("ConnectionString", StringComparison.OrdinalIgnoreCase))
|
||||
?.Value
|
||||
?? databaseConfiguration.CustomProviderOptions?.ConnectionString
|
||||
?? throw new InvalidOperationException(
|
||||
"No PostgreSQL connection string found. Set the POSTGRES_CONNECTION_STRING environment variable, " +
|
||||
"or provide it via CustomProviderOptions.Options[\"ConnectionString\"] or CustomProviderOptions.ConnectionString.");
|
||||
|
||||
options.UseNpgsql(
|
||||
connectionString,
|
||||
o => o.MigrationsAssembly(GetType().Assembly.FullName));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -34,9 +50,13 @@ public sealed class PostgreSqlDatabaseProvider : IJellyfinDatabaseProvider
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task RunScheduledOptimisation(CancellationToken cancellationToken)
|
||||
public async Task RunScheduledOptimisation(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
|
||||
await using (context.ConfigureAwait(false))
|
||||
{
|
||||
await context.Database.ExecuteSqlRawAsync("ANALYZE", cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -48,24 +68,38 @@ public sealed class PostgreSqlDatabaseProvider : IJellyfinDatabaseProvider
|
||||
/// <inheritdoc/>
|
||||
public Task<string> MigrationBackupFast(CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new NotSupportedException(BackupNotSupportedMessage);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task RestoreBackupFast(string key, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new NotSupportedException(BackupNotSupportedMessage);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task DeleteBackup(string key)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new NotSupportedException(BackupNotSupportedMessage);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task PurgeDatabase(JellyfinDbContext dbContext, IEnumerable<string>? tableNames)
|
||||
public async Task PurgeDatabase(JellyfinDbContext dbContext, IEnumerable<string>? tableNames)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
ArgumentNullException.ThrowIfNull(tableNames);
|
||||
|
||||
await dbContext.Database.ExecuteSqlRawAsync("SET session_replication_role = 'replica'").ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
foreach (var tableName in tableNames)
|
||||
{
|
||||
var truncateSql = "TRUNCATE TABLE \"" + tableName + "\" CASCADE";
|
||||
await dbContext.Database.ExecuteSqlRawAsync(truncateSql).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
await dbContext.Database.ExecuteSqlRawAsync("SET session_replication_role = 'origin'").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user