mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-04-28 08:19:47 +00:00
Implement semaphore for plugin loading to prevent concurrent initialization
This commit is contained in:
parent
5fe3e1cb34
commit
9cf4f943fb
@ -13,6 +13,7 @@ public static partial class PluginFactory
|
|||||||
private static readonly SettingsManager SETTINGS_MANAGER = Program.SERVICE_PROVIDER.GetRequiredService<SettingsManager>();
|
private static readonly SettingsManager SETTINGS_MANAGER = Program.SERVICE_PROVIDER.GetRequiredService<SettingsManager>();
|
||||||
private static readonly List<IAvailablePlugin> AVAILABLE_PLUGINS = [];
|
private static readonly List<IAvailablePlugin> AVAILABLE_PLUGINS = [];
|
||||||
private static readonly List<PluginBase> RUNNING_PLUGINS = [];
|
private static readonly List<PluginBase> RUNNING_PLUGINS = [];
|
||||||
|
private static readonly SemaphoreSlim PLUGIN_LOAD_SEMAPHORE = new(1, 1);
|
||||||
|
|
||||||
private static bool IS_INITIALIZED;
|
private static bool IS_INITIALIZED;
|
||||||
private static string DATA_DIR = string.Empty;
|
private static string DATA_DIR = string.Empty;
|
||||||
@ -73,39 +74,44 @@ public static partial class PluginFactory
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.LogInformation("Start loading plugins.");
|
if (!await PLUGIN_LOAD_SEMAPHORE.WaitAsync(0, cancellationToken))
|
||||||
if (!Directory.Exists(PLUGINS_ROOT))
|
|
||||||
{
|
|
||||||
LOG.LogInformation("No plugins found.");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
AVAILABLE_PLUGINS.Clear();
|
try
|
||||||
|
|
||||||
//
|
|
||||||
// The easiest way to load all plugins is to find all `plugin.lua` files and load them.
|
|
||||||
// By convention, each plugin is enforced to have a `plugin.lua` file.
|
|
||||||
//
|
|
||||||
var pluginMainFiles = Directory.EnumerateFiles(PLUGINS_ROOT, "plugin.lua", SearchOption.AllDirectories);
|
|
||||||
foreach (var pluginMainFile in pluginMainFiles)
|
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
LOG.LogInformation("Start loading plugins.");
|
||||||
break;
|
if (!Directory.Exists(PLUGINS_ROOT))
|
||||||
|
|
||||||
LOG.LogInformation($"Try to load plugin: {pluginMainFile}");
|
|
||||||
var code = await File.ReadAllTextAsync(pluginMainFile, Encoding.UTF8, cancellationToken);
|
|
||||||
var pluginPath = Path.GetDirectoryName(pluginMainFile)!;
|
|
||||||
var plugin = await Load(pluginPath, code, cancellationToken);
|
|
||||||
|
|
||||||
switch (plugin)
|
|
||||||
{
|
{
|
||||||
case NoPlugin noPlugin when noPlugin.Issues.Any():
|
LOG.LogInformation("No plugins found.");
|
||||||
LOG.LogError($"Was not able to load plugin: '{pluginMainFile}'. Reason: {noPlugin.Issues.First()}");
|
return;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
case NoPlugin:
|
AVAILABLE_PLUGINS.Clear();
|
||||||
LOG.LogError($"Was not able to load plugin: '{pluginMainFile}'. Reason: Unknown.");
|
|
||||||
continue;
|
//
|
||||||
|
// The easiest way to load all plugins is to find all `plugin.lua` files and load them.
|
||||||
|
// By convention, each plugin is enforced to have a `plugin.lua` file.
|
||||||
|
//
|
||||||
|
var pluginMainFiles = Directory.EnumerateFiles(PLUGINS_ROOT, "plugin.lua", SearchOption.AllDirectories);
|
||||||
|
foreach (var pluginMainFile in pluginMainFiles)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
break;
|
||||||
|
|
||||||
|
LOG.LogInformation($"Try to load plugin: {pluginMainFile}");
|
||||||
|
var code = await File.ReadAllTextAsync(pluginMainFile, Encoding.UTF8, cancellationToken);
|
||||||
|
var pluginPath = Path.GetDirectoryName(pluginMainFile)!;
|
||||||
|
var plugin = await Load(pluginPath, code, cancellationToken);
|
||||||
|
|
||||||
|
switch (plugin)
|
||||||
|
{
|
||||||
|
case NoPlugin noPlugin when noPlugin.Issues.Any():
|
||||||
|
LOG.LogError($"Was not able to load plugin: '{pluginMainFile}'. Reason: {noPlugin.Issues.First()}");
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case NoPlugin:
|
||||||
|
LOG.LogError($"Was not able to load plugin: '{pluginMainFile}'. Reason: Unknown.");
|
||||||
|
continue;
|
||||||
|
|
||||||
case { IsValid: false }:
|
case { IsValid: false }:
|
||||||
LOG.LogError($"Was not able to load plugin '{pluginMainFile}', because the Lua code is not a valid AI Studio plugin. There are {plugin.Issues.Count()} issues to fix.");
|
LOG.LogError($"Was not able to load plugin '{pluginMainFile}', because the Lua code is not a valid AI Studio plugin. There are {plugin.Issues.Count()} issues to fix.");
|
||||||
@ -124,8 +130,14 @@ public static partial class PluginFactory
|
|||||||
AVAILABLE_PLUGINS.Add(new PluginMetadata(plugin, pluginPath));
|
AVAILABLE_PLUGINS.Add(new PluginMetadata(plugin, pluginPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start or restart all plugins:
|
// Start or restart all plugins:
|
||||||
await RestartAllPlugins(cancellationToken);
|
await RestartAllPlugins(cancellationToken);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
PLUGIN_LOAD_SEMAPHORE.Release();
|
||||||
|
LOG.LogInformation("Finished loading plugins.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<PluginBase> Load(string pluginPath, string code, CancellationToken cancellationToken = default)
|
private static async Task<PluginBase> Load(string pluginPath, string code, CancellationToken cancellationToken = default)
|
||||||
|
Loading…
Reference in New Issue
Block a user