Esempio n. 1
0
        public void PutResponseAsync(Message responseMsg, BrokerQueueItem requestItem, bool ignoreAsyncToken = false)
        {
            try
            {
                // Null means the request has been put back.
                if (responseMsg != null && this.sharedData.Config.LoadBalancing.MessageResendLimit > 0)
                {
                    if (!requestItem.ReemitToken.Finish())
                    {
                        TraceUtils.TraceWarning(
                            "BrokerQueueDispatcher",
                            "PutResponseAsync",
                            "Drop the response {0} since no multi emission callback registered",
                            Utility.GetMessageIdFromMessage(requestItem.Message));

                        return;
                    }
                }

                BrokerQueueAsyncToken asyncToken = requestItem.PersistAsyncToken;
                if (asyncToken.AsyncToken != null || ignoreAsyncToken || responseMsg == null)
                {
                    asyncToken.Queue.PutResponseAsync(responseMsg, requestItem);
                    return;
                }

                DispatcherAsyncTokenItem asyncTokenItem = null;
                lock (this.requestsAsyncTokenTable)
                {
                    this.requestsAsyncTokenTable.TryGetValue(asyncToken.PersistId, out asyncTokenItem);
                }

                if (asyncTokenItem != null)
                {
                    bool hasGetAsyncToken = false;
                    try
                    {
                        if (asyncTokenItem != null)
                        {
                            if (asyncTokenItem.AsyncToken != null)
                            {
                                asyncToken.AsyncToken = asyncTokenItem.AsyncToken;
                                hasGetAsyncToken      = true;

                                lock (this.requestsAsyncTokenTable)
                                {
                                    this.requestsAsyncTokenTable.Remove(asyncToken.PersistId);
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        if (hasGetAsyncToken)
                        {
                            BrokerTracing.TraceWarning("[BrokerQueueDispatcher] .PutResponseAsync: remove the async token from the table raised the exception, {0}", e);
                        }
                        else
                        {
                            // maybe there are duplicate responses, and the request in the async token table is removed by the previous request.
                            BrokerTracing.TraceWarning("[BrokerQueueDispatcher] .PutResponseAsync: try to get the async token from the table raised the exception, {0}", e);
                        }
                    }

                    if (hasGetAsyncToken)
                    {
                        asyncToken.Queue.PutResponseAsync(responseMsg, requestItem);
                    }
                    else
                    {
                        BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PutResponseAsync: Failed to get async token.");

                        lock (this.responsesWithoutAsyncTokenTable)
                        {
                            this.responsesWithoutAsyncTokenTable.Add(asyncToken.PersistId, new DispatcherAsyncTokenItem(responseMsg, asyncToken));
                        }

                        if (asyncTokenItem.AsyncToken != null)
                        {
                            bool needPutToTheQueue = false;
                            try
                            {
                                lock (this.responsesWithoutAsyncTokenTable)
                                {
                                    this.responsesWithoutAsyncTokenTable.Remove(asyncToken.PersistId);
                                }

                                needPutToTheQueue = true;

                                lock (this.requestsAsyncTokenTable)
                                {
                                    this.requestsAsyncTokenTable.Remove(asyncToken.PersistId);
                                }
                            }
                            catch (Exception e)
                            {
                                if (needPutToTheQueue)
                                {
                                    BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PutResponseAsync: remove the request async token from the table failed, the exception: {0}", e);
                                }
                                else
                                {
                                    // in case the reponse message is persisted by another thread.
                                    BrokerTracing.TraceInfo("[BrokerQueueDispatcher] .PutResponseAsync: remove the response from the responses without async table fail, the exception: {0}", e);
                                }
                            }

                            if (needPutToTheQueue)
                            {
                                asyncToken.AsyncToken = asyncTokenItem.AsyncToken;
                                asyncToken.Queue.PutResponseAsync(responseMsg, requestItem);
                            }
                            else
                            {
                                BrokerTracing.TraceWarning(
                                    "[BrokerQueueDispatcher] .PutResponseAsync: Don't put response back because needPutToTheQueue=false. AsyncToken.PersistId={0}, requestItem id: {1}, response id:{2}",
                                    asyncToken.PersistId,
                                    requestItem?.Message?.Headers?.MessageId,
                                    responseMsg?.Headers?.MessageId);
                            }
                        }
                        else
                        {
                            // the request item is processed and its response is returned, but its async token is unknown yet.  At this point, as corresponding DispatcherAsyncToken item is
                            // already put into responsesWithoutAsyncTokenTable, the request item itself is of no use now. so dispose it.
                            BrokerTracing.TraceInfo(
                                "[BrokerQueueDispatcher] .PutResponseAsync: Dispose requestItem id: {0}, response id:{1}",
                                requestItem?.Message?.Headers?.MessageId,
                                responseMsg?.Headers?.MessageId);

                            requestItem.Dispose();
                        }
                    }
                }
                else
                {
                    BrokerTracing.TraceError("[BrokerQueueDispatcher] .PutResponseAsync: can not find the async token.");
                }
            }
            catch (Exception e)
            {
                BrokerTracing.TraceError("[BrokerQueueDispatcher] .PutResponseAsync: unkown exception, {0}", e);
            }
        }