ServiceCollectionExtensions.cs 4.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using Jellyfin.Database.Providers.SqLite;
  5. using Jellyfin.Server.Implementations.DatabaseConfiguration;
  6. using MediaBrowser.Common.Configuration;
  7. using MediaBrowser.Controller.Configuration;
  8. using Microsoft.EntityFrameworkCore;
  9. using Microsoft.Extensions.Configuration;
  10. using Microsoft.Extensions.DependencyInjection;
  11. using JellyfinDbProviderFactory = System.Func<System.IServiceProvider, Jellyfin.Server.Implementations.IJellyfinDatabaseProvider>;
  12. namespace Jellyfin.Server.Implementations.Extensions;
  13. /// <summary>
  14. /// Extensions for the <see cref="IServiceCollection"/> interface.
  15. /// </summary>
  16. public static class ServiceCollectionExtensions
  17. {
  18. private static IEnumerable<Type> DatabaseProviderTypes()
  19. {
  20. yield return typeof(SqliteDatabaseProvider);
  21. }
  22. private static IDictionary<string, JellyfinDbProviderFactory> GetSupportedDbProviders()
  23. {
  24. var items = new Dictionary<string, JellyfinDbProviderFactory>(StringComparer.InvariantCultureIgnoreCase);
  25. foreach (var providerType in DatabaseProviderTypes())
  26. {
  27. var keyAttribute = providerType.GetCustomAttribute<JellyfinDatabaseProviderKeyAttribute>();
  28. if (keyAttribute is null || string.IsNullOrWhiteSpace(keyAttribute.DatabaseProviderKey))
  29. {
  30. continue;
  31. }
  32. var provider = providerType;
  33. items[keyAttribute.DatabaseProviderKey] = (services) => (IJellyfinDatabaseProvider)ActivatorUtilities.CreateInstance(services, providerType);
  34. }
  35. return items;
  36. }
  37. /// <summary>
  38. /// Adds the <see cref="IDbContextFactory{TContext}"/> interface to the service collection with second level caching enabled.
  39. /// </summary>
  40. /// <param name="serviceCollection">An instance of the <see cref="IServiceCollection"/> interface.</param>
  41. /// <param name="configurationManager">The server configuration manager.</param>
  42. /// <param name="configuration">The startup Configuration.</param>
  43. /// <returns>The updated service collection.</returns>
  44. public static IServiceCollection AddJellyfinDbContext(
  45. this IServiceCollection serviceCollection,
  46. IServerConfigurationManager configurationManager,
  47. IConfiguration configuration)
  48. {
  49. var efCoreConfiguration = configurationManager.GetConfiguration<DatabaseConfigurationOptions>("database");
  50. var providers = GetSupportedDbProviders();
  51. JellyfinDbProviderFactory? providerFactory = null;
  52. if (efCoreConfiguration?.DatabaseType is null)
  53. {
  54. var cmdMigrationArgument = configuration.GetValue<string>("migration-provider");
  55. if (!string.IsNullOrWhiteSpace(cmdMigrationArgument))
  56. {
  57. efCoreConfiguration = new DatabaseConfigurationOptions()
  58. {
  59. DatabaseType = cmdMigrationArgument,
  60. };
  61. }
  62. else
  63. {
  64. // when nothing is setup via new Database configuration, fallback to SQLite with default settings.
  65. efCoreConfiguration = new DatabaseConfigurationOptions()
  66. {
  67. DatabaseType = "Jellyfin-SQLite",
  68. };
  69. configurationManager.SaveConfiguration("database", efCoreConfiguration);
  70. }
  71. }
  72. if (!providers.TryGetValue(efCoreConfiguration.DatabaseType.ToUpperInvariant(), out providerFactory!))
  73. {
  74. throw new InvalidOperationException($"Jellyfin cannot find the database provider of type '{efCoreConfiguration.DatabaseType}'. Supported types are {string.Join(", ", providers.Keys)}");
  75. }
  76. serviceCollection.AddSingleton<IJellyfinDatabaseProvider>(providerFactory!);
  77. serviceCollection.AddPooledDbContextFactory<JellyfinDbContext>((serviceProvider, opt) =>
  78. {
  79. var provider = serviceProvider.GetRequiredService<IJellyfinDatabaseProvider>();
  80. provider.Initialise(opt);
  81. });
  82. return serviceCollection;
  83. }
  84. }