diff --git a/Kyoo.Common/Controllers/IPlugin.cs b/Kyoo.Common/Controllers/IPlugin.cs index c1652a4a..56797bb2 100644 --- a/Kyoo.Common/Controllers/IPlugin.cs +++ b/Kyoo.Common/Controllers/IPlugin.cs @@ -46,6 +46,12 @@ namespace Kyoo.Controllers /// put typeof(ILibraryManager). /// Type[] Requires { get; } + + /// + /// True if this plugin is needed to start Kyoo. If this is true and a dependency could not be met, app startup + /// will be canceled. If this is false, Kyoo's startup will continue without enabling this plugin. + /// + bool IsRequired { get; } /// /// A configure method that will be run on plugin's startup. diff --git a/Kyoo.Common/Models/Exceptions/MissingDependencyException.cs b/Kyoo.Common/Models/Exceptions/MissingDependencyException.cs index ec459faf..b2a4aa43 100644 --- a/Kyoo.Common/Models/Exceptions/MissingDependencyException.cs +++ b/Kyoo.Common/Models/Exceptions/MissingDependencyException.cs @@ -14,7 +14,7 @@ namespace Kyoo.Models.Exceptions /// The name of the plugin that can't be loaded. /// The name of the missing dependency. public MissingDependencyException(string plugin, string dependency) - : base($"No {dependency} are available in kyoo but the plugin {plugin} requires it.") + : base($"No {dependency} are available in Kyoo but the plugin {plugin} requires it.") {} } } \ No newline at end of file diff --git a/Kyoo.Postgresql/PostgresModule.cs b/Kyoo.Postgresql/PostgresModule.cs index c83df51d..e54f0a45 100644 --- a/Kyoo.Postgresql/PostgresModule.cs +++ b/Kyoo.Postgresql/PostgresModule.cs @@ -29,6 +29,9 @@ namespace Kyoo.Postgresql /// public Type[] Requires => Array.Empty(); + + /// + public bool IsRequired => true; /// diff --git a/Kyoo/Controllers/PluginManager.cs b/Kyoo/Controllers/PluginManager.cs index 8b9e9ca2..d2945b0c 100644 --- a/Kyoo/Controllers/PluginManager.cs +++ b/Kyoo/Controllers/PluginManager.cs @@ -88,14 +88,17 @@ namespace Kyoo.Controllers return assembly.GetTypes() .Where(x => typeof(IPlugin).IsAssignableFrom(x)) .Where(x => _plugins.All(y => y.GetType() != x)) - .Select(x => (IPlugin)_container.Resolve(x)); + .Select(x => (IPlugin)_container.Resolve(x)) + .ToArray(); } catch (Exception ex) { _logger.LogError(ex, "Could not load the plugin at {Path}", path); return Array.Empty(); } - }).ToArray(); + }).ToList(); + if (!_plugins.Any()) + newPlugins.Add(new CoreModule()); _plugins.AddRange(newPlugins); ICollection available = _plugins.SelectMany(x => x.Provides).ToArray(); @@ -103,8 +106,14 @@ namespace Kyoo.Controllers { Type missing = plugin.Requires.FirstOrDefault(x => available.All(y => !y.IsAssignableTo(x))); if (missing != null) - throw new MissingDependencyException(plugin.Name, missing.Name); - plugin.Configure(_container); + { + Exception error = new MissingDependencyException(plugin.Name, missing.Name); + _logger.LogCritical(error, "A plugin's dependency could not be met"); + if (plugin.IsRequired) + Environment.Exit(1); + } + else + plugin.Configure(_container); } if (!_plugins.Any()) diff --git a/Kyoo/CoreModule.cs b/Kyoo/CoreModule.cs index ac8b6fbe..5916f33f 100644 --- a/Kyoo/CoreModule.cs +++ b/Kyoo/CoreModule.cs @@ -48,6 +48,9 @@ namespace Kyoo typeof(DatabaseContext) }; + /// + public bool IsRequired => true; + /// public void Configure(IUnityContainer container) { diff --git a/Kyoo/Program.cs b/Kyoo/Program.cs index 1dda599d..e5053735 100644 --- a/Kyoo/Program.cs +++ b/Kyoo/Program.cs @@ -49,7 +49,14 @@ namespace Kyoo IWebHostBuilder host = CreateWebHostBuilder(args); if (debug != null) host = host.UseEnvironment(debug == true ? "Development" : "Production"); - await host.Build().RunAsync(); + try + { + await host.Build().RunAsync(); + } + catch (Exception ex) + { + new Logger(new LoggerFactory()).LogCritical(ex, "Unhandled exception"); + } } /// @@ -74,7 +81,7 @@ namespace Kyoo { UnityContainer container = new(); container.EnableDebugDiagnostic(); - + return new WebHostBuilder() .UseContentRoot(AppDomain.CurrentDomain.BaseDirectory) .UseConfiguration(SetupConfig(new ConfigurationBuilder(), args).Build()) diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs index 3a25f1d6..0fc391d1 100644 --- a/Kyoo/Startup.cs +++ b/Kyoo/Startup.cs @@ -44,6 +44,8 @@ namespace Kyoo { string publicUrl = _configuration.GetValue("public_url"); + services.AddMvc().AddControllersAsServices(); + services.AddSpaStaticFiles(configuration => { configuration.RootPath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "wwwroot"); @@ -141,6 +143,11 @@ namespace Kyoo AllowedOrigins = { new Uri(publicUrl).GetLeftPart(UriPartial.Authority) } }); } + + public void ConfigureContainer(IUnityContainer container) + { + // TODO move this to the configure section and figure out a way to reload ControllerActivators with the updated unity container + } public void Configure(IUnityContainer container, IApplicationBuilder app, IWebHostEnvironment env) { @@ -204,7 +211,7 @@ namespace Kyoo if (env.IsDevelopment()) spa.UseAngularCliServer("start"); }); - + container.RegisterType(new SingletonLifetimeManager()); IPluginManager pluginManager = new PluginManager(container, _configuration, new Logger(_loggerFactory)); pluginManager.ReloadPlugins();