1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 21:38:38 +00:00

Core - Added plugin hot reloading

This commit is contained in:
Diogo Trindade 2023-04-16 17:35:43 +01:00
parent 0b5866a2b8
commit 0c44e4ba22

View File

@ -5,6 +5,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Core.DeviceProviders;
using Artemis.Core.DryIoc;
@ -30,6 +31,7 @@ internal class PluginManagementService : IPluginManagementService
private readonly IPluginRepository _pluginRepository;
private readonly List<Plugin> _plugins;
private readonly IQueuedActionRepository _queuedActionRepository;
private FileSystemWatcher _hotReloadWatcher;
private bool _disposed;
private bool _isElevated;
@ -43,6 +45,8 @@ internal class PluginManagementService : IPluginManagementService
_plugins = new List<Plugin>();
ProcessPluginDeletionQueue();
StartHotReload();
}
private void CopyBuiltInPlugin(ZipArchive zipArchive, string targetDirectory)
@ -218,6 +222,14 @@ internal class PluginManagementService : IPluginManagementService
return null;
}
private Plugin? GetPluginByDirectory(DirectoryInfo directory)
{
lock (_plugins)
{
return _plugins.FirstOrDefault(p => p.Directory.FullName == directory.FullName);
}
}
public void Dispose()
{
// Disposal happens manually before container disposal but the container doesn't know that so a 2nd call will be made
@ -912,6 +924,67 @@ internal class PluginManagementService : IPluginManagementService
}
#endregion
#region Hot Reload
private void StartHotReload()
{
// Watch for changes in the plugin directory, "plugin.json".
// If this file is changed, reload the plugin.
_hotReloadWatcher = new FileSystemWatcher(Constants.PluginsFolder, "plugin.json");
_hotReloadWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.FileName;
_hotReloadWatcher.Created += FileSystemWatcherOnCreated;
_hotReloadWatcher.Error += FileSystemWatcherOnError;
_hotReloadWatcher.IncludeSubdirectories = true;
_hotReloadWatcher.EnableRaisingEvents = true;
}
private void FileSystemWatcherOnError(object sender, ErrorEventArgs e)
{
_logger.Error(e.GetException(), "File system watcher error");
}
private void FileSystemWatcherOnCreated(object sender, FileSystemEventArgs e)
{
string? pluginPath = Path.GetDirectoryName(e.FullPath);
if (pluginPath == null)
{
_logger.Warning("Plugin change detected, but could not get plugin directory. {fullPath}", e.FullPath);
return;
}
DirectoryInfo pluginDirectory = new(pluginPath);
Plugin? plugin = GetPluginByDirectory(pluginDirectory);
if (plugin == null)
{
_logger.Warning("Plugin change detected, but could not find plugin. {fullPath}", e.FullPath);
return;
}
_logger.Information("Plugin change detected, reloading. {pluginName}", plugin.Info.Name);
bool wasEnabled = plugin.IsEnabled;
UnloadPlugin(plugin);
Thread.Sleep(500);
Plugin? loadedPlugin = LoadPlugin(pluginDirectory);
if (loadedPlugin == null)
{
return;
}
if (wasEnabled)
{
EnablePlugin(loadedPlugin, true, false);
}
_logger.Information("Plugin reloaded. {fullPath}", e.FullPath);
}
#endregion
}
/// <summary>