public bool NonReceiveContextPoisonHandling(MsmqMessageProperty messageProperty) { if (messageProperty.AbortCount <= this.ReceiveParameters.ReceiveRetryCount) { return(false); } int retryCycle = messageProperty.MoveCount / 2; lock (this) { if (this.disposed) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString())); } if (retryCycle >= this.ReceiveParameters.MaxRetryCycles) { if (TD.MaxRetryCyclesExceededMsmqIsEnabled()) { TD.MaxRetryCyclesExceededMsmq(messageProperty.MessageId); } FinalDisposition(messageProperty); } else { MsmqReceiveHelper.MoveReceivedMessage(this.mainQueue, this.retryQueueForMove, messageProperty.LookupId); MsmqDiagnostics.PoisonMessageMoved(messageProperty.MessageId, false, this.receiver.InstanceId); } } return(true); }
public bool ReceiveContextPoisonHandling(MsmqMessageProperty messageProperty) { // The basic idea is to use the message move count to get the number of retry attempts the message has been through // The computation of the retry count and retry cycle count is slightly involved due to fact that the message being processed // could have been recycled message. (Recycled message is the message that moves from lock queue to retry queue to main queue // and back to lock queue // // Count to tally message recycling (lock queue to retry queue to main queue adds move count of 2 to the message) const int retryMoveCount = 2; // Actual number of times message is received before recycling to retry queue int actualReceiveRetryCount = this.ReceiveParameters.ReceiveRetryCount + 1; // The message is recycled these many number of times int maxRetryCycles = this.ReceiveParameters.MaxRetryCycles; // Max change in message move count between recycling int maxMovePerCycle = (2 * actualReceiveRetryCount) + 1; // Number of recycles the message has been through int messageCyclesCompleted = messageProperty.MoveCount / (maxMovePerCycle + retryMoveCount); // Total number of moves on the message at the end of the last recycle int messageMoveCountForCyclesCompleted = messageCyclesCompleted * (maxMovePerCycle + retryMoveCount); // The differential move count for the current cycle int messageMoveCountForCurrentCycle = messageProperty.MoveCount - messageMoveCountForCyclesCompleted; lock (this) { if (this.disposed) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().ToString())); } // Check if the message has already completed its max recycle count (MaxRetryCycles) // and the disposed the message first. Such a message was previously disposed using the ReceiveErrorHandling method // and the channel/listener would immediately fault // if (messageCyclesCompleted > maxRetryCycles) { FinalDisposition(messageProperty); return(true); } // Check if the message is eligible for recycling/disposition if (messageMoveCountForCurrentCycle >= maxMovePerCycle) { if (TD.ReceiveRetryCountReachedIsEnabled()) { TD.ReceiveRetryCountReached(messageProperty.MessageId); } if (messageCyclesCompleted < maxRetryCycles) { // The message is eligible for recycling, move the message the message to retry queue MsmqReceiveHelper.MoveReceivedMessage(this.lockQueueForReceive, this.retryQueueForMove, messageProperty.LookupId); MsmqDiagnostics.PoisonMessageMoved(messageProperty.MessageId, false, this.receiver.InstanceId); } else { if (TD.MaxRetryCyclesExceededMsmqIsEnabled()) { TD.MaxRetryCyclesExceededMsmq(messageProperty.MessageId); } // Dispose the message using ReceiveErrorHandling FinalDisposition(messageProperty); } return(true); } else { return(false); } } }