From e6e7c4988829e66535b9ad708d918c70d48afd35 Mon Sep 17 00:00:00 2001 From: Wendell Jones Date: Tue, 10 Mar 2026 13:47:50 -0400 Subject: [PATCH] Fix EnsureDatabaseExistsAsync to respect ConnectionString from configuration - was still using localhost default --- .../new-dotnet-version_02bc64/scenario.json | 2 +- Jellyfin.Server/Jellyfin.Server.csproj.user | 2 +- .../PostgresDatabaseProvider.cs | 95 ++++++++++++++----- 3 files changed, 75 insertions(+), 24 deletions(-) diff --git a/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json b/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json index 4c5cad27..197127c6 100644 --- a/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json +++ b/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json @@ -3,7 +3,7 @@ "operationId": "02bc6448-a69d-4ff4-a0ec-0db07ec3a09a", "description": "Upgrade solution or project to new version of .NET", "startTime": "2026-03-05T22:18:32.3921759Z", - "lastUpdateTime": "2026-03-10T17:00:26.858894Z", + "lastUpdateTime": "2026-03-10T17:43:12.8279563Z", "stage": "Execution", "properties": {}, "folderPath": "" diff --git a/Jellyfin.Server/Jellyfin.Server.csproj.user b/Jellyfin.Server/Jellyfin.Server.csproj.user index 55f2b8df..bd1700e6 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj.user +++ b/Jellyfin.Server/Jellyfin.Server.csproj.user @@ -1,6 +1,6 @@  - D:\Projects\pgsql-jellyfin\Jellyfin.Server\Properties\PublishProfiles\SelfContained-Linux-x64.pubxml + D:\Projects\pgsql-jellyfin\Jellyfin.Server\Properties\PublishProfiles\SelfContained-Win-x64.pubxml \ No newline at end of file diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs index 8b3427ec..f33acbb1 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs @@ -297,30 +297,81 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider /// A task representing the asynchronous operation. public async Task EnsureDatabaseExistsAsync(DatabaseConfigurationOptions databaseConfiguration, CancellationToken cancellationToken = default) { - static T? GetOption(ICollection? options, string key, Func converter, Func? defaultValue = null) - { - if (options is null) - { - return defaultValue is not null ? defaultValue() : default; - } - - var value = options.FirstOrDefault(e => e.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - if (value is null) - { - return defaultValue is not null ? defaultValue() : default; - } - - return converter(value.Value); - } - var customOptions = databaseConfiguration.CustomProviderOptions?.Options; - var host = GetOption(customOptions, "host", e => e, () => "localhost")!; - var port = GetOption(customOptions, "port", int.Parse, () => 5432); - var database = GetOption(customOptions, "database", e => e, () => "jellyfin")!; - var username = GetOption(customOptions, "username", e => e, () => "jellyfin")!; - var password = GetOption(customOptions, "password", e => e, () => string.Empty)!; - var timeout = GetOption(customOptions, "connection-timeout", int.Parse, () => 15); + // Start with connection string if provided, then override with individual options + NpgsqlConnectionStringBuilder connectionBuilder; + + if (!string.IsNullOrWhiteSpace(databaseConfiguration.CustomProviderOptions?.ConnectionString)) + { + // Parse the existing connection string to get all parameters + connectionBuilder = new NpgsqlConnectionStringBuilder(databaseConfiguration.CustomProviderOptions.ConnectionString); + logger.LogDebug("EnsureDatabaseExists: Using ConnectionString from configuration as base"); + } + else + { + // Start with defaults + connectionBuilder = new NpgsqlConnectionStringBuilder + { + Host = "localhost", + Port = 5432, + Database = "jellyfin", + Username = "jellyfin", + Password = string.Empty, + Timeout = 15 + }; + logger.LogDebug("EnsureDatabaseExists: Using default connection parameters"); + } + + // Override with individual options if provided (these take precedence over ConnectionString) + if (customOptions is not null && customOptions.Count > 0) + { + var hostOpt = customOptions.FirstOrDefault(e => e.Key.Equals("host", StringComparison.OrdinalIgnoreCase)); + if (hostOpt is not null) + { + connectionBuilder.Host = hostOpt.Value; + } + + var portOpt = customOptions.FirstOrDefault(e => e.Key.Equals("port", StringComparison.OrdinalIgnoreCase)); + if (portOpt is not null && int.TryParse(portOpt.Value, out var portValue)) + { + connectionBuilder.Port = portValue; + } + + var databaseOpt = customOptions.FirstOrDefault(e => e.Key.Equals("database", StringComparison.OrdinalIgnoreCase)); + if (databaseOpt is not null) + { + connectionBuilder.Database = databaseOpt.Value; + } + + var usernameOpt = customOptions.FirstOrDefault(e => e.Key.Equals("username", StringComparison.OrdinalIgnoreCase)); + if (usernameOpt is not null) + { + connectionBuilder.Username = usernameOpt.Value; + } + + var passwordOpt = customOptions.FirstOrDefault(e => e.Key.Equals("password", StringComparison.OrdinalIgnoreCase)); + if (passwordOpt is not null) + { + connectionBuilder.Password = passwordOpt.Value; + } + + var timeoutOpt = customOptions.FirstOrDefault(e => e.Key.Equals("connection-timeout", StringComparison.OrdinalIgnoreCase)); + if (timeoutOpt is not null && int.TryParse(timeoutOpt.Value, out var timeoutValue)) + { + connectionBuilder.Timeout = timeoutValue; + } + + logger.LogDebug("EnsureDatabaseExists: Applied individual option overrides"); + } + + // Extract final values from builder (ensure non-null for parameters) + var host = connectionBuilder.Host ?? "localhost"; + var port = connectionBuilder.Port; + var database = connectionBuilder.Database ?? "jellyfin"; + var username = connectionBuilder.Username ?? "jellyfin"; + var password = connectionBuilder.Password ?? string.Empty; + var timeout = connectionBuilder.Timeout; // Connect to 'postgres' maintenance database to check if target database exists var maintenanceConnectionBuilder = new NpgsqlConnectionStringBuilder