|
@@ -1,5 +1,7 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
using System.Reflection;
|
|
|
using Jellyfin.Database.Implementations;
|
|
|
using Jellyfin.Database.Implementations.DbConfiguration;
|
|
@@ -42,6 +44,28 @@ public static class ServiceCollectionExtensions
|
|
|
return items;
|
|
|
}
|
|
|
|
|
|
+ private static JellyfinDbProviderFactory? LoadDatabasePlugin(CustomDatabaseOptions customProviderOptions, IApplicationPaths applicationPaths)
|
|
|
+ {
|
|
|
+ var plugin = Directory.EnumerateDirectories(applicationPaths.PluginsPath)
|
|
|
+ .Where(e => Path.GetFileName(e)!.StartsWith(customProviderOptions.PluginName, StringComparison.OrdinalIgnoreCase))
|
|
|
+ .Order()
|
|
|
+ .FirstOrDefault()
|
|
|
+ ?? throw new InvalidOperationException($"The requested custom database plugin with the name '{customProviderOptions.PluginName}' could not been found in '{applicationPaths.PluginsPath}'");
|
|
|
+
|
|
|
+ var dbProviderAssembly = Path.Combine(plugin, Path.ChangeExtension(customProviderOptions.PluginAssembly, "dll"));
|
|
|
+ if (!File.Exists(dbProviderAssembly))
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException($"Could not find the requested assembly at '{dbProviderAssembly}'");
|
|
|
+ }
|
|
|
+
|
|
|
+ // we have to load the assembly without proxy to ensure maximum performance for this.
|
|
|
+ var assembly = Assembly.LoadFrom(dbProviderAssembly);
|
|
|
+ var dbProviderType = assembly.GetExportedTypes().FirstOrDefault(f => f.IsAssignableTo(typeof(IJellyfinDatabaseProvider)))
|
|
|
+ ?? throw new InvalidOperationException($"Could not find any type implementing the '{nameof(IJellyfinDatabaseProvider)}' interface.");
|
|
|
+
|
|
|
+ return (services) => (IJellyfinDatabaseProvider)ActivatorUtilities.CreateInstance(services, dbProviderType);
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Adds the <see cref="IDbContextFactory{TContext}"/> interface to the service collection with second level caching enabled.
|
|
|
/// </summary>
|
|
@@ -55,7 +79,6 @@ public static class ServiceCollectionExtensions
|
|
|
IConfiguration configuration)
|
|
|
{
|
|
|
var efCoreConfiguration = configurationManager.GetConfiguration<DatabaseConfigurationOptions>("database");
|
|
|
- var providers = GetSupportedDbProviders();
|
|
|
JellyfinDbProviderFactory? providerFactory = null;
|
|
|
|
|
|
if (efCoreConfiguration?.DatabaseType is null)
|
|
@@ -80,9 +103,22 @@ public static class ServiceCollectionExtensions
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!providers.TryGetValue(efCoreConfiguration.DatabaseType.ToUpperInvariant(), out providerFactory!))
|
|
|
+ if (efCoreConfiguration.DatabaseType.Equals("PLUGIN_PROVIDER", StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
- throw new InvalidOperationException($"Jellyfin cannot find the database provider of type '{efCoreConfiguration.DatabaseType}'. Supported types are {string.Join(", ", providers.Keys)}");
|
|
|
+ if (efCoreConfiguration.CustomProviderOptions is null)
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException("The custom database provider must declare the custom provider options to work");
|
|
|
+ }
|
|
|
+
|
|
|
+ providerFactory = LoadDatabasePlugin(efCoreConfiguration.CustomProviderOptions, configurationManager.ApplicationPaths);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var providers = GetSupportedDbProviders();
|
|
|
+ if (!providers.TryGetValue(efCoreConfiguration.DatabaseType.ToUpperInvariant(), out providerFactory!))
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException($"Jellyfin cannot find the database provider of type '{efCoreConfiguration.DatabaseType}'. Supported types are {string.Join(", ", providers.Keys)}");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
serviceCollection.AddSingleton<IJellyfinDatabaseProvider>(providerFactory!);
|