New distribution model base

This commit is contained in:
2025-07-14 21:03:12 +03:00
parent 95ec6767fa
commit 17a6d3aad6
13 changed files with 94 additions and 79 deletions
+1
View File
@@ -40,6 +40,7 @@ class Program
return repo; return repo;
})); }));
builder.Services.AddSingleton<IMessageDistributorFactory, ChannelDistributorFactory>();
builder.Services.AddSingleton<IMethodRepository>(p => builder.Services.AddSingleton<IMethodRepository>(p =>
{ {
var methodRepo = new CollectableMethodRepository(); var methodRepo = new CollectableMethodRepository();
@@ -0,0 +1,15 @@
using System.Threading.Tasks;
using mROA.Implementation;
namespace mROA.Abstract
{
public interface IPrimaryMessageDistributior
{
Task Distribute(NetworkMessageHeader message);
}
public interface IMessageDistributorFactory
{
IPrimaryMessageDistributior Produce(int clientId);
}
}
+5
View File
@@ -1,9 +1,14 @@
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using mROA.Implementation;
namespace mROA.Abstract namespace mROA.Abstract
{ {
public interface IRequestExtractor public interface IRequestExtractor
{ {
Task StartExtraction(); Task StartExtraction();
void PushMessage(object parced, EMessageType originalType);
Predicate<NetworkMessageHeader> Rule { get; }
Func<NetworkMessageHeader,Type?>[] Converters { get; }
} }
} }
@@ -23,7 +23,6 @@ namespace mROA.Implementation.Backend
{ {
try try
{ {
ThrowIfNotInjected(instanceRepository);
if (command is CancelRequest) if (command is CancelRequest)
{ {
return CancelExecution(command); return CancelExecution(command);
@@ -96,18 +95,6 @@ namespace mROA.Implementation.Backend
return castedParams; return castedParams;
} }
private void ThrowIfNotInjected(IInstanceRepository instanceRepository)
{
if (_cancellationRepo is null)
throw new NullReferenceException("Method repository was not defined");
if (_methodRepo is null)
throw new NullReferenceException("Method repository was not defined");
if (instanceRepository is null)
throw new NullReferenceException("Context repository was not defined");
}
private FinalCommandExecution CancelExecution(ICallRequest command) private FinalCommandExecution CancelExecution(ICallRequest command)
{ {
var cts = _cancellationRepo.GetCancellation(command.Id); var cts = _cancellationRepo.GetCancellation(command.Id);
@@ -37,7 +37,7 @@ namespace mROA.Implementation.Backend
private IRequestExtractor CreateExtractor(IRepresentationModule interaction) private IRequestExtractor CreateExtractor(IRepresentationModule interaction)
{ {
var extractor = new RequestExtractor(_executeModule, _methodRepository, interaction, _serializationToolkit, interaction.Context); var extractor = new RequestExtractor(_executeModule, interaction, interaction.Context);
var context = interaction.Context; var context = interaction.Context;
if (_contextRepository is IContextRepositoryHub contextHub) if (_contextRepository is IContextRepositoryHub contextHub)
context.RealRepository = contextHub.GetRepository(interaction.Id); context.RealRepository = contextHub.GetRepository(interaction.Id);
@@ -11,21 +11,21 @@ namespace mROA.Implementation.Backend
{ {
public class NetworkGatewayModule : IGatewayModule public class NetworkGatewayModule : IGatewayModule
{ {
private readonly IServiceProvider _serviceProvider;
private readonly TcpListener _tcpListener; private readonly TcpListener _tcpListener;
private readonly IConnectionHub _hub; private readonly IConnectionHub _hub;
private readonly IContextualSerializationToolKit _serialization; private readonly IContextualSerializationToolKit _serialization;
private readonly Dictionary<int, CancellationTokenSource> _extractorsCTS = new(); private readonly Dictionary<int, CancellationTokenSource> _extractorsCTS = new();
private ICallIndexProvider _callIndexProvider; private ICallIndexProvider _callIndexProvider;
private readonly IIdentityGenerator _identityGenerator; private readonly IIdentityGenerator _identityGenerator;
public NetworkGatewayModule(IOptions<GatewayOptions> options, IServiceProvider service, IIdentityGenerator identityGenerator, IContextualSerializationToolKit serialization, ICallIndexProvider callIndexProvider, IConnectionHub hub) private readonly IMessageDistributorFactory _distributorFactory;
public NetworkGatewayModule(IOptions<GatewayOptions> options, IIdentityGenerator identityGenerator, IContextualSerializationToolKit serialization, ICallIndexProvider callIndexProvider, IConnectionHub hub, IMessageDistributorFactory distributorFactory)
{ {
_tcpListener = new(options.Value.Endpoint); _tcpListener = new(options.Value.Endpoint);
_serviceProvider = service;
_identityGenerator = identityGenerator; _identityGenerator = identityGenerator;
_serialization = serialization; _serialization = serialization;
_callIndexProvider = callIndexProvider; _callIndexProvider = callIndexProvider;
_hub = hub; _hub = hub;
_distributorFactory = distributorFactory;
} }
public void Run() public void Run()
@@ -74,7 +74,7 @@ namespace mROA.Implementation.Backend
interaction.PostMessageAsync(new NetworkMessageHeader(_serialization!, interaction.PostMessageAsync(new NetworkMessageHeader(_serialization!,
new IdAssignment { Id = interaction.ConnectionId }, null)); new IdAssignment { Id = interaction.ConnectionId }, null));
_extractorsCTS[interaction.ConnectionId] = cts; _extractorsCTS[interaction.ConnectionId] = cts;
_hub!.RegisterInteraction(interaction); _hub.RegisterInteraction(interaction);
Console.WriteLine("Client registered"); Console.WriteLine("Client registered");
break; break;
case EMessageType.ClientRecovery: case EMessageType.ClientRecovery:
@@ -0,0 +1,35 @@
using System.Threading.Channels;
using System.Threading.Tasks;
using mROA.Abstract;
namespace mROA.Implementation
{
public class ChannelDistributorFactory : IMessageDistributorFactory
{
private readonly IConnectionHub _hub;
public ChannelDistributorFactory(IConnectionHub hub)
{
_hub = hub;
}
public IPrimaryMessageDistributior Produce(int clientId)
{
return new ChannelMessageDistributor(_hub.GetInteraction(clientId).ReceiveChanel.Writer);
}
}
public class ChannelMessageDistributor : IPrimaryMessageDistributior
{
private readonly ChannelWriter<NetworkMessageHeader> _writer;
public ChannelMessageDistributor(ChannelWriter<NetworkMessageHeader> writer)
{
_writer = writer;
}
public async Task Distribute(NetworkMessageHeader message)
{
await _writer.WriteAsync(message);
}
}
}
@@ -82,9 +82,6 @@ namespace mROA.Implementation
public async Task PostMessageAsync(NetworkMessageHeader messageHeader) public async Task PostMessageAsync(NetworkMessageHeader messageHeader)
{ {
if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized");
while (true) while (true)
{ {
if (await PostMessageInternal(messageHeader)) if (await PostMessageInternal(messageHeader))
@@ -18,9 +18,6 @@ namespace mROA.Implementation
public IRepresentationModule Produce(int id) public IRepresentationModule Produce(int id)
{ {
if (_hub == null)
throw new NullReferenceException("Interaction module is null");
var interaction = _hub.GetInteraction(id); var interaction = _hub.GetInteraction(id);
var produced = new RepresentationModule(interaction, _serialization); var produced = new RepresentationModule(interaction, _serialization);
@@ -31,11 +31,6 @@ namespace mROA.Implementation.Frontend
public async Task Connect() public async Task Connect()
{ {
if (_interactionModule is null)
throw new Exception("Interaction module was not injected");
if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized");
_tcpClient.Connect(_serverEndPoint); _tcpClient.Connect(_serverEndPoint);
_tcpClient.NoDelay = true; _tcpClient.NoDelay = true;
PrepareExtractor(); PrepareExtractor();
@@ -9,71 +9,64 @@ namespace mROA.Implementation.Frontend
{ {
public class RequestExtractor : IRequestExtractor public class RequestExtractor : IRequestExtractor
{ {
private IExecuteModule _executeModule; private IExecuteModule _executeModule;
private IMethodRepository _methodRepository;
private IRepresentationModule _representationModule; private IRepresentationModule _representationModule;
private IContextualSerializationToolKit _serializationToolkit;
private IEndPointContext _context; private IEndPointContext _context;
public RequestExtractor(IExecuteModule executeModule, IMethodRepository methodRepository, IRepresentationModule representationModule, IContextualSerializationToolKit serializationToolkit, IEndPointContext context) public RequestExtractor(IExecuteModule executeModule, IRepresentationModule representationModule, IEndPointContext context)
{ {
_executeModule = executeModule; _executeModule = executeModule;
_methodRepository = methodRepository;
_representationModule = representationModule; _representationModule = representationModule;
_serializationToolkit = serializationToolkit;
_context = context; _context = context;
} }
public async Task StartExtraction() public async Task StartExtraction()
{ {
ThrowIfNotInjected();
var streamTokenSource = new CancellationTokenSource(); var streamTokenSource = new CancellationTokenSource();
var query = _representationModule.GetStream(m => var query = _representationModule.GetStream(Rule, _context,
m.MessageType is EMessageType.CallRequest or EMessageType.CancelRequest
or EMessageType.EventRequest or EMessageType.ClientDisconnect, _context,
streamTokenSource.Token, streamTokenSource.Token,
m => m.MessageType == EMessageType.CallRequest ? typeof(DefaultCallRequest) : null, Converters);
m => m.MessageType == EMessageType.CancelRequest ? typeof(CancelRequest) : null,
m => m.MessageType == EMessageType.EventRequest ? typeof(DefaultCallRequest) : null,
m => m.MessageType == EMessageType.ClientDisconnect ? typeof(ClientDisconnect) : null);
await foreach (var command in query) await foreach (var command in query)
{ {
switch (command.originalType) PushMessage(command.parced, command.originalType);
}
}
public void PushMessage(object parced, EMessageType originalType)
{
switch (originalType)
{ {
case EMessageType.CallRequest: case EMessageType.CallRequest:
HandleCallRequest((DefaultCallRequest)command.parced); HandleCallRequest((DefaultCallRequest)parced);
break; break;
case EMessageType.ClientDisconnect: case EMessageType.ClientDisconnect:
return; return;
case EMessageType.EventRequest: case EMessageType.EventRequest:
HandleEventRequest((DefaultCallRequest)command.parced); HandleEventRequest((DefaultCallRequest)parced);
break; break;
case EMessageType.CancelRequest: case EMessageType.CancelRequest:
HandleCancelRequest((command.parced as CancelRequest)!); HandleCancelRequest((parced as CancelRequest)!);
break; break;
default: default:
continue; return;
}
} }
} }
private void ThrowIfNotInjected() public Predicate<NetworkMessageHeader> Rule { get; } = m =>
{ m.MessageType is EMessageType.CallRequest or EMessageType.CancelRequest
if (_serializationToolkit == null) or EMessageType.EventRequest or EMessageType.ClientDisconnect;
throw new NullReferenceException("Serializing toolkit is null.");
if (_executeModule == null) public Func<NetworkMessageHeader, Type?>[] Converters { get; } = {
throw new NullReferenceException("Execute module is null."); m => m.MessageType == EMessageType.CallRequest ? typeof(DefaultCallRequest) : null,
if (_representationModule == null) m => m.MessageType == EMessageType.CancelRequest ? typeof(CancelRequest) : null,
throw new NullReferenceException("Representation module is null."); m => m.MessageType == EMessageType.EventRequest ? typeof(DefaultCallRequest) : null,
if (_methodRepository == null) m => m.MessageType == EMessageType.ClientDisconnect ? typeof(ClientDisconnect) : null
throw new NullReferenceException("Method repository is null."); };
}
private void HandleCancelRequest(CancelRequest req) private void HandleCancelRequest(CancelRequest req)
{ {
@@ -34,8 +34,6 @@ namespace mROA.Implementation
var index = _producedProxys.Find(i => i.Identifier.Equals(id)); var index = _producedProxys.Find(i => i.Identifier.Equals(id));
if (index is not null) if (index is not null)
return (T)(index as object); return (T)(index as object);
if (_representationProducer == null)
throw new NullReferenceException("representation producer is not initialized");
if (!_callIndexProvider.Activators.TryGetValue(typeof(T), out var remoteType)) if (!_callIndexProvider.Activators.TryGetValue(typeof(T), out var remoteType))
throw new NotSupportedException(); throw new NotSupportedException();
@@ -56,9 +54,6 @@ namespace mROA.Implementation
public object GetSingletonObject(Type type, IEndPointContext context) public object GetSingletonObject(Type type, IEndPointContext context)
{ {
if (_representationProducer == null)
throw new NullReferenceException("representation producer is not initialized");
var representationModule = var representationModule =
_representationProducer.Produce(context.OwnerId); _representationProducer.Produce(context.OwnerId);
@@ -82,11 +82,6 @@ namespace mROA.Implementation
public async Task PostCallMessageAsync<T>(Guid id, EMessageType eMessageType, T payload, public async Task PostCallMessageAsync<T>(Guid id, EMessageType eMessageType, T payload,
IEndPointContext? context) where T : notnull IEndPointContext? context) where T : notnull
{ {
if (_interaction == null)
throw new NullReferenceException("Interaction toolkit is not initialized");
if (_serialization == null)
throw new NullReferenceException("Serialization toolkit is not initialized");
var serialized = _serialization.Serialize(payload, context); var serialized = _serialization.Serialize(payload, context);
await _interaction.PostMessageAsync(new NetworkMessageHeader await _interaction.PostMessageAsync(new NetworkMessageHeader
{ Id = id, MessageType = eMessageType, Data = serialized }); { Id = id, MessageType = eMessageType, Data = serialized });