Skip to content

Commit 439c466

Browse files
committed
feat: WIP request/response message handler (not done yet)
1 parent 93261cf commit 439c466

5 files changed

Lines changed: 120 additions & 9 deletions

File tree

SimpleNetworkManager.NET/Messages/BaseRequestMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ public abstract class BaseRequestMessage : BaseMessage
1414
/// Generated automatically when the request is created.
1515
/// </summary>
1616
[Key(0)]
17-
public Guid RequestId { get; set; }
17+
public Guid RequestId { get; internal set; }
1818
}
1919
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Cysharp.Threading.Tasks;
2+
using Insthync.SimpleNetworkManager.NET.Network;
3+
using System;
4+
5+
namespace Insthync.SimpleNetworkManager.NET.Messages
6+
{
7+
public abstract class BaseRequestResponseMessageHandler<TRequest, TResponse> : BaseMessageHandler<TRequest>, IResponseMessageHandler
8+
where TRequest : BaseRequestMessage
9+
where TResponse : BaseResponseMessage
10+
{
11+
private static TResponse? s_responseMessageInstance;
12+
13+
public virtual BaseMessage GetResponseMessageInstance()
14+
{
15+
if (s_responseMessageInstance == null)
16+
s_responseMessageInstance = Activator.CreateInstance<TResponse>();
17+
return s_responseMessageInstance;
18+
}
19+
20+
protected override sealed async UniTask HandleAsync(BaseClientConnection clientConnection, TRequest data)
21+
{
22+
Guid requestId = data.RequestId;
23+
var response = await HandleRequestAsync(clientConnection, data);
24+
response.RequestId = requestId;
25+
await clientConnection.SendMessageAsync(data);
26+
}
27+
28+
protected abstract UniTask<TResponse> HandleRequestAsync(BaseClientConnection clientConnection, TRequest request);
29+
30+
public UniTask HandleResponseDataAsync(BaseClientConnection clientConnection, object? data)
31+
{
32+
if (data == null)
33+
throw new ArgumentNullException(nameof(data));
34+
return HandleResponseAsync(clientConnection, (TResponse)data);
35+
}
36+
37+
protected abstract UniTask HandleResponseAsync(BaseClientConnection clientConnection, TResponse request);
38+
}
39+
}

SimpleNetworkManager.NET/Messages/BaseResponseMessage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public abstract class BaseResponseMessage : BaseMessage
1313
/// Correlation ID that matches the original request's RequestId
1414
/// </summary>
1515
[Key(0)]
16-
public Guid RequestId { get; set; }
16+
public Guid RequestId { get; internal set; }
1717

1818
/// <summary>
1919
/// Indicates if the request was successful
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Cysharp.Threading.Tasks;
2+
using Insthync.SimpleNetworkManager.NET.Network;
3+
4+
namespace Insthync.SimpleNetworkManager.NET.Messages
5+
{
6+
internal interface IResponseMessageHandler : IMessageHandler
7+
{
8+
BaseMessage GetResponseMessageInstance();
9+
public UniTask HandleResponseDataAsync(BaseClientConnection clientConnection, object? data);
10+
}
11+
}

SimpleNetworkManager.NET/Services/MessageRouter.cs

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ public class MessageRouter
1616
{
1717
private readonly ILogger<MessageRouter> _logger;
1818
private readonly ConcurrentDictionary<uint, IMessageHandler> _handlers;
19+
private readonly ConcurrentDictionary<uint, IMessageHandler> _requestHandlers;
20+
private readonly ConcurrentDictionary<uint, IResponseMessageHandler> _responseHandlers;
1921

2022
public MessageRouter(ILogger<MessageRouter> logger)
2123
{
2224
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
2325
_handlers = new ConcurrentDictionary<uint, IMessageHandler>();
26+
_requestHandlers = new ConcurrentDictionary<uint, IMessageHandler>();
27+
_responseHandlers = new ConcurrentDictionary<uint, IResponseMessageHandler>();
2428
}
2529

2630
/// <summary>
@@ -52,6 +56,53 @@ public void RegisterHandler<T>(BaseMessageHandler<T> handler)
5256
}
5357
}
5458

59+
/// <summary>
60+
/// Registers a request message handler for a specific message type
61+
/// </summary>
62+
/// <typeparam name="TRequest">Type of request message the handler processes</typeparam>
63+
/// <typeparam name="TResponse">Type of response message the handler processes</typeparam>
64+
/// <param name="handler">Handler instance to register</param>
65+
/// <exception cref="ArgumentNullException">Thrown when handler is null</exception>
66+
public void RegisterHandler<TRequest, TResponse>(BaseRequestResponseMessageHandler<TRequest, TResponse> handler)
67+
where TRequest : BaseRequestMessage
68+
where TResponse : BaseResponseMessage
69+
{
70+
if (handler == null)
71+
throw new ArgumentNullException(nameof(handler));
72+
73+
// Get the request message type from the generic type parameter
74+
var requestInstance = handler.GetMessageInstance();
75+
var requestType = requestInstance.GetMessageType();
76+
77+
if (_requestHandlers.TryAdd(requestType, handler))
78+
{
79+
_logger.LogDebug("Registered handler for message type {MessageType} ({TypeName})",
80+
requestType, typeof(TRequest).Name);
81+
}
82+
else
83+
{
84+
_logger.LogWarning("Handler for message type {MessageType} ({TypeName}) already registered, replacing",
85+
requestType, typeof(TRequest).Name);
86+
_requestHandlers[requestType] = handler;
87+
}
88+
89+
// Get the response message type from the generic type parameter
90+
var responseInstance = handler.GetResponseMessageInstance();
91+
var responseType = responseInstance.GetMessageType();
92+
93+
if (_responseHandlers.TryAdd(responseType, handler))
94+
{
95+
_logger.LogDebug("Registered handler for message type {MessageType} ({TypeName})",
96+
responseType, typeof(TResponse).Name);
97+
}
98+
else
99+
{
100+
_logger.LogWarning("Handler for message type {MessageType} ({TypeName}) already registered, replacing",
101+
responseType, typeof(TResponse).Name);
102+
_responseHandlers[responseType] = handler;
103+
}
104+
}
105+
55106
/// <summary>
56107
/// Routes a message to the appropriate handler
57108
/// </summary>
@@ -67,16 +118,26 @@ public async UniTask RouteMessageAsync(BaseClientConnection clientConnection, by
67118
throw new ArgumentNullException(nameof(message));
68119

69120
var data = BaseMessage.ExtractMessageData(message, out var messageType);
70-
if (!_handlers.TryGetValue(messageType, out var handler))
121+
if (_handlers.TryGetValue(messageType, out var handler))
71122
{
72-
_logger.LogWarning("No handler registered for message type {MessageType} from client {ConnectionId}",
73-
messageType, clientConnection.ConnectionId);
74-
return;
123+
var messageInstance = handler.GetMessageInstance();
124+
var dataType = messageInstance.GetType();
125+
await handler.HandleDataAsync(clientConnection, MessagePackSerializer.Deserialize(messageInstance.GetType(), data, messageInstance.GetMessagePackOptions()));
75126
}
76127

77-
var messageInstance = handler.GetMessageInstance();
78-
var dataType = messageInstance.GetType();
79-
await handler.HandleDataAsync(clientConnection, MessagePackSerializer.Deserialize(messageInstance.GetType(), data, messageInstance.GetMessagePackOptions()));
128+
if (_requestHandlers.TryGetValue(messageType, out var requestHandler))
129+
{
130+
var messageInstance = requestHandler.GetMessageInstance();
131+
var dataType = messageInstance.GetType();
132+
await requestHandler.HandleDataAsync(clientConnection, MessagePackSerializer.Deserialize(messageInstance.GetType(), data, messageInstance.GetMessagePackOptions()));
133+
}
134+
135+
if (_responseHandlers.TryGetValue(messageType, out var responseHandler))
136+
{
137+
var messageInstance = responseHandler.GetMessageInstance();
138+
var dataType = messageInstance.GetType();
139+
await responseHandler.HandleResponseDataAsync(clientConnection, MessagePackSerializer.Deserialize(messageInstance.GetType(), data, messageInstance.GetMessagePackOptions()));
140+
}
80141
}
81142
}
82143
}

0 commit comments

Comments
 (0)