aboutsummaryrefslogtreecommitdiff
path: root/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs
diff options
context:
space:
mode:
authorLibravatar vman <public@vaughnnugent.com>2022-11-30 14:59:09 -0500
committerLibravatar vman <public@vaughnnugent.com>2022-11-30 14:59:09 -0500
commitc9d9e6d23ad7b6fdf25f30de9b4a84be23885e16 (patch)
tree6f8336e55da2b06bfac2204510bf661dfa1a1476 /VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs
parente8a846c83ca9922761db56373bc93fe4ea3f4021 (diff)
Project cleanup + analyzer updates
Diffstat (limited to 'VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs')
-rw-r--r--VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs57
1 files changed, 54 insertions, 3 deletions
diff --git a/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs b/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs
index 411b9b4..bfe0de1 100644
--- a/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs
+++ b/VNLib.Plugins.Extensions.Loading/LoadingExtensions.cs
@@ -26,11 +26,13 @@ using System;
using System.IO;
using System.Linq;
using System.Text.Json;
+using System.Threading.Tasks;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Runtime.CompilerServices;
using VNLib.Utils;
+using VNLib.Utils.Logging;
using VNLib.Utils.Extensions;
using VNLib.Plugins.Essentials.Accounts;
@@ -44,10 +46,9 @@ namespace VNLib.Plugins.Extensions.Loading
public const string DEBUG_CONFIG_KEY = "debug";
public const string SECRETS_CONFIG_KEY = "secrets";
public const string PASSWORD_HASHING_KEY = "passwords";
-
-
+
private static readonly ConditionalWeakTable<PluginBase, Lazy<PasswordHashing>> LazyPasswordTable = new();
-
+
/// <summary>
/// Gets the plugins ambient <see cref="PasswordHashing"/> if loaded, or loads it if required. This class will
@@ -176,5 +177,55 @@ namespace VNLib.Plugins.Extensions.Loading
throw new ObjectDisposedException("The plugin has been unloaded");
}
}
+
+ /// <summary>
+ /// Schedules an asynchronous callback function to run and its results will be observed
+ /// when the operation completes, or when the plugin is unloading
+ /// </summary>
+ /// <param name="plugin"></param>
+ /// <param name="asyncTask">The asynchronous operation to observe</param>
+ /// <param name="delayMs">An optional startup delay for the operation</param>
+ /// <returns>A task that completes when the deferred task completes </returns>
+ /// <exception cref="ObjectDisposedException"></exception>
+ public static async Task DeferTask(this PluginBase plugin, Func<Task> asyncTask, int delayMs = 0)
+ {
+ /*
+ * Motivation:
+ * Sometimes during plugin loading, a plugin may want to asynchronously load
+ * data, where the results are not required to be observed during loading, but
+ * should not be pending after the plugin is unloaded, as the assembly may be
+ * unloaded and referrences collected by the GC.
+ *
+ * So we can use the plugin's unload cancellation token to observe the results
+ * of a pending async operation
+ */
+
+ //Test status
+ plugin.ThrowIfUnloaded();
+
+ //Optional delay
+ await Task.Delay(delayMs);
+
+ //Run on ts
+ Task deferred = Task.Run(asyncTask);
+
+ //Add task to deferred list
+ plugin.DeferredTasks.Add(deferred);
+ try
+ {
+ //Await the task results
+ await deferred;
+ }
+ catch(Exception ex)
+ {
+ //Log errors
+ plugin.Log.Error(ex, "Error occured while observing deferred task");
+ }
+ finally
+ {
+ //Remove task when complete
+ plugin.DeferredTasks.Remove(deferred);
+ }
+ }
}
}