2025-04-15 11:15:22 +08:00
|
|
|
|
using Confluent.Kafka;
|
2025-04-17 13:35:08 +08:00
|
|
|
|
using JiShe.CollectBus.Common.Consts;
|
2025-04-17 14:39:14 +08:00
|
|
|
|
using JiShe.CollectBus.Common.Extensions;
|
2025-04-17 19:41:09 +08:00
|
|
|
|
using JiShe.CollectBus.Common.Helpers;
|
2025-04-16 09:54:21 +08:00
|
|
|
|
using JiShe.CollectBus.Kafka.AdminClient;
|
2025-04-15 11:15:22 +08:00
|
|
|
|
using JiShe.CollectBus.Kafka.Attributes;
|
|
|
|
|
|
using JiShe.CollectBus.Kafka.Consumer;
|
2025-04-19 00:30:58 +08:00
|
|
|
|
using JiShe.CollectBus.Kafka.Internal;
|
|
|
|
|
|
using JiShe.CollectBus.Kafka.Serialization;
|
2025-04-15 11:15:22 +08:00
|
|
|
|
using Microsoft.AspNetCore.Builder;
|
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
|
using Microsoft.Extensions.Hosting;
|
2025-04-15 15:49:22 +08:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
2025-04-17 14:39:14 +08:00
|
|
|
|
using Microsoft.Extensions.Options;
|
2025-04-19 00:30:58 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.ComponentModel;
|
2025-04-15 11:15:22 +08:00
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
|
|
|
|
|
namespace JiShe.CollectBus.Kafka
|
|
|
|
|
|
{
|
2025-04-21 10:17:40 +08:00
|
|
|
|
public static class KafkaSubscribeExtensions
|
2025-04-15 11:15:22 +08:00
|
|
|
|
{
|
2025-04-17 11:53:29 +08:00
|
|
|
|
|
2025-05-12 14:02:22 +08:00
|
|
|
|
private static long _threadCount = 0;
|
|
|
|
|
|
private static long _topicSubscribeCount = 0;
|
|
|
|
|
|
private static long _threadStartCount = 0;
|
|
|
|
|
|
|
2025-04-19 00:30:58 +08:00
|
|
|
|
public static void UseInitKafkaTopic(this IServiceProvider provider)
|
|
|
|
|
|
{
|
2025-04-17 14:39:14 +08:00
|
|
|
|
//初始化主题信息
|
|
|
|
|
|
var kafkaAdminClient = provider.GetRequiredService<IAdminClientService>();
|
|
|
|
|
|
var kafkaOptions = provider.GetRequiredService<IOptions<KafkaOptionConfig>>();
|
|
|
|
|
|
|
2025-04-21 10:17:40 +08:00
|
|
|
|
var topics = ProtocolConstExtensions.GetAllTopicNamesByIssued();
|
2025-04-17 14:39:14 +08:00
|
|
|
|
topics.AddRange(ProtocolConstExtensions.GetAllTopicNamesByReceived());
|
|
|
|
|
|
foreach (var item in topics)
|
|
|
|
|
|
{
|
|
|
|
|
|
kafkaAdminClient.CreateTopicAsync(item, kafkaOptions.Value.NumPartitions, kafkaOptions.Value.KafkaReplicationFactor).ConfigureAwait(false).GetAwaiter().GetResult();
|
|
|
|
|
|
}
|
2025-05-23 10:07:47 +08:00
|
|
|
|
|
2025-04-19 00:30:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加Kafka订阅
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void UseKafkaSubscribe(this IServiceProvider provider)
|
|
|
|
|
|
{
|
|
|
|
|
|
var lifetime = provider.GetRequiredService<IHostApplicationLifetime>();
|
|
|
|
|
|
var kafkaOptions = provider.GetRequiredService<IOptions<KafkaOptionConfig>>();
|
2025-04-18 09:28:48 +08:00
|
|
|
|
lifetime.ApplicationStarted.Register(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var logger = provider.GetRequiredService<ILogger<CollectBusKafkaModule>>();
|
2025-05-12 14:02:22 +08:00
|
|
|
|
//var threadCount = 0;
|
|
|
|
|
|
//var topicCount = 0;
|
2025-04-17 13:01:26 +08:00
|
|
|
|
var assemblyPath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(assemblyPath))
|
|
|
|
|
|
{
|
2025-05-12 14:02:22 +08:00
|
|
|
|
logger.LogWarning($"kafka订阅未能找到程序路径");
|
2025-04-17 13:01:26 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
var dllFiles = Directory.GetFiles(assemblyPath, "*.dll");
|
|
|
|
|
|
foreach (var file in dllFiles)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 跳过已加载的程序集
|
|
|
|
|
|
var assemblyName = AssemblyName.GetAssemblyName(file);
|
|
|
|
|
|
var existingAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
|
|
|
|
|
.FirstOrDefault(a => a.GetName().FullName == assemblyName.FullName);
|
|
|
|
|
|
var assembly = existingAssembly ?? Assembly.LoadFrom(file);
|
|
|
|
|
|
// 实现IKafkaSubscribe接口
|
|
|
|
|
|
var subscribeTypes = assembly.GetTypes().Where(type =>
|
2025-04-18 09:28:48 +08:00
|
|
|
|
typeof(IKafkaSubscribe).IsAssignableFrom(type) &&
|
2025-05-23 10:07:47 +08:00
|
|
|
|
!type.IsAbstract && !type.IsInterface).ToList();
|
2025-04-18 09:28:48 +08:00
|
|
|
|
if (subscribeTypes.Count == 0)
|
2025-04-17 13:01:26 +08:00
|
|
|
|
continue;
|
2025-04-18 09:28:48 +08:00
|
|
|
|
|
2025-05-12 14:02:22 +08:00
|
|
|
|
// 并行处理
|
|
|
|
|
|
Parallel.ForEach(subscribeTypes, subscribeType =>
|
2025-04-17 13:01:26 +08:00
|
|
|
|
{
|
|
|
|
|
|
var subscribes = provider.GetServices(subscribeType).ToList();
|
2025-05-23 10:07:47 +08:00
|
|
|
|
Parallel.ForEach(subscribes, subscribe =>
|
2025-04-17 13:01:26 +08:00
|
|
|
|
{
|
2025-04-18 09:28:48 +08:00
|
|
|
|
if (subscribe != null)
|
2025-04-17 13:01:26 +08:00
|
|
|
|
{
|
2025-04-18 09:28:48 +08:00
|
|
|
|
Tuple<int, int> tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value);
|
2025-05-12 14:02:22 +08:00
|
|
|
|
//threadCount += tuple.Item1;
|
|
|
|
|
|
//topicCount += tuple.Item2;
|
2025-04-17 13:01:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-05-12 14:02:22 +08:00
|
|
|
|
});
|
|
|
|
|
|
//foreach (var subscribeType in subscribeTypes)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var subscribes = provider.GetServices(subscribeType).ToList();
|
|
|
|
|
|
// subscribes.ForEach(subscribe =>
|
|
|
|
|
|
// {
|
|
|
|
|
|
// if (subscribe != null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Tuple<int, int> tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value);
|
|
|
|
|
|
// threadCount += tuple.Item1;
|
|
|
|
|
|
// topicCount += tuple.Item2;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
//}
|
2025-04-17 13:01:26 +08:00
|
|
|
|
}
|
2025-05-12 14:02:22 +08:00
|
|
|
|
logger.LogWarning($"kafka订阅主题:{_topicSubscribeCount}数,共启动:{_threadCount}线程");
|
2025-05-23 10:07:47 +08:00
|
|
|
|
|
|
|
|
|
|
var kafkaTaskScheduler = provider.GetRequiredService<KafkaTaskScheduler>();
|
|
|
|
|
|
kafkaTaskScheduler.ExceptionEvent += (ex) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, "Kafka任务调度异常");
|
|
|
|
|
|
};
|
2025-05-23 14:01:33 +08:00
|
|
|
|
//logger.LogWarning($"kafka订阅工作线程数:{kafkaTaskScheduler.WorkerThreads},队列任务:{kafkaTaskScheduler.QueuedTasks}数");
|
|
|
|
|
|
//
|
2025-05-23 10:07:47 +08:00
|
|
|
|
// 订阅调度监控测试可打开
|
|
|
|
|
|
//_ = Task.Factory.StartNew(async () =>
|
|
|
|
|
|
// {
|
|
|
|
|
|
// while (true)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// logger.LogWarning($"kafka订阅工作线程数:{kafkaTaskScheduler.WorkerThreads},队列任务:{kafkaTaskScheduler.QueuedTasks}数");
|
|
|
|
|
|
// await Task.Delay(TimeSpan.FromSeconds(5));
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
2025-04-18 09:28:48 +08:00
|
|
|
|
});
|
2025-05-23 10:07:47 +08:00
|
|
|
|
|
2025-04-17 13:01:26 +08:00
|
|
|
|
}
|
2025-04-17 11:53:29 +08:00
|
|
|
|
|
2025-04-21 10:17:40 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加Kafka订阅
|
|
|
|
|
|
/// </summary>
|
2025-04-18 09:28:48 +08:00
|
|
|
|
public static void UseKafkaSubscribersAsync(this IApplicationBuilder app, Assembly assembly)
|
|
|
|
|
|
{
|
|
|
|
|
|
var provider = app.ApplicationServices;
|
|
|
|
|
|
var lifetime = provider.GetRequiredService<IHostApplicationLifetime>();
|
|
|
|
|
|
var kafkaOptions = provider.GetRequiredService<IOptions<KafkaOptionConfig>>();
|
|
|
|
|
|
lifetime.ApplicationStarted.Register(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var logger = provider.GetRequiredService<ILogger<CollectBusKafkaModule>>();
|
|
|
|
|
|
int threadCount = 0;
|
|
|
|
|
|
int topicCount = 0;
|
|
|
|
|
|
var subscribeTypes = assembly.GetTypes()
|
|
|
|
|
|
.Where(t => typeof(IKafkaSubscribe).IsAssignableFrom(t))
|
|
|
|
|
|
.ToList();
|
2025-04-18 08:22:52 +08:00
|
|
|
|
|
2025-04-18 09:28:48 +08:00
|
|
|
|
if (subscribeTypes.Count == 0) return;
|
2025-05-23 10:07:47 +08:00
|
|
|
|
|
|
|
|
|
|
Parallel.ForEach(subscribeTypes, subscribeType =>
|
2025-04-18 09:28:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
var subscribes = provider.GetServices(subscribeType).ToList();
|
2025-05-23 10:07:47 +08:00
|
|
|
|
Parallel.ForEach(subscribes, subscribe =>
|
2025-04-18 09:28:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (subscribe != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Tuple<int, int> tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value);
|
2025-05-23 10:07:47 +08:00
|
|
|
|
//threadCount += tuple.Item1;
|
|
|
|
|
|
//topicCount += tuple.Item2;
|
2025-04-18 09:28:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-05-23 10:07:47 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
//foreach (var subscribeType in subscribeTypes)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var subscribes = provider.GetServices(subscribeType).ToList();
|
|
|
|
|
|
// subscribes.ForEach(subscribe =>
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
|
|
|
|
// if (subscribe != null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Tuple<int, int> tuple = BuildKafkaSubscribe(subscribe, provider, logger, kafkaOptions.Value);
|
|
|
|
|
|
// threadCount += tuple.Item1;
|
|
|
|
|
|
// topicCount += tuple.Item2;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
|
|
|
|
|
//}
|
2025-04-18 09:28:48 +08:00
|
|
|
|
logger.LogInformation($"kafka订阅主题:{topicCount}数,共启动:{threadCount}线程");
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-04-15 11:15:22 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 构建Kafka订阅
|
|
|
|
|
|
/// </summary>
|
2025-04-19 00:30:58 +08:00
|
|
|
|
private static Tuple<int, int> BuildKafkaSubscribe(object subscribe, IServiceProvider provider, ILogger<CollectBusKafkaModule> logger, KafkaOptionConfig kafkaOptionConfig)
|
2025-04-15 11:15:22 +08:00
|
|
|
|
{
|
2025-04-15 15:49:22 +08:00
|
|
|
|
var subscribedMethods = subscribe.GetType().GetMethods()
|
|
|
|
|
|
.Select(m => new { Method = m, Attribute = m.GetCustomAttribute<KafkaSubscribeAttribute>() })
|
|
|
|
|
|
.Where(x => x.Attribute != null)
|
|
|
|
|
|
.ToArray();
|
2025-04-17 14:39:14 +08:00
|
|
|
|
//var configuration = provider.GetRequiredService<IConfiguration>();
|
2025-04-16 09:54:21 +08:00
|
|
|
|
int threadCount = 0;
|
2025-04-19 00:30:58 +08:00
|
|
|
|
|
2025-05-12 14:02:22 +08:00
|
|
|
|
Parallel.ForEach(subscribedMethods, sub =>
|
2025-04-15 11:15:22 +08:00
|
|
|
|
{
|
2025-05-12 14:02:22 +08:00
|
|
|
|
Interlocked.Increment(ref _topicSubscribeCount);
|
2025-05-23 10:07:47 +08:00
|
|
|
|
var adminClientService = provider.GetRequiredService<IAdminClientService>();
|
2025-04-17 19:41:09 +08:00
|
|
|
|
int topicCount = adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic);
|
2025-05-23 10:07:47 +08:00
|
|
|
|
// 可以根据配置文件TaskThreadCount来配置线程数
|
|
|
|
|
|
int partitionCount = sub.Attribute!.TaskCount == -1 ? (kafkaOptionConfig.TaskThreadCount==-1? topicCount: kafkaOptionConfig.TaskThreadCount) : sub.Attribute!.TaskCount;// kafkaOptionConfig.NumPartitions;
|
2025-04-19 00:30:58 +08:00
|
|
|
|
partitionCount = partitionCount > topicCount ? topicCount : partitionCount;
|
2025-04-30 10:35:26 +08:00
|
|
|
|
//partitionCount = sub.Attribute!.TaskCount == -1 ? adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic) : sub.Attribute!.TaskCount;
|
2025-04-16 09:54:21 +08:00
|
|
|
|
if (partitionCount <= 0)
|
|
|
|
|
|
partitionCount = 1;
|
2025-05-12 14:02:22 +08:00
|
|
|
|
Parallel.For(0,partitionCount, async (partition) =>
|
2025-04-16 09:54:21 +08:00
|
|
|
|
{
|
2025-05-12 14:02:22 +08:00
|
|
|
|
Interlocked.Increment(ref _threadCount);
|
|
|
|
|
|
//Task.Run(() => StartConsumerAsync(provider, sub.Attribute!, sub.Method, subscribe, logger));
|
|
|
|
|
|
//threadCount++;
|
|
|
|
|
|
await StartConsumerAsync(provider, sub.Attribute!, sub.Method, subscribe, logger);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
//foreach (var sub in subscribedMethods)
|
|
|
|
|
|
//{
|
2025-05-23 10:07:47 +08:00
|
|
|
|
//// //int partitionCount = sub.Attribute!.TaskCount==-1?3: sub.Attribute!.TaskCount;// kafkaOptionConfig.NumPartitions;
|
2025-05-12 14:02:22 +08:00
|
|
|
|
// var adminClientService = provider.GetRequiredService<IAdminClientService>();
|
|
|
|
|
|
|
|
|
|
|
|
// int topicCount = adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic);
|
|
|
|
|
|
|
|
|
|
|
|
// int partitionCount = sub.Attribute!.TaskCount == -1 ? topicCount : sub.Attribute!.TaskCount;// kafkaOptionConfig.NumPartitions;
|
|
|
|
|
|
|
|
|
|
|
|
// partitionCount = partitionCount > topicCount ? topicCount : partitionCount;
|
|
|
|
|
|
// //partitionCount = sub.Attribute!.TaskCount == -1 ? adminClientService.GetTopicPartitionsNum(sub.Attribute!.Topic) : sub.Attribute!.TaskCount;
|
|
|
|
|
|
// if (partitionCount <= 0)
|
|
|
|
|
|
// partitionCount = 1;
|
|
|
|
|
|
// for (int i = 0; i < partitionCount; i++)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// //if (sub.Attribute!.Topic == ProtocolConst.SubscriberLoginReceivedEventName)
|
|
|
|
|
|
// Task.Run(() => StartConsumerAsync(provider, sub.Attribute!, sub.Method, subscribe, logger));
|
|
|
|
|
|
// threadCount++;
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
2025-04-18 09:28:48 +08:00
|
|
|
|
return Tuple.Create(threadCount, subscribedMethods.Length);
|
2025-04-15 11:15:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 启动后台消费线程
|
|
|
|
|
|
/// </summary>
|
2025-04-19 00:30:58 +08:00
|
|
|
|
private static async Task StartConsumerAsync(IServiceProvider provider, KafkaSubscribeAttribute attr, MethodInfo method, object subscribe, ILogger<CollectBusKafkaModule> logger)
|
2025-04-15 11:15:22 +08:00
|
|
|
|
{
|
2025-04-18 08:22:52 +08:00
|
|
|
|
var consumerService = provider.GetRequiredService<IConsumerService>();
|
2025-05-23 14:01:33 +08:00
|
|
|
|
|
2025-04-18 08:22:52 +08:00
|
|
|
|
if (attr.EnableBatch)
|
|
|
|
|
|
{
|
2025-05-12 14:02:22 +08:00
|
|
|
|
Interlocked.Increment(ref _threadStartCount);
|
|
|
|
|
|
logger.LogInformation($"kafka开启线程消费:{_threadStartCount}");
|
2025-04-19 00:30:58 +08:00
|
|
|
|
await consumerService.SubscribeBatchAsync<dynamic>(attr.Topic, async (message) =>
|
2025-04-15 11:15:22 +08:00
|
|
|
|
{
|
2025-04-18 08:22:52 +08:00
|
|
|
|
try
|
2025-04-17 13:56:17 +08:00
|
|
|
|
{
|
2025-04-18 08:23:31 +08:00
|
|
|
|
#if DEBUG
|
2025-04-19 00:30:58 +08:00
|
|
|
|
logger.LogInformation($"kafka批量消费消息:{message.Serialize()}");
|
2025-04-18 08:23:31 +08:00
|
|
|
|
#endif
|
2025-04-18 08:22:52 +08:00
|
|
|
|
// 处理消息
|
|
|
|
|
|
return await ProcessMessageAsync(message.ToList(), method, subscribe);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (ConsumeException ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 处理消费错误
|
|
|
|
|
|
logger.LogError($"kafka批量消费异常:{ex.Message}");
|
|
|
|
|
|
}
|
2025-05-14 17:41:39 +08:00
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 处理消费错误
|
|
|
|
|
|
logger.LogError($"kafka批量消费异常:{ex.Message}");
|
|
|
|
|
|
}
|
2025-04-18 08:22:52 +08:00
|
|
|
|
return await Task.FromResult(false);
|
|
|
|
|
|
}, attr.GroupId, attr.BatchSize, attr.BatchTimeout);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-05-12 14:02:22 +08:00
|
|
|
|
Interlocked.Increment(ref _threadStartCount);
|
|
|
|
|
|
logger.LogInformation($"kafka开启线程消费:{_threadStartCount}");
|
2025-04-19 00:30:58 +08:00
|
|
|
|
await consumerService.SubscribeAsync<dynamic>(attr.Topic, async (message) =>
|
2025-04-15 11:15:22 +08:00
|
|
|
|
{
|
2025-04-18 08:22:52 +08:00
|
|
|
|
try
|
2025-04-17 13:56:17 +08:00
|
|
|
|
{
|
2025-04-18 08:22:52 +08:00
|
|
|
|
#if DEBUG
|
|
|
|
|
|
logger.LogInformation($"kafka消费消息:{message}");
|
|
|
|
|
|
#endif
|
|
|
|
|
|
// 处理消息
|
|
|
|
|
|
return await ProcessMessageAsync(new List<object>() { message }, method, subscribe);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (ConsumeException ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 处理消费错误
|
|
|
|
|
|
logger.LogError($"kafka消费异常:{ex.Message}");
|
|
|
|
|
|
}
|
2025-05-14 17:41:39 +08:00
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 处理消费错误
|
|
|
|
|
|
logger.LogError($"kafka批量消费异常:{ex.Message}");
|
|
|
|
|
|
}
|
2025-04-18 08:22:52 +08:00
|
|
|
|
return await Task.FromResult(false);
|
|
|
|
|
|
}, attr.GroupId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-15 11:15:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-15 18:03:51 +08:00
|
|
|
|
|
2025-04-15 15:49:22 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 处理消息
|
|
|
|
|
|
/// </summary>
|
2025-04-19 00:30:58 +08:00
|
|
|
|
private static async Task<bool> ProcessMessageAsync(List<dynamic> messages, MethodInfo method, object subscribe)
|
2025-04-15 11:15:22 +08:00
|
|
|
|
{
|
2025-05-14 17:41:39 +08:00
|
|
|
|
try
|
2025-04-15 18:03:51 +08:00
|
|
|
|
{
|
2025-05-14 17:41:39 +08:00
|
|
|
|
var parameters = method.GetParameters();
|
|
|
|
|
|
bool isGenericTask = method.ReturnType.IsGenericType
|
|
|
|
|
|
&& method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>);
|
|
|
|
|
|
bool existParameters = parameters.Length > 0;
|
|
|
|
|
|
object[]? executeParameters = null;
|
|
|
|
|
|
|
|
|
|
|
|
if (existParameters)
|
2025-04-19 00:30:58 +08:00
|
|
|
|
{
|
2025-05-14 17:41:39 +08:00
|
|
|
|
IList? list = null;
|
|
|
|
|
|
Tuple<Type, Type?> tuple = method.GetParameterTypeInfo();
|
|
|
|
|
|
bool isEnumerable = false;
|
|
|
|
|
|
if (tuple.Item2 != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Type listType = typeof(List<>).MakeGenericType(tuple.Item2);
|
|
|
|
|
|
list = (IList)Activator.CreateInstance(listType)!;
|
|
|
|
|
|
isEnumerable = tuple.Item2.IsConvertType();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
isEnumerable = tuple.Item1.IsConvertType();
|
|
|
|
|
|
}
|
|
|
|
|
|
#region 暂时
|
|
|
|
|
|
//foreach (var msg in messages)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// if (tuple.Item2 != null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// if (isEnumerable)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var parameterType = parameters[0].ParameterType;
|
|
|
|
|
|
// var data=messages?.Serialize().Deserialize(parameterType);
|
|
|
|
|
|
// messageObj = data!=null? new[] { data }:null;
|
|
|
|
|
|
// break;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// else
|
|
|
|
|
|
// {
|
|
|
|
|
|
// // 集合类型
|
|
|
|
|
|
// var data = msg?.Serialize().Deserialize(tuple.Item2) /*isEnumerable ? Convert.ChangeType(msg, tuple.Item2) : msg?.Serialize().Deserialize(tuple.Item2)*/;
|
|
|
|
|
|
// if (data != null)
|
|
|
|
|
|
// list?.Add(data);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
// else
|
|
|
|
|
|
// {
|
|
|
|
|
|
// // (dynamic)Convert.ChangeType(msg, tuple.Item1)
|
|
|
|
|
|
// using (var stream = new MemoryStream(msg))
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var data1= System.Text.Json.JsonSerializer.Deserialize(stream, tuple.Item1);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// var data = isEnumerable ? System.Text.Json.JsonSerializer.Deserialize(msg, tuple.Item1): msg?.ToString()?.Deserialize(tuple.Item1);
|
|
|
|
|
|
// if (data != null)
|
|
|
|
|
|
// messageObj = new[] { data };
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
//if (tuple.Item2 != null && list != null && list.Count > 0)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// messageObj = new[] { list };
|
|
|
|
|
|
//}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
var parameterDescriptors = method.GetParameters();
|
|
|
|
|
|
executeParameters = new object?[parameterDescriptors.Length];
|
|
|
|
|
|
for (var i = 0; i < parameterDescriptors.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in messages)
|
2025-04-19 00:30:58 +08:00
|
|
|
|
{
|
2025-05-14 17:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
object? tempParameter = null;
|
|
|
|
|
|
var parameterDescriptor = parameterDescriptors[i];
|
|
|
|
|
|
if (KafkaSerialization.IsJsonType(item))
|
2025-04-19 00:30:58 +08:00
|
|
|
|
{
|
2025-05-14 17:41:39 +08:00
|
|
|
|
tempParameter = KafkaSerialization.Deserialize(item, tuple.Item2 != null ? tuple.Item2 : parameterDescriptor.ParameterType);
|
2025-04-19 00:30:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-05-14 17:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
var converter = TypeDescriptor.GetConverter(parameterDescriptor.ParameterType);
|
|
|
|
|
|
if (converter.CanConvertFrom(item.GetType()))
|
|
|
|
|
|
{
|
|
|
|
|
|
tempParameter = converter.ConvertFrom(item);
|
|
|
|
|
|
}
|
2025-04-19 00:30:58 +08:00
|
|
|
|
else
|
2025-05-14 17:41:39 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (parameterDescriptor.ParameterType.IsInstanceOfType(item))
|
|
|
|
|
|
tempParameter = item;
|
|
|
|
|
|
else
|
|
|
|
|
|
tempParameter = Convert.ChangeType(item, parameterDescriptor.ParameterType);
|
|
|
|
|
|
}
|
2025-04-19 00:30:58 +08:00
|
|
|
|
}
|
2025-05-14 17:41:39 +08:00
|
|
|
|
if (tuple.Item2 == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
executeParameters[i] = tempParameter;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
list.Add(tempParameter);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-19 00:30:58 +08:00
|
|
|
|
}
|
2025-05-14 17:41:39 +08:00
|
|
|
|
if (list != null && list.Count > 0)
|
|
|
|
|
|
executeParameters[i] = list;
|
2025-04-19 00:30:58 +08:00
|
|
|
|
}
|
2025-04-17 19:41:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-14 17:41:39 +08:00
|
|
|
|
var result = method.Invoke(subscribe, executeParameters);
|
|
|
|
|
|
if (result is Task<ISubscribeAck> genericTask)
|
|
|
|
|
|
{
|
|
|
|
|
|
await genericTask.ConfigureAwait(false);
|
|
|
|
|
|
return genericTask.Result.Ack;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (result is Task nonGenericTask)
|
|
|
|
|
|
{
|
|
|
|
|
|
await nonGenericTask.ConfigureAwait(false);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (result is ISubscribeAck ackResult)
|
|
|
|
|
|
{
|
|
|
|
|
|
return ackResult.Ack;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
2025-04-15 11:15:22 +08:00
|
|
|
|
}
|
2025-05-14 17:41:39 +08:00
|
|
|
|
catch (Exception ex)
|
2025-04-17 18:08:27 +08:00
|
|
|
|
{
|
2025-05-14 17:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
throw;
|
2025-04-17 18:08:27 +08:00
|
|
|
|
}
|
2025-04-15 11:15:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-19 00:30:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-04-15 11:15:22 +08:00
|
|
|
|
}
|