aboutsummaryrefslogtreecommitdiff
path: root/PagerHandler.cs
diff options
context:
space:
mode:
authorJake Mannens <jake@asger.xyz>2024-09-20 16:21:09 +1000
committerJake Mannens <jake@asger.xyz>2024-10-29 11:42:54 +1100
commite8e3c4cba8ffa0056e984c113cfbb75319e00022 (patch)
tree8336315e61f9e77207276d478b25fe5dc7c3d06c /PagerHandler.cs
parent0e21907c76dbefed11f382bcf949143f0716567f (diff)
v0.4-rc1v0.4-rc1
Diffstat (limited to 'PagerHandler.cs')
-rw-r--r--PagerHandler.cs125
1 files changed, 125 insertions, 0 deletions
diff --git a/PagerHandler.cs b/PagerHandler.cs
new file mode 100644
index 0000000..8520064
--- /dev/null
+++ b/PagerHandler.cs
@@ -0,0 +1,125 @@
+using System.Reflection;
+
+namespace PagerParser;
+
+[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
+public class PagerHandlerAttribute : Attribute {}
+
+public interface IPagerHandler {
+ public void OnConfiguring(
+ ILogger logger,
+ IConfiguration config,
+ IServiceProvider serviceProvider);
+
+ public Task StartAsync(CancellationToken ct);
+ public Task StopAsync(CancellationToken ct);
+
+ public Task HandleMessageAsync(
+ PagerMessage message,
+ ParsedPagerMessage? parsedMessage);
+}
+
+public interface IRootPagerHandler {
+ public Task HandleMessageAsync(
+ PagerMessage message,
+ ParsedPagerMessage? parsedMessage);
+}
+
+public class RootPagerHandler : IRootPagerHandler, IHostedService {
+ private readonly HandlerEntry[] handlers;
+
+ private readonly ILogger<RootPagerHandler> logger;
+
+ public RootPagerHandler(IServiceProvider serviceProvider) {
+ handlers = typeof(RootPagerHandler).Assembly.GetTypes()
+ .Where(t => t.IsClass)
+ .Where(t => t.IsAssignableTo(typeof(IPagerHandler)))
+ .Where(t => t.GetCustomAttributes<PagerHandlerAttribute>().Any())
+ .Select(t => Activator.CreateInstance(t))
+ .Cast<IPagerHandler>()
+ .Select(h => new HandlerEntry(h))
+ .ToArray();
+
+ var config = serviceProvider.GetRequiredService<IConfiguration>();
+
+ logger = serviceProvider.GetRequiredService<ILogger<RootPagerHandler>>();
+
+ foreach(var entry in handlers) {
+ var name = entry.Handler.GetType().Name;
+ var loggerType = typeof(ILogger<>).MakeGenericType(entry.GetType());
+ var logger = serviceProvider.GetRequiredService(loggerType);
+ try {
+ this.logger.LogDebug($"Configuring page handler: {name}");
+ entry.Handler.OnConfiguring((ILogger) logger, config, serviceProvider);
+ } catch {
+ // TODO: include exceptions in log on failure
+ this.logger.LogWarning($"Failed to configure page handler: {name}");
+ entry.State = HandlerState.Failed;
+ }
+ }
+ }
+
+ public async Task StartAsync(CancellationToken ct) {
+ logger.LogInformation("Root pager handler service starting...");
+ await Task.WhenAll(
+ handlers.Select(async e => {
+ var name = e.Handler.GetType().Name;
+ if(e.State != HandlerState.Stopped)
+ return;
+ logger.LogDebug($"Starting page handler: {name}");
+ try {
+ await e.Handler.StartAsync(ct);
+ e.State = HandlerState.Started;
+ } catch {
+ logger.LogWarning($"Failed to start page handler: {name}");
+ e.State = HandlerState.Failed;
+ }
+ }).ToArray());
+ }
+
+ public async Task StopAsync(CancellationToken ct) {
+ logger.LogInformation("Root pager handler service stopping...");
+ await Task.WhenAll(
+ handlers.Select(async e => {
+ var name = e.Handler.GetType().Name;
+ if(e.State != HandlerState.Started)
+ return;
+ logger.LogDebug($"Stopping page handler: {name}");
+ try {
+ await e.Handler.StopAsync(ct);
+ e.State = HandlerState.Stopped;
+ } catch {
+ logger.LogWarning($"Failed to stop page handler: {name}");
+ e.State = HandlerState.Failed;
+ }
+ }).ToArray());
+ }
+
+ public async Task HandleMessageAsync(PagerMessage m, ParsedPagerMessage? pm) {
+ await Task.WhenAll(
+ handlers
+ .Where(e => e.State == HandlerState.Started)
+ .Select(async e => {
+ var name = e.Handler.GetType().Name;
+ try {
+ await e.Handler.HandleMessageAsync(m, pm);
+ } catch {
+ logger.LogWarning($"Page handler {name} failed to handle pager message");
+ }
+ }).ToArray());
+ }
+
+ private record HandlerEntry {
+ public IPagerHandler Handler { get; set; }
+ public HandlerState State { get; set; } = HandlerState.Stopped;
+
+ public HandlerEntry(IPagerHandler handler) =>
+ Handler = handler;
+ }
+
+ private enum HandlerState {
+ Stopped,
+ Started,
+ Failed
+ }
+}