/// <summary> /// Triggers event and sends message to subscribers /// </summary> protected void Trigger(object model) { try { if (_subscribers.Count == 0) { return; } HorseMessage message = new HorseMessage(MessageType.Event, Target); message.SetSource(Name); if (model != null) { message.Serialize(model, _server.MessageContentSerializer); } byte[] data = HmqWriter.Create(message); List <MqClient> removing = null; lock (_subscribers) foreach (MqClient subscriber in _subscribers) { //if client is disconnected, add it into removing list if (!subscriber.IsConnected) { //removing list is created when it's needed if (removing == null) { removing = new List <MqClient>(); } removing.Add(subscriber); } else { _ = subscriber.SendAsync(data); } } //if there are some removing clients from subscribers list, remove them if (removing != null) { lock (_subscribers) foreach (MqClient remove in removing) { _subscribers.Remove(remove); } } } catch (Exception e) { _server.SendError("EVENT_TRIGGER", e, $"Name:{Name}, Type:{GetType().Name}"); } }
/// <summary> /// Called when a acknowledge message is received from the client /// </summary> internal async Task AcknowledgeDelivered(MqClient from, HorseMessage deliveryMessage) { try { if (!IsInitialized) { return; } MessageDelivery delivery = TimeKeeper.FindAndRemoveDelivery(from, deliveryMessage.MessageId); //when server and consumer are in pc, //sometimes consumer sends ack before server start to follow ack of the message //that happens when ack message is arrived in less than 0.01ms //in that situation, server can't find the delivery with FindAndRemoveDelivery, it returns null //so we need to check it again after a few milliseconds if (delivery == null) { await Task.Delay(1); delivery = TimeKeeper.FindAndRemoveDelivery(from, deliveryMessage.MessageId); //try again if (delivery == null) { await Task.Delay(3); delivery = TimeKeeper.FindAndRemoveDelivery(from, deliveryMessage.MessageId); } } bool success = !(deliveryMessage.HasHeader && deliveryMessage.Headers.Any(x => x.Key.Equals(HorseHeaders.NEGATIVE_ACKNOWLEDGE_REASON, StringComparison.InvariantCultureIgnoreCase))); // ReSharper disable once ConditionIsAlwaysTrueOrFalse (it's possible, resharper doesn't work properly in here) if (delivery != null) { if (delivery.Receiver != null && delivery.Message == delivery.Receiver.CurrentlyProcessing) { delivery.Receiver.CurrentlyProcessing = null; } delivery.MarkAsAcknowledged(success); } if (success) { Info.AddAcknowledge(); } else { Info.AddNegativeAcknowledge(); } Decision decision = await DeliveryHandler.AcknowledgeReceived(this, deliveryMessage, delivery, success); // ReSharper disable once ConditionIsAlwaysTrueOrFalse (it's possible, resharper doesn't work properly in here) if (delivery != null) { if (Options.HideClientNames) { deliveryMessage.SetSource(null); } await ApplyDecision(decision, delivery.Message, deliveryMessage); } ReleaseAcknowledgeLock(true); } catch (Exception e) { Server.SendError("QUEUE_ACK_RECEIVED", e, $"QueueName:{Name}, MessageId:{deliveryMessage.MessageId}"); } }