implement message subscribing and worker

This commit is contained in:
2026-02-14 19:17:05 +01:00
parent 4cdfa1e096
commit 0dadaf1280
19 changed files with 376 additions and 11 deletions

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AipsCore\AipsCore.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DotNetEnv" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.3" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,21 @@
using AipsCore.Infrastructure.DI;
using AipsWorker;
using AipsWorker.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
LoadingDotEnv.TryLoad();
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureServices((context, services) =>
{
services.AddAips(context.Configuration);
services.AddAipsMessageHandlers();
services.AddHostedService<WorkerService>();
});
var app = builder.Build();
await app.RunAsync();

View File

@@ -0,0 +1,24 @@
using DotNetEnv;
namespace AipsWorker.Utilities;
public static class LoadingDotEnv
{
public static bool TryLoad()
{
string? dir = Directory.GetCurrentDirectory();
while (dir != null && !File.Exists(Path.Combine(dir, ".env")))
{
dir = Directory.GetParent(dir)?.FullName;
}
if (dir != null)
{
Env.Load(Path.Combine(dir, ".env"));
return true;
}
return false;
}
}

View File

@@ -0,0 +1,48 @@
using System.Reflection;
using AipsCore.Application.Abstract.MessageBroking;
namespace AipsWorker.Utilities;
public class SubscribeMethodUtility
{
private readonly IMessageSubscriber _subscriber;
public SubscribeMethodUtility(IMessageSubscriber subscriber)
{
_subscriber = subscriber;
}
public async Task SubscribeToMessageTypeAsync(
Type messageType,
object targetInstance,
MethodInfo handlerMethod)
{
var subscribeMethod = GetGenericSubscribeMethod(messageType);
var handlerDelegate = CreateHandlerDelegate(messageType, targetInstance, handlerMethod);
var task = (Task)subscribeMethod.Invoke(
_subscriber,
new object[] { handlerDelegate })!;
await task;
}
private MethodInfo GetGenericSubscribeMethod(Type messageType)
{
var method = typeof(IMessageSubscriber)
.GetMethod(nameof(IMessageSubscriber.SubscribeAsync))!;
return method.MakeGenericMethod(messageType);
}
private Delegate CreateHandlerDelegate(
Type messageType,
object targetInstance,
MethodInfo handlerMethod)
{
var delegateType = typeof(Func<,,>)
.MakeGenericType(messageType, typeof(CancellationToken), typeof(Task));
return Delegate.CreateDelegate(delegateType, targetInstance, handlerMethod);
}
}

View File

@@ -0,0 +1,61 @@
using System.Reflection;
using AipsCore.Application.Abstract;
using AipsCore.Application.Abstract.MessageBroking;
using AipsCore.Application.Common.Message.TestMessage;
using AipsWorker.Utilities;
using Microsoft.Extensions.Hosting;
namespace AipsWorker;
public class WorkerService : BackgroundService
{
private readonly IDispatcher _dispatcher;
private readonly SubscribeMethodUtility _subscribeMethodUtility;
public WorkerService(IMessageSubscriber subscriber, IDispatcher dispatcher)
{
_dispatcher = dispatcher;
_subscribeMethodUtility = new SubscribeMethodUtility(subscriber);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var messageTypes = GetAllMessageTypes();
foreach (var messageType in messageTypes)
{
var handleMethod = GetMessageHandleMethod(messageType);
await _subscribeMethodUtility.SubscribeToMessageTypeAsync(messageType, this, handleMethod);
}
}
private IReadOnlyCollection<Type> GetAllMessageTypes()
{
var messageInterface = typeof(IMessage);
var assembly = messageInterface.Assembly;
return assembly
.GetTypes()
.Where(t =>
!t.IsAbstract &&
!t.IsInterface &&
messageInterface.IsAssignableFrom(t))
.ToList();
}
private async Task HandleMessage<T>(T message, CancellationToken ct) where T : IMessage
{
await _dispatcher.Execute(message, ct);
}
private MethodInfo GetMessageHandleMethod(Type messageType)
{
return GetType()
.GetMethod(nameof(HandleMessage),
BindingFlags.Instance | BindingFlags.NonPublic)!
.MakeGenericMethod(messageType);
}
}