aboutsummaryrefslogtreecommitdiff
path: root/lib/Plugins.Runtime/src/AssemblyWatcher.cs
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-09-27 01:09:11 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-09-27 01:09:11 -0400
commit5150e2ad6d07a8b12c6678329d18fdb8acacf7f0 (patch)
tree81321ccac14a359ec3b087632fc7f3fdfa7ac689 /lib/Plugins.Runtime/src/AssemblyWatcher.cs
parent3f2982f9b48dcef1a7434d396c45d57bb61d0a3c (diff)
serializer overhaul, plugin cleanup round 3 or 4, more tests
Diffstat (limited to 'lib/Plugins.Runtime/src/AssemblyWatcher.cs')
-rw-r--r--lib/Plugins.Runtime/src/AssemblyWatcher.cs81
1 files changed, 80 insertions, 1 deletions
diff --git a/lib/Plugins.Runtime/src/AssemblyWatcher.cs b/lib/Plugins.Runtime/src/AssemblyWatcher.cs
index 1cf87b0..09b49dc 100644
--- a/lib/Plugins.Runtime/src/AssemblyWatcher.cs
+++ b/lib/Plugins.Runtime/src/AssemblyWatcher.cs
@@ -22,8 +22,13 @@
* along with VNLib.Plugins.Runtime. If not, see http://www.gnu.org/licenses/.
*/
+using System.IO;
+using System.Threading;
using System.Collections.Generic;
+using VNLib.Utils;
+using VNLib.Utils.Extensions;
+
namespace VNLib.Plugins.Runtime
{
internal sealed class AssemblyWatcher : IPluginAssemblyWatcher
@@ -36,6 +41,7 @@ namespace VNLib.Plugins.Runtime
_watchers = new();
}
+ ///<inheritdoc/>
public void StopWatching(IPluginReloadEventHandler handler)
{
lock (_lock)
@@ -49,6 +55,7 @@ namespace VNLib.Plugins.Runtime
}
}
+ ///<inheritdoc/>
public void WatchAssembly(IPluginReloadEventHandler handler, IPluginAssemblyLoader loader)
{
lock(_lock)
@@ -65,6 +72,78 @@ namespace VNLib.Plugins.Runtime
//Store watcher
_watchers.Add(handler, watcher);
}
- }
+ }
+
+ private sealed class AsmFileWatcher : VnDisposeable
+ {
+ public IPluginReloadEventHandler Handler { get; }
+
+ private readonly IPluginAssemblyLoader _loaderSource;
+ private readonly Timer _delayTimer;
+ private readonly FileSystemWatcher _watcher;
+
+ private bool _pause;
+
+ public AsmFileWatcher(IPluginAssemblyLoader LoaderSource, IPluginReloadEventHandler handler)
+ {
+ Handler = handler;
+ _loaderSource = LoaderSource;
+
+ string dir = Path.GetDirectoryName(LoaderSource.Config.AssemblyFile)!;
+
+ //Configure watcher to notify only when the assembly file changes
+ _watcher = new FileSystemWatcher(dir)
+ {
+ Filter = "*.dll",
+ EnableRaisingEvents = false,
+ IncludeSubdirectories = true,
+ NotifyFilter = NotifyFilters.LastWrite,
+ };
+
+ //Configure listener
+ _watcher.Changed += OnFileChanged;
+ _watcher.Created += OnFileChanged;
+
+ _watcher.EnableRaisingEvents = true;
+
+ //setup delay timer to wait on the config
+ _delayTimer = new(OnTimeout, this, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
+ }
+
+ void OnFileChanged(object sender, FileSystemEventArgs e)
+ {
+ //if were already waiting to process an event, we dont need to stage another
+ if (_pause)
+ {
+ return;
+ }
+
+ //Set pause flag
+ _pause = true;
+
+ //Restart the timer to trigger reload event on elapsed
+ _delayTimer.Restart(_loaderSource.Config.ReloadDelay);
+ }
+
+ private void OnTimeout(object? state)
+ {
+ _delayTimer.Stop();
+
+ //Fire event, let exception crash app
+ Handler.OnPluginUnloaded(_loaderSource);
+
+ //Clear pause flag
+ _pause = false;
+ }
+
+ protected override void Free()
+ {
+ _delayTimer.Dispose();
+
+ //Detach event handler and dispose watcher
+ _watcher.Changed -= OnFileChanged;
+ _watcher.Dispose();
+ }
+ }
}
}