using Confluent.Kafka;
using JiShe.CollectBus.Kafka.Attributes;
using JiShe.CollectBus.Kafka.Consumer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace JiShe.CollectBus.Kafka
{
public static class KafkaSubcribesExtensions
{
///
/// 添加Kafka订阅
///
///
///
public static void UseKafkaSubscribers(this IApplicationBuilder app, Assembly assembly)
{
var subscribeTypes = assembly.GetTypes()
.Where(t => typeof(IKafkaSubscribe).IsAssignableFrom(t))
.ToList();
if (subscribeTypes.Count == 0) return;
var provider = app.ApplicationServices;
var lifetime = provider.GetRequiredService();
lifetime.ApplicationStarted.Register(() =>
{
foreach (var subscribeType in subscribeTypes)
{
var subscribes = provider.GetServices(subscribeType).ToList();
subscribes.ForEach(subscribe => {
if(subscribe is IKafkaSubscribe)
{
BuildKafkaSubscriber(subscribe, provider);
}
});
}
});
}
///
/// 构建Kafka订阅
///
///
///
private static void BuildKafkaSubscriber(object subscribe, IServiceProvider provider)
{
var methods = subscribe.GetType().GetMethods();
foreach (var method in methods)
{
var attr = method.GetCustomAttribute();
if (attr == null) continue;
// 启动后台消费线程
Task.Run(() => StartConsumerAsync(provider, attr, method, subscribe));
}
}
///
/// 启动后台消费线程
///
///
///
///
///
///
private static async Task StartConsumerAsync(IServiceProvider provider, KafkaSubscribeAttribute attr,MethodInfo method, object subscribe)
{
var consumerService = provider.GetRequiredService>();
await consumerService.SubscribeAsync(attr.Topics, async (key, message) =>
{
try
{
if (string.IsNullOrEmpty(message))
await Task.CompletedTask ;
// 处理消息
await ProcessMessageAsync(message, method, subscribe);
}
catch (ConsumeException ex)
{
// 处理消费错误
throw;
}
});
}
private static async Task ProcessMessageAsync(string message, MethodInfo method, object subscribe)
{
var parameters = method.GetParameters();
if (parameters.Length != 1) return;
var paramType = parameters[0].ParameterType;
var messageObj = paramType == typeof(string)
? message
: JsonConvert.DeserializeObject(message, paramType);
if (method.ReturnType == typeof(Task))
{
await (Task)method.Invoke(subscribe, new[] { messageObj })!;
}
else
{
method.Invoke(subscribe, new[] { messageObj });
}
}
}
}