mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-08-21 04:12:56 +00:00
Implemented another hot reload locking mechanism
This commit is contained in:
parent
bc88746c61
commit
c6d61a3de0
@ -42,6 +42,7 @@ public static partial class PluginFactory
|
|||||||
var tempDownloadFile = Path.GetTempFileName();
|
var tempDownloadFile = Path.GetTempFileName();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
await LockHotReloadAsync();
|
||||||
using var httpClient = new HttpClient();
|
using var httpClient = new HttpClient();
|
||||||
var response = await httpClient.GetAsync(downloadUrl, cancellationToken);
|
var response = await httpClient.GetAsync(downloadUrl, cancellationToken);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
@ -80,6 +81,8 @@ public static partial class PluginFactory
|
|||||||
LOG.LogError(e, "Failed to delete the temporary download file.");
|
LOG.LogError(e, "Failed to delete the temporary download file.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnlockHotReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -46,12 +46,41 @@ public static partial class PluginFactory
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
LOG.LogInformation($"File changed ({changeType}): {args.FullPath}. Reloading plugins...");
|
LOG.LogInformation($"File changed ({changeType}): {args.FullPath}. Reloading plugins...");
|
||||||
|
if (File.Exists(HOT_RELOAD_LOCK_FILE))
|
||||||
|
{
|
||||||
|
LOG.LogInformation("Hot reload lock file exists. Waiting for it to be released before proceeding with the reload.");
|
||||||
|
|
||||||
|
var lockFileCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30));
|
||||||
|
var token = lockFileCancellationTokenSource.Token;
|
||||||
|
var waitTime = TimeSpan.FromSeconds(1);
|
||||||
|
while (File.Exists(HOT_RELOAD_LOCK_FILE) && !token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LOG.LogDebug("Waiting for hot reload lock to be released...");
|
||||||
|
await Task.Delay(waitTime, token);
|
||||||
|
waitTime = TimeSpan.FromSeconds(Math.Min(waitTime.TotalSeconds * 2, 120)); // Exponential backoff with a cap
|
||||||
|
}
|
||||||
|
catch (TaskCanceledException)
|
||||||
|
{
|
||||||
|
// Case: The cancellation token was triggered, meaning the lock file is still present.
|
||||||
|
// We expect that something goes wrong. So, we try to delete the lock file:
|
||||||
|
LOG.LogWarning("Hot reload lock file still exists after 30 seconds. Attempting to delete it...");
|
||||||
|
UnlockHotReload();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.LogInformation("Hot reload lock file released. Proceeding with plugin reload.");
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for parallel writes to finish:
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(3));
|
|
||||||
await LoadAll();
|
await LoadAll();
|
||||||
await MessageBus.INSTANCE.SendMessage<bool>(null, Event.PLUGINS_RELOADED);
|
await MessageBus.INSTANCE.SendMessage<bool>(null, Event.PLUGINS_RELOADED);
|
||||||
}
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.LogError(e, $"Error while reloading plugins after change in file '{args.FullPath}' with change type '{changeType}'.");
|
||||||
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
HOT_RELOAD_SEMAPHORE.Release();
|
HOT_RELOAD_SEMAPHORE.Release();
|
||||||
|
@ -13,6 +13,7 @@ public static partial class PluginFactory
|
|||||||
private static string PLUGINS_ROOT = string.Empty;
|
private static string PLUGINS_ROOT = string.Empty;
|
||||||
private static string INTERNAL_PLUGINS_ROOT = string.Empty;
|
private static string INTERNAL_PLUGINS_ROOT = string.Empty;
|
||||||
private static string CONFIGURATION_PLUGINS_ROOT = string.Empty;
|
private static string CONFIGURATION_PLUGINS_ROOT = string.Empty;
|
||||||
|
private static string HOT_RELOAD_LOCK_FILE = string.Empty;
|
||||||
private static FileSystemWatcher HOT_RELOAD_WATCHER = null!;
|
private static FileSystemWatcher HOT_RELOAD_WATCHER = null!;
|
||||||
private static ILanguagePlugin BASE_LANGUAGE_PLUGIN = NoPluginLanguage.INSTANCE;
|
private static ILanguagePlugin BASE_LANGUAGE_PLUGIN = NoPluginLanguage.INSTANCE;
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ public static partial class PluginFactory
|
|||||||
LOG.LogInformation("Initializing plugin factory...");
|
LOG.LogInformation("Initializing plugin factory...");
|
||||||
DATA_DIR = SettingsManager.DataDirectory!;
|
DATA_DIR = SettingsManager.DataDirectory!;
|
||||||
PLUGINS_ROOT = Path.Join(DATA_DIR, "plugins");
|
PLUGINS_ROOT = Path.Join(DATA_DIR, "plugins");
|
||||||
|
HOT_RELOAD_LOCK_FILE = Path.Join(PLUGINS_ROOT, ".lock");
|
||||||
INTERNAL_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".internal");
|
INTERNAL_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".internal");
|
||||||
CONFIGURATION_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".config");
|
CONFIGURATION_PLUGINS_ROOT = Path.Join(PLUGINS_ROOT, ".config");
|
||||||
|
|
||||||
@ -42,6 +44,51 @@ public static partial class PluginFactory
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task LockHotReloadAsync()
|
||||||
|
{
|
||||||
|
if (!IS_INITIALIZED)
|
||||||
|
{
|
||||||
|
LOG.LogError("PluginFactory is not initialized.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(HOT_RELOAD_LOCK_FILE))
|
||||||
|
{
|
||||||
|
LOG.LogWarning("Hot reload lock file already exists.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await File.WriteAllTextAsync(HOT_RELOAD_LOCK_FILE, DateTime.UtcNow.ToString("o"));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.LogError(e, "An error occurred while trying to lock hot reloading.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UnlockHotReload()
|
||||||
|
{
|
||||||
|
if (!IS_INITIALIZED)
|
||||||
|
{
|
||||||
|
LOG.LogError("PluginFactory is not initialized.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(File.Exists(HOT_RELOAD_LOCK_FILE))
|
||||||
|
File.Delete(HOT_RELOAD_LOCK_FILE);
|
||||||
|
else
|
||||||
|
LOG.LogWarning("Hot reload lock file does not exist. Nothing to unlock.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.LogError(e, "An error occurred while trying to unlock hot reloading.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void Dispose()
|
public static void Dispose()
|
||||||
{
|
{
|
||||||
if(!IS_INITIALIZED)
|
if(!IS_INITIALIZED)
|
||||||
|
Loading…
Reference in New Issue
Block a user