예제 #1
0
        public void PutRequestTest()
        {
            var f       = new MockBrokerQueueFactory();
            var ob      = new MockBrokerObserver();
            var adapter = new RequestQueueAdapter(ob, f);
            var item    = new BrokerQueueItem(SampleMessage, Guid.NewGuid(), null);

            DispatchData data = new DispatchData("1", 1, "1")
            {
                BrokerQueueItem = item,
                MessageId       = Guid.NewGuid()
            };

            adapter.PutRequestBack(data);

            Assert.AreEqual(1, ob.RequestProcessingCompletedInvokedTimes, "RequestProcessingCompleted of BrokerObserver should be invoked once.");
            Assert.IsNull(data.BrokerQueueItem, "BrokerQueueItem property should be set to null after put back.");
            Assert.AreEqual(1, f.PutResponseAsyncInvokedTimes, "PutResponseAsync should be invoked once.");
            var messageList = f.PutMessageDic.ToList();

            Assert.AreEqual(1, messageList.Count, "There should be only one message put.");
            Assert.AreEqual(item, messageList[0].Key, "BrokerQueueItem should match.");
            Assert.AreEqual(1, messageList[0].Value.Count, "There should be only one response for the request queue item.");
            Assert.AreEqual(null, messageList[0].Value[0], "Response message should be null.");
        }
예제 #2
0
        /// <summary>
        /// Get a response from the storage
        /// </summary>
        /// <param name="callback">the response callback, the async result should be the BrokerQueueItem</param>
        /// <param name="callbackState">the state object for the callback</param>
        public void GetResponseAsync(PersistCallback callback, object callbackState)
        {
            if (this.isClosedField)
            {
                BrokerTracing.TraceWarning("[MemoryPersist] .GetResponseAsync: the queue is closed.");
                return;
            }

            BrokerQueueItem responseItem = null;

            try
            {
                lock (this.lockResponseQueueField)
                {
                    responseItem = this.responseQueueField.Dequeue();
                }
            }
            catch (InvalidOperationException)
            {
                BrokerTracing.TraceError("[MemoryPersist] .GetResponseAsync: no response available.  sessionId = {0}, clientId = {1}", this.sessionIdField, this.clientIdField);
            }

            if (callback == null)
            {
                return;
            }

            ThreadPool.QueueUserWorkItem(this.GetOperationComplete, new GetCallbackContext(callback, callbackState, responseItem));
        }
        public void PutResponseBackDummyExceptionTest()
        {
            var f = new MockBrokerQueueFactory();

            var ob = new MockBrokerObserver();

            var sampleMessage = Message.CreateMessage(MessageVersion.Default, "SampleAction");

            sampleMessage.Headers.MessageId = new UniqueId(Guid.NewGuid());
            var adapter = new ResponseQueueAdapter(ob, f, 4);
            var item    = new BrokerQueueItem(DummyRequestContext.GetInstance(MessageVersion.Soap11), sampleMessage, Guid.NewGuid(), null);

            DispatchData data = new DispatchData("1", 1, "1")
            {
                BrokerQueueItem = item,
                MessageId       = Guid.NewGuid(),
                DispatchTime    = new DateTime(2000, 1, 1),
                Exception       = new FaultException <RetryOperationError>(new RetryOperationError("Reason")),
            };

            adapter.PutResponseBack(data);

            Assert.IsTrue(ob.Duration > 0, "The call duration should be greater than 0");
            Assert.AreEqual(f.PutMessageDic.Count, 1, "There must be 1 and only 1 instance");
            Assert.AreEqual(f.PutResponseAsyncInvokedTimes, 1, "There must be 1 and only 1 invoke");
            Assert.AreSame(f.PutMessageDic.First().Key, item, "The put back BrokerQueueItem should be the same as the original one.");
            Assert.AreEqual(f.PutMessageDic.First().Value.Count, 1, "The response message should only be one.");
            Assert.AreSame(f.PutMessageDic.First().Value[0].Headers.RelatesTo, item.Message.Headers.MessageId, "The put back Message should be the same as the original one.");
            Assert.IsNull(data.BrokerQueueItem, "BrokerQueueItem property should be set to null after put back.");
            Assert.IsNull(data.ReplyMessage, "The reply message should be null after put back.");
            Assert.IsNull(data.Exception, "The Exception should be null after put back.");
        }
        public void PutResponseBackPassTest()
        {
            var f = new MockBrokerQueueFactory();

            var ob = new MockBrokerObserver();

            var sampleMessage = Message.CreateMessage(MessageVersion.Default, "SampleAction");

            sampleMessage.Headers.MessageId = new UniqueId(Guid.NewGuid());
            var mockDuplexRequestContext = new MockDuplexRequestContext(sampleMessage);
            var adapter = new ResponseQueueAdapter(ob, f, 4);
            var item    = new BrokerQueueItem(mockDuplexRequestContext, sampleMessage, Guid.NewGuid(), null);
            var message = Message.CreateMessage(MessageVersion.Default, "Default");

            DispatchData data = new DispatchData("1", 1, "1")
            {
                BrokerQueueItem = item,
                MessageId       = Guid.NewGuid(),
                DispatchTime    = new DateTime(2000, 1, 1),
                ReplyMessage    = message,
            };

            adapter.PutResponseBack(data);

            Assert.IsTrue(ob.Duration > 0, "The call duration should be greater than 0");
            Assert.AreSame(mockDuplexRequestContext.ReplyMessage, message, "The put back Message should be the same as the original one.");
            Assert.IsNull(data.BrokerQueueItem, "BrokerQueueItem property should be set to null after put back.");
            Assert.IsNull(data.ReplyMessage, "The reply message should be null after put back.");
            Assert.IsNull(data.Exception, "The Exception should be null after put back.");
        }
예제 #5
0
        /// <summary>
        /// BrokerQueueCallback root method
        /// </summary>
        /// <param name="item">indicating the broker queue item</param>
        /// <param name="state">indicating the state</param>
        public void CallbackRoot(BrokerQueueItem item, object state)
        {
            if (!this.refObj.IncreaseCount())
            {
                throw new ObjectDisposedException("dispatcher");
            }

            try
            {
                this.brokerQueueCallback(item, state);
            }
            finally
            {
                try
                {
                    this.refObj.DecreaseCount();
                }
                catch (ThreadAbortException)
                {
                }
                catch (AppDomainUnloadedException)
                {
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceEvent(TraceEventType.Critical, 0, "[ReferencedThreadHelper] Exception catched while disposing the object: {0}", e);
                }
            }
        }
예제 #6
0
 public void PutResponseAsync(Message responseMsg, BrokerQueueItem requestItem)
 {
     Interlocked.Increment(ref this.putResponseAsyncInvokedTimes);
     this.messageDic.AddOrUpdate(
         requestItem,
         x => new List <Message>()
     {
         responseMsg
     },
         (x, list) =>
     {
         list.Add(responseMsg);
         return(list);
     });
 }
예제 #7
0
        /// <summary>
        /// Put a single request item into the storage.
        /// </summary>
        /// <param name="request">the single request that need be stored to the persistenc</param>
        /// <param name="putRequestCallback">the callback function that will be called once the async operation finish or exception raise.</param>
        /// <param name="callbackState">the state object for the callback.</param>
        public async Task PutRequestAsync(BrokerQueueItem request, PutRequestCallback putRequestCallback, object callbackState)
        {
            if (this.isClosedField)
            {
                BrokerTracing.TraceWarning("[MemoryPersist] .GetRequestAsync: the queue is closed.");
                return;
            }

            request.PersistAsyncToken.AsyncToken = this.PersistToken;
            this.requestQueueField.Enqueue(request);

            Interlocked.Increment(ref this.allRequestCountField);
            Interlocked.Increment(ref this.requestCountField);

            PutRequestComplete(putRequestCallback, callbackState);
        }
예제 #8
0
        public async Task GetRequestTest()
        {
            var request = new BrokerQueueItem(
                null,
                Message.CreateMessage(MessageVersion.Soap12WSAddressing10, action, shortMsg),
                null);

            await this.sessionPersist.PutRequestAsync(request, null, 0);

            this.sessionPersist.GetRequestAsync(this.GetMessageTestCallback, null);
            while (!this.CallbackIsCalled)
            {
                await Task.Delay(millisecondsDelay);
            }

            Assert.AreEqual(true, this.IsExpected);
        }
예제 #9
0
        /// <summary>
        /// acknowledge that a response message is dispatched, either successfully or not
        /// </summary>
        /// <param name="responseItem">response message being dispatched</param>
        /// <param name="success">if dispatching is success or not</param>
        public void AckResponse(BrokerQueueItem responseMessage, bool success)
        {
            if (success)
            {
                responseMessage.Dispose();
                return;
            }

            // if failed to send response, response message is put back
            responseMessage.PrepareMessage();

            // put response back
            lock (this.lockResponseQueueField)
            {
                this.filteredOutResponseQueueField.Enqueue(responseMessage);
            }
        }
예제 #10
0
        public async Task GetLargeResponseTest()
        {
            var response = new BrokerQueueItem(
                null,
                Message.CreateMessage(MessageVersion.Soap12WSAddressing10, action, largeMsg),
                null);

            response.PersistAsyncToken.AsyncToken = Guid.NewGuid().ToString();
            response.PeerItem = new BrokerQueueItem(
                null,
                Message.CreateMessage(MessageVersion.Soap12WSAddressing10, action, largeMsg),
                null);
            this.sessionPersist.PutResponseAsync(response, null, 0);
            this.sessionPersist.GetResponseAsync(this.GetLargeMessageTestCallback, null);
            while (!this.CallbackIsCalled)
            {
                await Task.Delay(millisecondsDelay);
            }

            Assert.AreEqual(true, this.IsExpected);
        }
예제 #11
0
        /// <summary>
        /// Put on response item into persistence
        /// </summary>
        /// <param name="response">the response item to be persisted</param>
        /// <param name="putResponseCallback">the callback function that will be called once the async operation finish or exception raise.</param>
        /// <param name="callbackState">the state object for the callback.</param>
        public void PutResponseAsync(BrokerQueueItem response, PutResponseCallback putResponseCallback, object callbackState)
        {
            bool isFaultResponse = response.Message.IsFault;

            lock (this.lockResponseQueueField)
            {
                this.responseQueueField.Enqueue(response);
                Interlocked.Increment(ref this.responseCountField);
            }

            response.PeerItem.Dispose();
            response.PeerItem = null;

            if (isFaultResponse)
            {
                Interlocked.Increment(ref this.failedRequestCountField);
            }
            bool isLastResponse = (Interlocked.Decrement(ref this.requestCountField) == 0);

            PutResponseComplete(1, isFaultResponse ? 1 : 0, isLastResponse, putResponseCallback, callbackState);
        }
예제 #12
0
        /// <summary>
        /// Fetch the requests one by one from the storage but not remove the original message in the storage.
        /// </summary>
        /// <param name="callback">the callback to get the async result</param>
        /// <param name="state">the state object for the callback</param>
        public void GetRequestAsync(PersistCallback callback, object state)
        {
            if (this.isClosedField)
            {
                BrokerTracing.TraceWarning("[MemoryPersist] .GetRequestAsync: the queue is closed.");
                return;
            }

            BrokerQueueItem requestItem = null;

            if (!this.requestQueueField.TryDequeue(out requestItem))
            {
                BrokerTracing.TraceError("[MemoryPersist] .GetRequestAsync: no request available. sessionId={0}, clientId={1}", this.sessionIdField, this.clientIdField);
            }

            if (callback == null)
            {
                return;
            }

            ThreadPool.QueueUserWorkItem(this.GetOperationComplete, new GetCallbackContext(callback, state, requestItem));
        }
예제 #13
0
 public void HandleEndpointNotFoundException(int clientIndex, BackEnd.IService client, BrokerQueueItem item, Guid messageId, System.ServiceModel.EndpointNotFoundException e)
 {
 }
예제 #14
0
 public void HandleStorageException(DateTime dispatchTime, int clientIndex, BackEnd.IService client, BrokerQueueItem item, Guid messageId, StorageException e)
 {
 }
예제 #15
0
 public Task HandleException(DateTime dispatchTime, int clientIndex, BackEnd.IService client, BrokerQueueItem item, Guid messageId, Exception e)
 {
     return(Task.CompletedTask);
 }
예제 #16
0
        public bool HandleFaultExceptionRetry(int clientIndex, BrokerQueueItem item, Message reply, DateTime dispatchTime, out bool preemption)
        {
            preemption = false;

            return(true);
        }
예제 #17
0
 private void GetLargeMessageTestCallback(BrokerQueueItem persistMessage, object state, Exception exception)
 {
     this.IsExpected       = persistMessage.Message.GetBody <byte[]>().SequenceEqual(largeMsg);
     this.CallbackIsCalled = true;
 }
예제 #18
0
        /// <summary>
        /// Receive response message
        /// </summary>
        /// <param name="item">broker queue item</param>
        /// <param name="asyncState">async state</param>
        private void ReceiveResponse(BrokerQueueItem item, object asyncState)
        {
            if (this.callbackChannelDisposed)
            {
                throw new Exception("Callback channel was disposed");
            }

            this.ResetTimeout();
            BrokerTracing.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "[BrokerClient] Client {0}: Receive Response from BrokerQueue", this.clientId);
            object[] objArray = asyncState as object[];
            IResponseServiceCallback callback = (IResponseServiceCallback)objArray[0];
            string  clientData = objArray[1].ToString();
            Message response   = this.ConvertMessage(item.Message);
            int     index      = response.Headers.FindHeader(Constant.ResponseCallbackIdHeaderName, Constant.ResponseCallbackIdHeaderNS);

            if (index < 0)
            {
                response.Headers.Add(MessageHeader.CreateHeader(Constant.ResponseCallbackIdHeaderName, Constant.ResponseCallbackIdHeaderNS, clientData));
            }

            Exception exception = null;

            try
            {
                if (callback is AzureQueueProxy)
                {
                    callback.SendResponse(response, clientData);
                }
                else
                {
                    callback.SendResponse(response);
                }
                BrokerTracing.EtwTrace.LogFrontEndResponseSent(this.SharedData.BrokerInfo.SessionId, this.clientId, Utility.GetMessageIdFromResponse(response));
                this.IncreaseResponsesCount();
            }
            catch (ObjectDisposedException e)
            {
                this.callbackChannelDisposed = true;
                exception = new Exception("Callback channel is disposed", e);
                throw exception;
            }
            catch (CommunicationObjectFaultedException e)
            {
                this.callbackChannelDisposed = true;
                exception = new Exception("Callback channel is faulted", e);
                throw exception;
            }
            catch (CommunicationObjectAbortedException e)
            {
                this.callbackChannelDisposed = true;
                exception = new Exception("Callback channel is abroted", e);
                throw exception;
            }
            catch (Exception ce)
            {
                BrokerTracing.TraceEvent(System.Diagnostics.TraceEventType.Error, 0, "[BrokerClient] Client {0}: Send back response error: {1}", this.clientId, ce);

                // Reply a fault message indicating failed to send back the response and reply EOR and finish.
                this.ReplyFaultMessage(callback, FrontEndFaultMessage.GenerateFaultMessage(null, MessageVersion.Default, SOAFaultCode.Broker_SendBackResponseFailed, SR.SendBackResponseFailed), clientData);
                this.ReplyEndOfMessage(callback, clientData);
            }
            finally
            {
                // We do not need to lock here because this callback is designed to be
                // triggered by BrokerQueue synchronizely
                if (this.cacheBrokerQueueItem)
                {
                    lock (this.lockCacheItemList)
                    {
                        this.cachedItemList.Add(item);
                    }
                }
                else
                {
                    this.Queue.AckResponse(item, (exception == null));
                }

                if (this.callbackChannelDisposed)
                {
                    this.Queue.ResetResponsesCallback();
                }
            }
        }
예제 #19
0
        /// <summary>
        /// Receive response message from host.
        /// </summary>
        /// <param name="data">DispatchData instance</param>
        public void ReceiveResponse(DispatchData data)
        {
            Contract.Requires(data.AsyncResult != null, string.Format(ContractMessageFormat, "DispatchData.AsyncResult"));

            Contract.Requires(data.Client != null, string.Format(ContractMessageFormat, "DispatchData.Client"));

            Contract.Requires(data.BrokerQueueItem != null, string.Format(ContractMessageFormat, "DispatchData.BrokerQueueItem"));

            Contract.Ensures(
                data.ReplyMessage != null || data.Exception != null,
                "DispatchData should have either a reply message either an exception.");

            Message reply = null;

            string taskId = data.TaskId;

            DateTime dispatchTime = data.DispatchTime;

            int clientIndex = data.ClientIndex;

            IService client = data.Client;

            BrokerQueueItem item = data.BrokerQueueItem;

            // Bug #16197: if request action field is dropped by wcf, restore it back
            if (string.IsNullOrEmpty(item.Message.Headers.Action))
            {
                item.Message.Headers.Action = data.RequestAction;
            }

            this.dispatcher.items[clientIndex] = null;

            this.dispatcher.DecreaseProcessingCount();

            Guid messageId = Utility.GetMessageIdFromMessage(item.Message);

            try
            {
                // Get the response message
                reply = client.EndProcessMessage(data.AsyncResult);

                data.ReplyMessage = reply;

                // following method needs to be called before setting bServiceInitalizationCompleted flag
                this.PostProcessMessage(reply);

                // mark bServiceInitalizationCompleted flag to true;
                if (!this.dispatcher.ServiceInitializationCompleted)
                {
                    this.dispatcher.ServiceInitializationCompleted = true;

                    // nofity that it is connected to service host
                    this.dispatcher.OnServiceInstanceConnected(null);
                }

                BrokerTracing.EtwTrace.LogBackendResponseReceived(data.SessionId, taskId, messageId, reply.IsFault);
            }
            catch (EndpointNotFoundException e)
            {
                data.Exception = e;

                // TODO: need ExceptionHandler
                this.dispatcher.HandleEndpointNotFoundException(clientIndex, client, item, messageId, e);

                return;
            }
            catch (StorageException e)
            {
                data.Exception = e;

                // TODO: need ExceptionHandler
                this.dispatcher.HandleStorageException(dispatchTime, clientIndex, client, item, messageId, e);

                return;
            }
            catch (Exception e)
            {
                data.Exception = e;

                // TODO: need ExceptionHandler
                this.dispatcher.HandleException(dispatchTime, clientIndex, client, item, messageId, e);

                return;
            }

            if (reply.IsFault)
            {
                // If any fault message is received, consider passing binding data again.
                // TODO: pass binding data only on special error code
                this.dispatcher.PassBindingFlags[clientIndex] = true;
            }

            bool servicePreempted = false;

            if (reply.IsFault)
            {
                BrokerTracing.TraceVerbose(
                    BrokerTracing.GenerateTraceString(
                        "ResponseReceiver",
                        "ReceiveResponse",
                        taskId,
                        clientIndex,
                        client.ToString(),
                        messageId,
                        "The response is a fault message."));

                // TODO: need ExceptionHandler
                data.ExceptionHandled = this.dispatcher.HandleFaultExceptionRetry(clientIndex, item, reply, dispatchTime, out servicePreempted);
            }
            else
            {
                // if it is a normal response, check if the CancelEvent happens when request is being processed.
                int index = reply.Headers.FindHeader(Constant.MessageHeaderPreemption, Constant.HpcHeaderNS);

                if (index >= 0 && index < reply.Headers.Count)
                {
                    servicePreempted = true;

                    int messageCount = reply.Headers.GetHeader <int>(index);

                    BrokerTracing.TraceVerbose(
                        BrokerTracing.GenerateTraceString(
                            "ResponseReceiver",
                            "ReceiveResponse",
                            taskId,
                            clientIndex,
                            client.ToString(),
                            messageId,
                            string.Format("The count of processing message in the counterpart host is {0}.", messageCount)));

                    // will remove the dispatcher if no processing message left on the host
                    if (messageCount == 0)
                    {
                        // Simulate a SessionFault and reuse the method HandleServiceInstanceFailure,
                        // and the message will be processed later as normal.
                        BrokerTracing.TraceVerbose(
                            BrokerTracing.GenerateTraceString(
                                "ResponseReceiver",
                                "ReceiveResponse",
                                taskId,
                                clientIndex,
                                client.ToString(),
                                messageId,
                                "(Preemption) Call HandleServiceInstanceFailure."));

                        // TODO: need ServiceInstanceFailureHandler
                        this.dispatcher.HandleServiceInstanceFailure(new SessionFault(SOAFaultCode.Service_Preempted, string.Empty));
                    }
                }
            }

            data.ServicePreempted = servicePreempted;

            // Debug Failure Test
            SimulateFailure.FailOperation(1);
        }
예제 #20
0
 /// <summary>
 /// Instantiate a new instance of class GetCallbackContext
 /// </summary>
 /// <param name="callback">the callback</param>
 /// <param name="callbackState">the callback context</param>
 /// <param name="callbackMsg">the retrieved back message</param>
 public GetCallbackContext(PersistCallback callback, object callbackState, BrokerQueueItem callbackMsg)
 {
     this.callbackField      = callback;
     this.callbackStateField = callbackState;
     this.callbackMsgField   = callbackMsg;
 }
예제 #21
0
 public override void AckResponse(BrokerQueueItem response, bool success)
 {
     throw new NotImplementedException();
 }
예제 #22
0
            /// <summary>
            /// Receive Response
            /// </summary>
            /// <param name="item">indicating the broker queue item</param>
            /// <param name="asyncState">indicating the async state</param>
            public void ReceiveResponse(BrokerQueueItem item, object asyncState)
            {
                BrokerTracing.TraceVerbose("[PullResponsesHandler] Receive response.");
                XmlDocument doc = new XmlDocument()
                {
                    XmlResolver = null
                };

                this.resetTimeout();

                try
                {
                    Message soap11Message = this.convertMessage(item.Message);
                    byte[]  buffer;

                    MemoryStream ms = null;
                    try
                    {
                        ms = new MemoryStream();
                        using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(ms))
                        {
                            var msTemp = ms;
                            ms = null;
                            soap11Message.WriteMessage(writer);
                            writer.Flush();
                            buffer = msTemp.ToArray();
                        }
                    }
                    finally
                    {
                        if (ms != null)
                        {
                            ms.Dispose();
                        }
                    }

                    try
                    {
                        ms = new MemoryStream(buffer);
                        using (XmlReader reader = XmlReader.Create(ms))
                        {
                            ms = null;
                            doc.Load(reader);
                        }
                    }
                    finally
                    {
                        if (ms != null)
                        {
                            ms.Dispose();
                        }
                    }

                    this.messages.Add(doc.DocumentElement);
                    if (this.messages.Count >= this.count)
                    {
                        this.completeEvent.Set();
                    }
                }
                finally
                {
                    this.queue.AckResponse(item, true);
                }
            }
예제 #23
0
        private async Task DeserializeMessage(CloudQueueMessage message)
        {
            Exception       exception       = null;
            BrokerQueueItem brokerQueueItem = null;

            if (message.AsBytes != null && message.AsBytes.Length > 0)
            {
                // Deserialize message to BrokerQueueItem
                try
                {
                    brokerQueueItem = (BrokerQueueItem)this.formatter.Deserialize(
                        await AzureStorageTool.GetMsgBody(this.blobContainer, message.AsBytes));
                    brokerQueueItem.PersistAsyncToken.AsyncToken =
                        brokerQueueItem.Message.Headers.MessageId.ToString();
                    BrokerTracing.TraceVerbose(
                        "[AzureQueueRequestFetcher] .DeserializeMessage: deserialize header={0} property={1}",
                        brokerQueueItem.Message.Headers.MessageId,
                        brokerQueueItem.Message.Properties);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceError(
                        "[AzureQueueRequestFetcher] .DeserializeMessage: deserialize message failed, Exception:{0}",
                        e.ToString());
                    exception = e;
                }
            }

            if (brokerQueueItem != null && !this.requestDic.TryAdd(
                    brokerQueueItem.PersistAsyncToken.AsyncToken.ToString(),
                    true))
            {
                Interlocked.Increment(ref this.pendingFetchCount);
                try
                {
                    await this.requestQueue.DeleteMessageAsync(message);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceError(
                        "[AzureQueueRequestFetcher] .DeserializeMessage: delete duplicate message in request queue failed, Exception:{0}",
                        e.ToString());
                }
            }
            else
            {
                var copyMessage = new CloudQueueMessage(message.AsBytes);
                await this.pendingQueue.AddMessageAsync(copyMessage);

                try
                {
                    await this.requestQueue.DeleteMessageAsync(message);
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceError(
                        "[AzureQueueRequestFetcher] .DeserializeMessage: delete message in request queue failed, Exception:{0}",
                        e.ToString());
                }

                this.HandleMessageResult(new MessageResult(brokerQueueItem, exception));
            }
        }
예제 #24
0
 public MessageResult(BrokerQueueItem message, Exception e)
 {
     this.message   = message;
     this.exception = e;
 }
예제 #25
0
 public override void PutResponseAsync(Message responseMsg, BrokerQueueItem requestItem)
 {
     this.replyMessageQueue.Enqueue(responseMsg);
 }
예제 #26
0
 private void GetWrongMessageTestCallback(BrokerQueueItem persistMessage, object state, Exception exception)
 {
     this.IsExpected       = persistMessage.Message.GetBody <string>().Equals(wrongMsg);
     this.CallbackIsCalled = true;
 }
예제 #27
0
        /// <summary>
        /// Trigger the callback when called GetRequestAsync
        /// For UnitTesting purpose
        /// </summary>
        /// <param name="item">indicate the broker queue item</param>
        public void TriggerGetRequestCallback(BrokerQueueItem item)
        {
            KeyValuePair <BrokerQueueCallback, object> pair = this.callbackQueue.Dequeue();

            pair.Key(item, pair.Value);
        }
예제 #28
0
        /// <summary>
        /// Callback function invoked on BeginPeek completion.
        /// </summary>
        /// <param name="ar"></param>
        private void PeekMessageComplete(IAsyncResult ar)
        {
            BrokerTracing.TraceVerbose("[MSMQMessageFetcher] .PeekMessageComplete: Peek message complete.");

            Exception exception = null;

            System.Messaging.Message message         = null;
            bool             needRetry               = false;
            RefCountedCursor storedMessagePeekCursor = ar.AsyncState as RefCountedCursor;

            this.rwlockMessagePeekCursorField.EnterReadLock();
            try
            {
                try
                {
                    //
                    // Check if target queue is disposed. If so, don't call EndPeek.  However, the check doesn't guarantee
                    // that msmqQueueField is valid when EndPeek is invoked on it. So ObjectDisposedException shall be handled.
                    //
                    if (this.isQueueDisposed)
                    {
                        BrokerTracing.TraceWarning("[MSMQMessageFetcher]) .PeekMessageComplete: target queue is disposed");
                        return;
                    }

                    message = this.msmqQueueField.EndPeek(ar);
                    Interlocked.Increment(ref this.peekCursorPosition);
                }
                catch (MessageQueueException e)
                {
                    if (this.isDisposedField)
                    {
                        this.RevertFetchCount();
                        return;
                    }

                    needRetry = MessageQueueHelper.HandleAsyncCallbackError(
                        e,
                        ref this.messagePeekActionField,
                        "[MSMQMessageFetcher] .PeekMessageComplete: EndPeek message failed, outstandingPeekCount:{0}, messageCount={1}",
                        this.outstandingFetchCount,
                        this.msmqMessageCount);

                    if (!needRetry)
                    {
                        BrokerTracing.TraceError(
                            "[MSMQMessageFetcher] .PeekMessageComplete: end peek message failed, outstandingPeekCount:{0}, messageCount:{1} Exception:{2}",
                            this.outstandingFetchCount,
                            this.msmqMessageCount,
                            e);
                        exception = e;
                    }
                }
                catch (Exception e)
                {
                    if (this.isDisposedField)
                    {
                        this.RevertFetchCount();
                        return;
                    }

                    BrokerTracing.TraceError("[MSMQMessageFetcher] .PeekMessageComplete: end peek message failed, Exception:{0}", e.ToString());
                    exception = e;
                }
                finally
                {
                    storedMessagePeekCursor.Release();
                }
            }
            finally
            {
                this.rwlockMessagePeekCursorField.ExitReadLock();
            }

            if (needRetry)
            {
                Interlocked.Increment(ref this.pendingFetchCount);
                return;
            }

            if (message == null && exception == null)
            {
                BrokerTracing.TraceWarning("[MSMQMessageFetcher] .PeekMessageComplete: EndPeek return null.");
            }

            if (message != null)
            {
                // if the message is one of the partial messages
                if (message.AppSpecific > 0 && !string.IsNullOrEmpty(message.Label))
                {
                    try
                    {
                        BrokerTracing.TraceVerbose(
                            "[MSMQMessageFetcher] .PeekMessageComplete: peek partial message with AppSpecific {0} and Label {1}.", message.AppSpecific, message.Label);
                        string[] labels    = message.Label.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
                        string   groupId   = labels[0];
                        int      msgNumber = int.Parse(labels[1]);
                        ConcurrentDictionary <int, Message> messages = this.partialMessages.GetOrAdd(groupId, (k) => new ConcurrentDictionary <int, Message>());
                        if (!messages.TryAdd(msgNumber, message))
                        {
                            BrokerTracing.TraceError(
                                "[MSMQMessageFetcher] .PeekMessageComplete: try add one of the composed messages failed. Message Label {0}.", message.Label);
                        }

                        // check if all partial messages are peeked and cached
                        if (this.partialMessageCounters.AddOrUpdate(groupId, 1, (k, v) => v + 1) == message.AppSpecific)
                        {
                            BrokerTracing.TraceVerbose(
                                "[MSMQMessageFetcher] .PeekMessageComplete: all partial messages are peeked and cached for group {0}.", groupId);
                            Message msg = new Message();
                            msg.BodyType = message.BodyType;
                            byte[]      buffer    = new byte[Constant.MSMQChunkSize];
                            List <long> lookUpIds = new List <long>(message.AppSpecific);
                            for (int i = 1; i <= message.AppSpecific; i++)
                            {
                                Message m     = messages[i];
                                int     count = m.BodyStream.Read(buffer, 0, Constant.MSMQChunkSize);
                                msg.BodyStream.Write(buffer, 0, count);
                                lookUpIds.Add(m.LookupId);
                            }
                            msg.BodyStream.Position = 0;
                            BrokerQueueItem brokerQueueItem = null;

                            // Deserialize message to BrokerQueueItem
                            try
                            {
                                brokerQueueItem = (BrokerQueueItem)this.messageFormatter.Read(msg);
                                brokerQueueItem.PersistAsyncToken.AsyncToken = lookUpIds.ToArray();
                            }
                            catch (Exception e)
                            {
                                BrokerTracing.TraceError(
                                    "[MSMQMessageFetcher] .PeekMessageComplete: deserialize message failed for composed messages with groupId {0}, Exception:{1}", groupId,
                                    e);
                                exception = e;
                            }

                            messages.Clear();
                            if (!this.partialMessages.TryRemove(groupId, out messages))
                            {
                                BrokerTracing.TraceWarning(
                                    "[MSMQMessageFetcher] .PeekMessageComplete: try to remove partial messages with groupId {0} from cahce failed.", groupId);
                            }
                            int messageCount;
                            if (!this.partialMessageCounters.TryRemove(groupId, out messageCount))
                            {
                                BrokerTracing.TraceWarning(
                                    "[MSMQMessageFetcher] .PeekMessageComplete: try to remove partial message counters with groupId {0} from cahce failed.", groupId);
                            }

                            this.HandleMessageResult(new MessageResult(brokerQueueItem, exception));
                        }
                        else
                        {
                            Interlocked.Increment(ref this.pendingFetchCount);
                        }
                    }
                    catch (Exception ex)
                    {
                        BrokerTracing.TraceError(
                            "[MSMQMessageFetcher] .PeekMessageComplete: peek composed message failed, Exception:{0}", ex);
                    }
                }
                else
                {
                    BrokerQueueItem brokerQueueItem = null;

                    // Deserialize message to BrokerQueueItem
                    try
                    {
                        brokerQueueItem = (BrokerQueueItem)this.messageFormatter.Read(message);
                        brokerQueueItem.PersistAsyncToken.AsyncToken = new long[1] {
                            message.LookupId
                        };
                    }
                    catch (Exception e)
                    {
                        BrokerTracing.TraceError(
                            "[MSMQMessageFetcher] .PeekMessageComplete: deserialize message failed, Exception:{0}",
                            e.ToString());
                        exception = e;
                    }

                    this.HandleMessageResult(new MessageResult(brokerQueueItem, exception));
                }
            }
        }
        private async Task PeekMessageAsync()
        {
            if (this.isDisposedField)
            {
                this.RevertFetchCount();
                return;
            }

            while (true)
            {
                Exception exception = null;
                if (this.pendingFetchCount < 1)
                {
                    break;
                }

                while (this.pendingFetchCount > 0)
                {
                    byte[] messageBody = null;
                    try
                    {
                        if (responseList == null || responseList.Count <= index)
                        {
                            BrokerTracing.TraceVerbose(
                                "[AzureQueueResponseFetch] .PeekMessageAsync: lastIndex={0}, ackIndex={1}",
                                lastIndex, ackIndex);
                            responseList = await AzureStorageTool.GetBatchEntityAsync(
                                this.responseTable,
                                this.lastIndex,
                                this.ackIndex);

                            index = 0;
                            BrokerTracing.TraceVerbose(
                                "[AzureQueueResponseFetch] .PeekMessageAsync: get batch entity count={0}",
                                responseList.Count);
                        }

                        if (responseList.Count > index)
                        {
                            messageBody = responseList[index].Message;
                            if (long.TryParse(responseList[index].RowKey, out var tempIndex) &&
                                tempIndex > this.lastIndex)
                            {
                                this.lastIndex = tempIndex;
                            }

                            index++;
                        }
                    }
                    catch (Exception e)
                    {
                        BrokerTracing.TraceError(
                            "[AzureQueueResponseFetch] .PeekMessageAsync: peek batch messages failed, Exception:{0}",
                            e.ToString());
                        exception = e;
                    }

                    if (messageBody == null && exception == null)
                    {
                        BrokerTracing.TraceWarning("[AzureQueueResponseFetch] .PeekMessage: null message and exception, lastIndex = {0}, ack = {1}, Count = {2}, index = {3}.",
                                                   this.lastIndex, this.ackIndex, responseList.Count, index);
                    }
                    else
                    {
                        BrokerQueueItem brokerQueueItem = null;

                        if (messageBody != null && messageBody.Length > 0)
                        {
                            // Deserialize message to BrokerQueueItem
                            try
                            {
                                brokerQueueItem = (BrokerQueueItem)this.formatter.Deserialize(
                                    await AzureStorageTool.GetMsgBody(this.blobContainer, messageBody));
                                brokerQueueItem.PersistAsyncToken.AsyncToken =
                                    brokerQueueItem.Message.Headers.RelatesTo.ToString();
                                BrokerTracing.TraceVerbose(
                                    "[AzureQueueResponseFetch] .PeekMessage: deserialize header={0} property={1}",
                                    brokerQueueItem.Message.Headers.RelatesTo,
                                    brokerQueueItem.Message.Properties);
                            }
                            catch (Exception e)
                            {
                                BrokerTracing.TraceError(
                                    "[AzureQueueResponseFetch] .PeekMessage: deserialize message failed, Exception:{0}",
                                    e.ToString());
                                exception = e;
                            }
                        }

                        this.HandleMessageResult(new MessageResult(brokerQueueItem, exception));

                        Interlocked.Decrement(ref this.pendingFetchCount);
                    }
                }

                this.CheckAndGetMoreMessages();
            }
        }