diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 29967c6df5..6687be2e91 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -575,7 +575,11 @@ namespace Emby.Server.Implementations /// A task representing the service initialization operation. public async Task InitializeServices() { - var jellyfinDb = await Resolve>().CreateDbContextAsync().ConfigureAwait(false); + var factory = Resolve>(); + var provider = Resolve(); + provider.DbContextFactory = factory; + + var jellyfinDb = await factory.CreateDbContextAsync().ConfigureAwait(false); await using (jellyfinDb.ConfigureAwait(false)) { if ((await jellyfinDb.Database.GetPendingMigrationsAsync().ConfigureAwait(false)).Any()) diff --git a/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs b/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs index 64dd03ca4e..72a6f819e0 100644 --- a/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs +++ b/Jellyfin.Database/Jellyfin.Database.Implementations/IJellyfinDatabaseProvider.cs @@ -10,6 +10,11 @@ namespace Jellyfin.Server.Implementations; /// public interface IJellyfinDatabaseProvider : IAsyncDisposable { + /// + /// Gets or Sets the Database Factory when initialisaition is done. + /// + IDbContextFactory? DbContextFactory { get; set; } + /// /// Initialises jellyfins EFCore database access. /// diff --git a/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Jellyfin.Database.Providers.SqLite.csproj b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Jellyfin.Database.Providers.SqLite.csproj index 0f04275392..e77c944f95 100644 --- a/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Jellyfin.Database.Providers.SqLite.csproj +++ b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Jellyfin.Database.Providers.SqLite.csproj @@ -45,7 +45,7 @@ - + diff --git a/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Migrations/DesignTimeJellyfinDbFactory.cs b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Migrations/DesignTimeJellyfinDbFactory.cs index 942af284a9..ff0ce3403c 100644 --- a/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Migrations/DesignTimeJellyfinDbFactory.cs +++ b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/Migrations/DesignTimeJellyfinDbFactory.cs @@ -19,7 +19,7 @@ namespace Jellyfin.Server.Implementations.Migrations return new JellyfinDbContext( optionsBuilder.Options, NullLogger.Instance, - new SqliteDatabaseProvider(null!, null!, NullLogger.Instance)); + new SqliteDatabaseProvider(null!, NullLogger.Instance)); } } } diff --git a/Jellyfin.Server.Implementations/ModelBuilderExtensions.cs b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/ModelBuilderExtensions.cs similarity index 100% rename from Jellyfin.Server.Implementations/ModelBuilderExtensions.cs rename to Jellyfin.Database/Jellyfin.Database.Providers.SqLite/ModelBuilderExtensions.cs diff --git a/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/SqliteDatabaseProvider.cs b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/SqliteDatabaseProvider.cs index 8bc025a0bf..8ef5b6af5e 100644 --- a/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/SqliteDatabaseProvider.cs +++ b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/SqliteDatabaseProvider.cs @@ -10,6 +10,7 @@ namespace Jellyfin.Database.Providers.SqLite; /// /// Configures jellyfin to use an SqLite database. /// +[JellyfinDatabaseProviderKey("Jellyfin-SqLite")] public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider { private readonly IApplicationPaths _applicationPaths; @@ -18,17 +19,16 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider /// /// Initializes a new instance of the class. /// - /// The Db context to interact with the database. /// Service to construct the fallback when the old data path configuration is used. /// A logger. - public SqliteDatabaseProvider(IDbContextFactory dbContextFactory, IApplicationPaths applicationPaths, ILogger logger) + public SqliteDatabaseProvider(IApplicationPaths applicationPaths, ILogger logger) { - DbContextFactory = dbContextFactory; _applicationPaths = applicationPaths; _logger = logger; } - private IDbContextFactory DbContextFactory { get; } + /// + public IDbContextFactory? DbContextFactory { get; set; } /// public void Initialise(DbContextOptionsBuilder options) @@ -41,7 +41,7 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider /// public async Task RunScheduledOptimisation(CancellationToken cancellationToken) { - var context = await DbContextFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); await using (context.ConfigureAwait(false)) { if (context.Database.IsSqlite()) @@ -67,7 +67,7 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider public async ValueTask DisposeAsync() { // Run before disposing the application - var context = await DbContextFactory.CreateDbContextAsync().ConfigureAwait(false); + var context = await DbContextFactory!.CreateDbContextAsync().ConfigureAwait(false); await using (context.ConfigureAwait(false)) { await context.Database.ExecuteSqlRawAsync("PRAGMA optimize").ConfigureAwait(false); diff --git a/Jellyfin.Server.Implementations/ValueConverters/DateTimeKindValueConverter.cs b/Jellyfin.Database/Jellyfin.Database.Providers.SqLite/ValueConverters/DateTimeKindValueConverter.cs similarity index 100% rename from Jellyfin.Server.Implementations/ValueConverters/DateTimeKindValueConverter.cs rename to Jellyfin.Database/Jellyfin.Database.Providers.SqLite/ValueConverters/DateTimeKindValueConverter.cs diff --git a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs index e48f4ce106..1b0dbbe108 100644 --- a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using Jellyfin.Database.Providers.SqLite; using Jellyfin.Server.Implementations.DatabaseConfiguration; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; @@ -17,14 +18,15 @@ namespace Jellyfin.Server.Implementations.Extensions; /// public static class ServiceCollectionExtensions { + private static IEnumerable DatabaseProviderTypes() + { + yield return typeof(SqliteDatabaseProvider); + } + private static IDictionary GetSupportedDbProviders() { var items = new Dictionary(); - foreach (var providerType in AppDomain - .CurrentDomain - .GetAssemblies() - .SelectMany(f => f.GetTypes()) - .Where(e => e.IsClass && typeof(IJellyfinDatabaseProvider).IsAssignableFrom(e))) + foreach (var providerType in DatabaseProviderTypes()) { var keyAttribute = providerType.GetCustomAttribute(); if (keyAttribute is null || string.IsNullOrWhiteSpace(keyAttribute.DatabaseProviderKey)) @@ -51,15 +53,16 @@ public static class ServiceCollectionExtensions var providers = GetSupportedDbProviders(); JellyfinDbProviderFactory? providerFactory = null; - if (efCoreConfiguration is null) + if (efCoreConfiguration?.DatabaseType is null) { // when nothing is setup via new Database configuration, fallback to SqLite with default settings. efCoreConfiguration = new DatabaseConfigurationOptions() { - DatabaseType = "SqLite", + DatabaseType = "Jellyfin-SqLite", }; } - else if (!providers.TryGetValue(efCoreConfiguration.DatabaseType, out providerFactory!)) + + if (!providers.TryGetValue(efCoreConfiguration.DatabaseType, out providerFactory!)) { throw new InvalidOperationException($"Jellyfin cannot find the database provider of type '{efCoreConfiguration.DatabaseType}'. Supported types are {string.Join(", ", providers.Keys)}"); } diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index cf3c792764..b566b3489b 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -36,6 +36,7 @@ + diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index d5b6e93b8e..9788119a54 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,6 +11,7 @@ using Jellyfin.Server.Implementations; using Jellyfin.Server.Implementations.Activity; using Jellyfin.Server.Implementations.Devices; using Jellyfin.Server.Implementations.Events; +using Jellyfin.Server.Implementations.Extensions; using Jellyfin.Server.Implementations.Security; using Jellyfin.Server.Implementations.Trickplay; using Jellyfin.Server.Implementations.Users; @@ -116,9 +117,12 @@ namespace Jellyfin.Server // Jellyfin.Server yield return typeof(CoreAppHost).Assembly; - // Jellyfin.Server.Implementations + // Jellyfin.Database.Implementations yield return typeof(JellyfinDbContext).Assembly; + // Jellyfin.Server.Implementations + yield return typeof(ServiceCollectionExtensions).Assembly; + // Jellyfin.LiveTv yield return typeof(LiveTvManager).Assembly; }