public void Subscribe(string productId, string topic, Func<BasicDeliverEventArgs, bool> action, SubscribeOptions options = null) { this.Subscribe_internal<object>(productId, topic, false, (body, message) => action(message), options); }
void Subscribe_internal<T>(string productId, string topic, bool hasReloveBody, Func<T, BasicDeliverEventArgs, bool> action, SubscribeOptions options = null) { options = options ?? SubscribeOptions.Default; var queueName = topic; var channel = _CacheManager.GetChannel(productId, topic, hasSub: true); if (options.Model == MessageModel.Broadcasting) { var ip = Aquirrel.Tools.LocalIp.GetLocalIPV4() ?? System.Net.Dns.GetHostName(); var fanoutQueueName = ip + "." + productId + "." + topic + "." + DateTime.UtcNow.Ticks; channel.QueueDeclare(queue: fanoutQueueName); channel.QueueBind(fanoutQueueName, topic, "", null); queueName = fanoutQueueName; } var consumer = new EventingBasicConsumer(channel); consumer.Shutdown += (obj, ea) => { _logger.LogError($"eventbus.consumer.shutdown;{Environment.NewLine}{productId}-{topic}-{ea.ToJson()}"); }; channel.BasicQos(0, (ushort)options.BasicQos, false); var tx = typeof(T) == typeof(string); consumer.Received += (obj, ea) => { var isSuccess = false; try { if (hasReloveBody) { var body = Encoding.UTF8.GetString(ea.Body); if (tx) isSuccess = action((T)((object)body), ea); else { var msg = body.ToJson<T>(); isSuccess = action(msg, ea); } } else { isSuccess = action(default(T), ea); } } catch (Exception ex) { object mid = null; ea.BasicProperties?.Headers.TryGetValue("mid", out mid); _logger.LogError(ex, $"eventbus.subscribe.consumer.exception;{Environment.NewLine}{productId}-{topic}-" + $"{{mid:{mid},RoutingKey:{ea.RoutingKey},ConsumerTag:{ea.ConsumerTag},DeliveryTag:{ea.DeliveryTag},Exchange:{ea.Exchange}}}"); } finally { try { if (isSuccess) { consumer.Model.BasicAck(ea.DeliveryTag, false); } else { consumer.Model.BasicNack(ea.DeliveryTag, false, options.FailMesaageReQueue); } } catch { } } }; _logger.LogInformation($"eventbus.subscribe;{productId}-{queueName}"); channel.BasicConsume(queueName, false, consumer); }
/// <summary> /// 消费者订阅 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="productId"></param> /// <param name="topic">集群消费:queuename;广播消费:exchange</param> /// <param name="action"></param> /// <param name="options"></param> public void Subscribe<T>(string productId, string topic, Func<T, bool> action, SubscribeOptions options = null) { this.Subscribe_internal<T>(productId, topic, true, (body, message) => action(body), options); }