feat: init all packetHandler once & reuse
All checks were successful
Test if Server can be built / build-server (push) Successful in 24s

This commit is contained in:
Timothy Schenk 2023-08-14 21:07:15 +02:00
parent 63c29f21df
commit 010f05c565

View file

@ -1,13 +1,14 @@
namespace Server.Services; namespace Server.Services;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Reflection; using System.Reflection;
using DotNext.Collections.Generic;
using MassTransit.Internals; using MassTransit.Internals;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.VisualBasic.CompilerServices; using Microsoft.VisualBasic.CompilerServices;
using Newtonsoft.Json;
using PacketHandlers; using PacketHandlers;
using Packets; using Packets;
using static DotNext.Metaprogramming.CodeGenerator; using static DotNext.Metaprogramming.CodeGenerator;
@ -17,8 +18,12 @@ public class PacketDistributorService : IHostedService
{ {
private readonly ConcurrentQueue<RawPacket> concurrentQueue; private readonly ConcurrentQueue<RawPacket> concurrentQueue;
private readonly ILogger<PacketDistributorService> logger; private readonly ILogger<PacketDistributorService> logger;
private readonly Dictionary<OperationCode, Type> packetHandlers; private readonly ConcurrentDictionary<OperationCode, object> packetHandlersInstantiation;
private readonly Dictionary<OperationCode, Func<byte[], IPacket>> deserializationMap;
private readonly
ImmutableDictionary<OperationCode,
Func<byte[], IPacket>> deserializationMap;
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;
public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider) public PacketDistributorService(ILogger<PacketDistributorService> logger, IServiceProvider serviceProvider)
@ -26,29 +31,38 @@ public class PacketDistributorService : IHostedService
this.concurrentQueue = new ConcurrentQueue<RawPacket>(); this.concurrentQueue = new ConcurrentQueue<RawPacket>();
this.logger = logger; this.logger = logger;
this.serviceProvider = serviceProvider; this.serviceProvider = serviceProvider;
this.packetHandlers = new Dictionary<OperationCode, Type>(); var tempDeserializationMap =
this.deserializationMap = new Dictionary<OperationCode, Func<byte[], IPacket>>(); new Dictionary<OperationCode, Func<byte[], IPacket>>();
var executingAssembly = Assembly.GetExecutingAssembly(); var executingAssembly = Assembly.GetExecutingAssembly();
var packetsTypes = this.GetPacketsWithId(executingAssembly); var packetsTypes = this.GetPacketsWithId(executingAssembly);
this.packetHandlers = this.GetAllPacketHandlersWithId(executingAssembly); var packetHandlers = this.GetAllPacketHandlersWithId(executingAssembly);
this.packetHandlersInstantiation = new ConcurrentDictionary<OperationCode, object>();
packetHandlers.ForEach(x =>
{
var packetHandler =
ActivatorUtilities.GetServiceOrCreateInstance(this.serviceProvider,
x.Value);
this.packetHandlersInstantiation.TryAdd(x.Key, packetHandler);
});
foreach (var packetsType in packetsTypes) foreach (var packetsType in packetsTypes)
{ {
var lambda = Lambda<Func<byte[], IPacket>>(fun => var lambda = Lambda<Func<byte[], IPacket>>(fun =>
{ {
var arg = fun[0]; var argPacketData = fun[0];
var newPacket = packetsType.Value.New(); var newPacket = packetsType.Value.New();
var packetVariable = DeclareVariable(packetsType.Value, "packet"); var packetVariable = DeclareVariable(packetsType.Value, "packet");
Assign(packetVariable, newPacket); Assign(packetVariable, newPacket);
Call(packetVariable, nameof(IPacket.Deserialize), arg); Call(packetVariable, nameof(IPacket.Deserialize), argPacketData);
Return(packetVariable); Return(packetVariable);
}).Compile(); }).Compile();
logger.LogInformation("Packet creation function created for {Opcode}", packetsType.Key); logger.LogInformation("Packet creation function created for {Opcode}", packetsType.Key);
this.deserializationMap.Add(packetsType.Key, lambda); tempDeserializationMap.Add(packetsType.Key, lambda);
} }
this.deserializationMap = tempDeserializationMap.ToImmutableDictionary();
} }
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
@ -81,7 +95,8 @@ public class PacketDistributorService : IHostedService
t is { IsClass: true, IsAbstract: false } && t t is { IsClass: true, IsAbstract: false } && t
.GetInterfaces().Any(i => .GetInterfaces().Any(i =>
i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<>))).ToDictionary(type => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPacketHandler<>))).ToDictionary(type =>
type.GetInterfaces().First(t =>t is { IsGenericType: true} && t.GetGenericTypeDefinition() == typeof(IPacketHandler<>)) type.GetInterfaces().First(t =>
t is { IsGenericType: true } && t.GetGenericTypeDefinition() == typeof(IPacketHandler<>))
.GetGenericArguments().First().GetCustomAttribute<PacketIdAttribute>()!.Code); .GetGenericArguments().First().GetCustomAttribute<PacketIdAttribute>()!.Code);
if (packetHandlersWithId is not { Count: 0 }) if (packetHandlersWithId is not { Count: 0 })
@ -126,12 +141,10 @@ public class PacketDistributorService : IHostedService
} }
var packet = this.deserializationMap[item.OperationCode](item.MessageBody); var packet = this.deserializationMap[item.OperationCode](item.MessageBody);
var packetHandler = this.packetHandlersInstantiation[item.OperationCode].GetType().GetMethod("HandleAsync")
ActivatorUtilities.GetServiceOrCreateInstance(this.serviceProvider, ?.Invoke(this.packetHandlersInstantiation[item.OperationCode], new object[] { packet, item.Session });
this.packetHandlers[item.OperationCode]);
packetHandler.GetType().GetMethod("HandleAsync") //this.logger.LogDebug("Packet data {PacketData}", JsonConvert.SerializeObject(packet));
?.Invoke(packetHandler, new object[] { packet, item.Session });
this.logger.LogDebug("Packet data {PacketData}", JsonConvert.SerializeObject(packet));
this.logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} has finished", this.logger.LogTrace("[{TempId}] Packet with ID: {MessageOperationCode} has finished",
item.Session.Id, item.Session.Id,
item.OperationCode); item.OperationCode);