/// <summary> /// Pushes a message into the queue. /// </summary> internal async Task <PushResult> Push(QueueMessage message, MqClient sender) { if (Status == QueueStatus.Stopped) { return(PushResult.StatusNotSupported); } if (Options.MessageLimit > 0 && HighPriorityLinkedList.Count + RegularLinkedList.Count >= Options.MessageLimit) { return(PushResult.LimitExceeded); } if (Options.MessageSizeLimit > 0 && message.Message.Length > Options.MessageSizeLimit) { return(PushResult.LimitExceeded); } //prepare properties message.Message.FirstAcquirer = true; message.Message.AcknowledgeRequired = Options.RequestAcknowledge; //if message doesn't have message id and "UseMessageId" option is enabled, create new message id for the message if (Options.UseMessageId && string.IsNullOrEmpty(message.Message.MessageId)) { message.Message.SetMessageId(Channel.Server.MessageIdGenerator.Create()); } //if we have an option maximum wait duration for message, set it after message joined to the queue. //time keeper will check this value and if message time is up, it will remove message from the queue. if (Options.MessageTimeout > TimeSpan.Zero) { message.Deadline = DateTime.UtcNow.Add(Options.MessageTimeout); } if (Options.HideClientNames) { message.Message.SetSource(null); } try { //fire message receive event Info.AddMessageReceive(); Decision decision = await DeliveryHandler.ReceivedFromProducer(this, message, sender); message.Decision = decision; bool allow = await ApplyDecision(decision, message); if (!allow) { return(PushResult.Success); } if (State.CanEnqueue(message)) { await RunInListSync(() => AddMessage(message)); if (State.TriggerSupported && !_triggering) { _ = Trigger(); } } else { _ = State.Push(message); } return(PushResult.Success); } catch (Exception ex) { Info.AddError(); try { Decision decision = await DeliveryHandler.ExceptionThrown(this, State.ProcessingMessage, ex); if (State.ProcessingMessage != null) { await ApplyDecision(decision, State.ProcessingMessage); if (decision.KeepMessage && !State.ProcessingMessage.IsInQueue) { AddMessage(State.ProcessingMessage, false); } } } catch //if developer does wrong operation, we should not stop { } } return(PushResult.Success); }
/// <summary> /// Pushes a message into the queue. /// </summary> internal async Task <PushResult> Push(QueueMessage message, MqClient sender) { if (!IsInitialized) { try { UpdateOptionsByMessage(message.Message); DeliveryHandlerBuilder handlerBuilder = new DeliveryHandlerBuilder { Server = Server, Queue = this, Headers = message.Message.Headers, DeliveryHandlerHeader = message.Message.FindHeader(HorseHeaders.DELIVERY_HANDLER) }; IMessageDeliveryHandler deliveryHandler = await Server.DeliveryHandlerFactory(handlerBuilder); InitializeQueue(deliveryHandler); handlerBuilder.TriggerAfterCompleted(); } catch (Exception e) { Server.SendError("INITIALIZE_IN_PUSH", e, $"QueueName:{Name}"); throw; } } if (Status == QueueStatus.Stopped) { return(PushResult.StatusNotSupported); } if (Options.MessageLimit > 0 && PriorityMessagesList.Count + MessagesList.Count >= Options.MessageLimit) { return(PushResult.LimitExceeded); } if (Options.MessageSizeLimit > 0 && message.Message.Length > Options.MessageSizeLimit) { return(PushResult.LimitExceeded); } //remove operational headers that are should not be sent to consumers or saved to disk message.Message.RemoveHeaders(HorseHeaders.DELAY_BETWEEN_MESSAGES, HorseHeaders.ACKNOWLEDGE, HorseHeaders.QUEUE_NAME, HorseHeaders.QUEUE_STATUS, HorseHeaders.QUEUE_TOPIC, HorseHeaders.PUT_BACK_DELAY, HorseHeaders.DELIVERY, HorseHeaders.DELIVERY_HANDLER, HorseHeaders.CC); //prepare properties message.Message.WaitResponse = Options.Acknowledge != QueueAckDecision.None; //if message doesn't have message id and "UseMessageId" option is enabled, create new message id for the message if (Options.UseMessageId && string.IsNullOrEmpty(message.Message.MessageId)) { message.Message.SetMessageId(Server.MessageIdGenerator.Create()); } //if we have an option maximum wait duration for message, set it after message joined to the queue. //time keeper will check this value and if message time is up, it will remove message from the queue. if (Options.MessageTimeout > TimeSpan.Zero) { message.Deadline = DateTime.UtcNow.Add(Options.MessageTimeout); } if (Options.HideClientNames) { message.Message.SetSource(null); } try { //fire message receive event Info.AddMessageReceive(); Decision decision = await DeliveryHandler.ReceivedFromProducer(this, message, sender); message.Decision = decision; bool allow = await ApplyDecision(decision, message); if (!allow) { return(PushResult.Success); } //trigger message produced event OnMessageProduced.Trigger(message); if (State.CanEnqueue(message)) { await RunInListSync(() => AddMessage(message)); if (State.TriggerSupported && !_triggering) { _ = Trigger(); } } else { _ = State.Push(message); } return(PushResult.Success); } catch (Exception ex) { Server.SendError("PUSH", ex, $"QueueName:{Name}"); Info.AddError(); try { Decision decision = await DeliveryHandler.ExceptionThrown(this, State.ProcessingMessage, ex); if (State.ProcessingMessage != null) { await ApplyDecision(decision, State.ProcessingMessage); if (!State.ProcessingMessage.IsInQueue) { if (decision.PutBack == PutBackDecision.Start) { AddMessage(State.ProcessingMessage, false); } else if (decision.PutBack == PutBackDecision.End) { AddMessage(State.ProcessingMessage); } } } } catch //if developer does wrong operation, we should not stop { } } return(PushResult.Success); }