示例#1
0
        /// <summary>
        /// Process a collection of queue messages.
        /// </summary>
        /// <param name="messages">collection of the queue messages</param>
        private void ProcessMessages(IEnumerable <CloudQueueMessage> messages)
        {
            BrokerTracing.TraceInfo(SoaHelper.CreateTraceMessage("Proxy", "ProcessMessages", string.Format("Process {0} messages.", messages.Count <CloudQueueMessage>())));

            messages.AsParallel <CloudQueueMessage>()
            .ForAll <CloudQueueMessage>(
                (requestQueueMessage) =>
            {
                Message request = null;

                try
                {
                    BrokerTracing.TraceInfo(string.Format("SOA broker proxy perf1 - {0}", DateTime.UtcNow.TimeOfDay.TotalSeconds));

                    request = this.requestStorageClients.First().GetWcfMessageFromQueueMessage(requestQueueMessage);

                    this.requestMessageQueue.Add(request);

                    // this.requestMessageQueue.Enqueue(request);
                    UniqueId messageId = SoaHelper.GetMessageId(request);

                    BrokerTracing.TraceInfo(SoaHelper.CreateTraceMessage("Proxy", "Request received inqueue", string.Empty, messageId, "Request message in queue"));
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceError(SoaHelper.CreateTraceMessage("Proxy", "ProcessMessages", string.Format("Error occurs {0}", e)));
                }
            });

            this.semaphoreForWorker.Release();
        }
示例#2
0
        /// <summary>
        /// Process a collection of queue messages.
        /// </summary>
        /// <param name="messages">collection of the queue messages</param>
        private void ProcessMessages(IEnumerable <CloudQueueMessage> messages)
        {
            SessionBase.TraceSource.TraceInformation(
                SoaHelper.CreateTraceMessage(
                    "Proxy",
                    "ProcessMessages",
                    string.Format("Process {0} messages.", messages.Count <CloudQueueMessage>())));

            messages.AsParallel <CloudQueueMessage>().ForAll <CloudQueueMessage>(
                (responseQueueMessage) =>
            {
                Message response = null;

                try
                {
                    SessionBase.TraceSource.TraceInformation(
                        string.Format("SOA broker proxy perf1 - {0}", DateTime.UtcNow.TimeOfDay.TotalSeconds));

                    response = this.responseStorageClient.GetWcfMessageFromQueueMessage(responseQueueMessage);

                    var qkey = Tuple.Create(SoaHelper.GetClientDataHeaderFromMessage(response));

                    if (!this.responseMessageQueues.ContainsKey(qkey))
                    {
                        lock (this.responseMessageQueues)
                        {
                            if (!this.responseMessageQueues.ContainsKey(qkey))
                            {
                                this.responseMessageQueues.Add(qkey, new ConcurrentQueue <Message>());
                            }
                        }
                    }

                    this.responseMessageQueues[qkey].Enqueue(response);

                    UniqueId messageId = SoaHelper.GetMessageId(response);

                    SessionBase.TraceSource.TraceInformation(
                        SoaHelper.CreateTraceMessage(
                            "Proxy",
                            "Response received inqueue",
                            string.Empty,
                            messageId,
                            "Response message in queue"));

                    // do not delete the message from the queue here, depends on the long invisable timeout and hourly cleanup
                    // this.responseStorageClient.DeleteMessageAsync(responseQueueMessage, messageId);
                }
                catch (Exception e)
                {
                    SessionBase.TraceSource.TraceInformation(
                        SoaHelper.CreateTraceMessage(
                            "Proxy", "ProcessMessages", string.Format("Error occurs {0}", e)));
                }
            });

            this.semaphoreForWorker.Release();
        }
示例#3
0
        public static Guid GetMessageIdFromMessage(Message message)
        {
            Guid     guid = Guid.Empty;
            UniqueId id   = SoaHelper.GetMessageId(message);

            if (id != null)
            {
                id.TryGetGuid(out guid);
            }
            return(guid);
        }
示例#4
0
 /// <summary>
 /// Prepare addressing headers when converting messages
 /// </summary>
 /// <param name="source">indicating the source message</param>
 /// <param name="destination">indicating the destination message</param>
 public static void PrepareAddressingHeaders(Message source, Message destination)
 {
     if (destination.Headers.MessageVersion.Addressing != AddressingVersion.None)
     {
         if (source.Headers.MessageVersion.Addressing != AddressingVersion.None)
         {
             destination.Headers.MessageId = source.Headers.MessageId;
             destination.Headers.RelatesTo = source.Headers.RelatesTo;
             destination.Headers.ReplyTo   = source.Headers.ReplyTo;
             destination.Headers.To        = source.Headers.To;
             destination.Headers.FaultTo   = source.Headers.FaultTo;
             destination.Headers.From      = source.Headers.From;
         }
         else
         {
             UniqueId messageId = SoaHelper.GetMessageId(source);
             if (messageId != null)
             {
                 destination.Headers.MessageId = messageId;
             }
         }
     }
 }
        /// <summary>
        /// Receives response messages from broker's response service
        /// </summary>
        /// <param name="message">Response message</param>
        public void SendResponse(Message message)
        {
            try
            {
                int currentResponseCount = 0;

                // Reset the heartbeat since operation just succeeded
                this.session.ResetHeartbeat();

                // Reset timeout timer since a response was received
                if (this.responseHandlerTimeoutTimer != null)
                {
                    this.responseHandlerTimeoutTimer.Change(this.responseHanderTimeout, 0);
                }

                // Bug #15946: handling client side exception thrown from WebResponseHandler(when talking to rest service)
                if (string.Equals(message.Headers.Action, Constant.WebAPI_ClientSideException, StringComparison.Ordinal))
                {
                    Exception e = message.Properties[Constant.WebAPI_ClientSideException] as Exception;
                    this.InvokeCallback(new BrokerResponse <TMessage>(e, message.Headers.RelatesTo));
                    return;
                }

                // TODO: Consider whether user callback should get an EOM message
                if (!Utility.IsEOM(message))
                {
                    // If the handler is closed, timed out, closed or broker heartbeat signaled, dont forward any more requests to the user.
                    // NOTE: If some responses already slipped through its OK because we prefer that over adding a lock here
                    if (this.shuttingDown)
                    {
                        return;
                    }

                    // Create a BrokerResponse object wrapper for the message object. A copy of the message must be created
                    MessageBuffer messageBuffer = null;
                    try
                    {
                        messageBuffer = message.CreateBufferedCopy(Constant.MaxBufferSize);
                    }
                    catch (Exception e)
                    {
                        Utility.LogError("AsyncResponseCallback.SendResponse received exception - {0}", e);
                        this.InvokeCallback(new BrokerResponse <TMessage>(e, message.Headers.RelatesTo));
                        return;
                    }

                    BrokerResponse <TMessage> brokerResponse = this.CreateResponse(BrokerClientBase.GetActionFromResponseMessage(message),
                                                                                   !message.IsFault ? message.Headers.Action : String.Empty,
                                                                                   messageBuffer,
                                                                                   message.Headers.RelatesTo == null ? SoaHelper.GetMessageId(message) : message.Headers.RelatesTo);

                    BrokerResponse <TMessage> lastResponse = null;

                    if (this.ignoreIsLastResponseProperty)
                    {
                        lastResponse = brokerResponse;
                    }
                    else
                    {
                        // Atomically swap out the last response.
                        lastResponse = Interlocked.Exchange <BrokerResponse <TMessage> >(ref this.lastBrokerResponse, brokerResponse);
                    }

                    // If there was a previous last response
                    if (lastResponse != null)
                    {
                        // Send it to the callback
                        this.InvokeCallback(lastResponse);

                        // Increment response count
                        currentResponseCount = Interlocked.Increment(ref this.currentResponseCount);
                    }

                    // If the caller wants all messages at once, do so.
                    // Else we always request ResponseWindowSize * 2 messages. If we get to
                    // the end of a window, request another
                    if (this.responseWindowSize != Constant.GetResponse_All && currentResponseCount != 0 &&
                        (currentResponseCount + 1) % this.responseWindowSize == 0)
                    {
                        // Call async version and block on completion in order to workaround System.Net.Socket bug #750028
                        try
                        {
                            SessionBase.TraceSource.TraceInformation("GetResponse : currentResponseCount {0} : clientId {1}", currentResponseCount, this.clientId);
                            this.responseService.GetResponses(
                                this.action,
                                this.callbackManagerId,
                                GetResponsePosition.Current,
                                this.responseWindowSize,
                                this.clientId);
                        }
                        catch (FaultException <SessionFault> e)
                        {
                            throw Utility.TranslateFaultException(e);
                        }
                    }
                }

                // If this is a client purged fault, return that exception in a BrokerResponse
                else
                {
                    TypedMessageConverter endOfResponsesConverter = TypedMessageConverter.Create(typeof(EndOfResponses), Constant.EndOfMessageAction);
                    EndOfResponses        endOfResponses          = (EndOfResponses)endOfResponsesConverter.FromMessage(message);

                    switch (endOfResponses.Reason)
                    {
                    case EndOfResponsesReason.ClientPurged:
                        this.InvokeCallback(new BrokerResponse <TMessage>(SessionBase.ClientPurgedException, new UniqueId(Guid.Empty)));
                        break;

                    case EndOfResponsesReason.ClientTimeout:
                        this.InvokeCallback(new BrokerResponse <TMessage>(SessionBase.ClientTimeoutException, new UniqueId(Guid.Empty)));
                        break;

                    default:
                        // Save how many responses are expected (minus 1 for the last response)
                        System.Diagnostics.Debug.Assert(endOfResponses.Count > 0, "Response count should also be positive number");
                        this.expectedResponseCount = endOfResponses.Count - 1;
                        break;
                    }
                }

                if (!this.ignoreIsLastResponseProperty)
                {
                    // Check to see if we receive the EOM message and all the responses.
                    // If so pass last response to callback marked as such. Also make
                    // sure this isnt called again with a lock.
                    if (this.expectedResponseCount == this.currentResponseCount)
                    {
                        lock (this.lastResponseLock)
                        {
                            if (this.expectedResponseCount == this.currentResponseCount)
                            {
                                // Mark the response as the last one
                                this.lastBrokerResponse.isLastResponse = true;

                                // Send last response to callback. Note since currentResponseCount
                                // is incremented after responses are sent to the callback, the
                                // callback will not be processing any other responses at this time.
                                this.InvokeCallback(this.lastBrokerResponse);

                                this.expectedResponseCount = -1;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // Log and eat unhandled user exceptions from their calback
                Utility.LogError("Unhandled exception processing response - {0}", e);
            }
        }
示例#6
0
        /// <summary>
        /// Receives new response messages from broker
        /// </summary>
        /// <param name="response">Response message</param>
        void IResponseServiceCallback.SendResponse(Message response)
        {
            MessageBuffer  messageBuffer       = null;
            EndOfResponses endOfResponses      = null;
            Exception      clientSideException = null;
            bool           isEOM = false;

            // Reset the heartbeat since operation just succeeded
            this.session.ResetHeartbeat();

            try
            {
                // Check whether this is an EOM message
                isEOM = Utility.IsEOM(response);

                if (!isEOM)
                {
                    // If not EOM, create a copy of the message's buffer so it can be deserialized
                    // A copy is needed because WCF will dispose this message when the callback returns
                    // Alternatively we could deserialize the entire message but we want
                    //  callback to be quick and we may wind up deserializing messages the user
                    //  never looks at (i.e. just checks user data or exits enum early)
                    try
                    {
                        messageBuffer = response.CreateBufferedCopy(Constant.MaxBufferSize);
                    }
                    catch (Exception e)
                    {
                        SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}][BrokerResponseEnumerator] Failed to create message buffer from the response message: {1}", this.session.Id, e);
                        clientSideException = e;
                    }
                }
                else
                {
                    // If EOM, deserialize EndOfResponses message
                    endOfResponses = (EndOfResponses)this.endOfResponsesConverter.FromMessage(response);
                }

                string messageId = String.Empty;
                try
                {
                    messageId = SoaHelper.GetMessageId(response).ToString();
                }
                catch
                {
                    // Swallow possible ObjectDisposedException
                }

                SessionBase.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "[Session:{0}][BrokerResponseEnumerator] Response received from broker. IsEOM = {1}, MessageId = {2}", this.session.Id, isEOM, messageId);

                lock (this.responsesLock)
                {
                    // If the enumerator is disposing or disposed, return
                    if (this.isDisposeCalled)
                    {
                        return;
                    }

                    // If this is not an EOM message
                    if (!isEOM)
                    {
                        string actionFromResponse = BrokerClientBase.GetActionFromResponseMessage(response);

                        // Save the response in the current window
                        MessageWindowItem messageItem = new MessageWindowItem(
                            messageBuffer,
                            actionFromResponse,
                            !response.IsFault ? response.Headers.Action : String.Empty,
                            response.Headers.RelatesTo == null ? SoaHelper.GetMessageId(response) : response.Headers.RelatesTo);

                        // Bug #15946: handling client side exception thrown from WebResponseHandler(when talking to rest service)
                        // To propagate the client side exception to BrokerResponseEnumerator api, store the exception in MessageWindowItem
                        if (string.Equals(response.Headers.Action, Constant.WebAPI_ClientSideException, StringComparison.Ordinal))
                        {
                            clientSideException = response.Properties[Constant.WebAPI_ClientSideException] as Exception;
                        }
                        messageItem.CarriedException = clientSideException;

                        this.currentReceiveWindow.Enqueue(messageItem);

                        // Increment the current number of responses
                        this.currentResponseCount++;

                        // Lower number of outstanding requests
                        if (Interlocked.Decrement(ref this.outstandingRequestCount) == 0)
                        {
                            try
                            {
                                this.GetMoreResponses(false, ResponseWindowSize);
                            }
                            catch (Exception e)
                            {
                                SessionBase.TraceSource.TraceEvent(TraceEventType.Error,
                                                                   0, "[Session:{0}][BrokerResponseEnumerator] Failed to get more responses in SendResponse context: {1}", this.session.Id, e);

                                // Send broker down signal since connection to broker might be bad
                                ((IResponseServiceCallback)this).SendBrokerDownSignal(false);
                            }
                        }

                        // If the current window is full or there are no more responses
                        if (this.currentReceiveWindow.Count == ResponseWindowSize ||
                            this.currentResponseCount == this.totalResponseCount)
                        {
                            // Disable the flush timer
                            this.flushResponsesTimer.Change(Timeout.Infinite, Timeout.Infinite);

                            // Immediately flush the receive window
                            this.FlushCurrentReceiveWindow();
                        }

                        // Otherwise reset the flushtimer to the full interval
                        else
                        {
                            this.flushResponsesTimer.Change(this.flushResponsesTimerInterval, Timeout.Infinite);
                        }
                    }
                    else
                    {
                        // If we already received an EOM, ignore any others. We may get multiple EOM since
                        // more responses are requested until we get EOM. This can lead to overrequesting.
                        if (this.totalResponseCount != -1)
                        {
                            return;
                        }

                        // Save total response count
                        this.totalResponseCount   = endOfResponses.Count;
                        this.endOfResponsesReason = endOfResponses.Reason;

                        // If there are no more responses
                        if (this.currentResponseCount == this.totalResponseCount)
                        {
                            // Make the current receive window available to enumerator if it has responses
                            if (this.currentReceiveWindow.Count != 0)
                            {
                                this.responsesWindows.Enqueue(this.currentReceiveWindow);
                                this.currentReceiveWindow = new Queue <MessageWindowItem>();
                            }

                            // Notify enumerator that a new window is available. Notify even if
                            // its empty since it allows MoveNext to exit and return there are no
                            // more items
                            this.newResponseWindowOrEOM.Set();
                        }
                    }
                }
            }
            catch (Exception e)
            {
                // If we get an exception here log and dispose the enum
                this.Dispose();

                SessionBase.TraceSource.TraceEvent(TraceEventType.Error, 0, "[Session:{0}][BrokerResponseEnumerator] Unhandled exception in response enumerator callback :{1}", this.session.Id, e);
            }
        }
示例#7
0
            /// <summary>
            /// Async Pattern. Callback of BeginProcessMessage method.
            /// </summary>
            /// <param name="state">state object</param>
            private void InternalBeginAddRequest(object state)
            {
                Message requestMessage = null;

                SessionBase.TraceSource.TraceInformation(
                    SoaHelper.CreateTraceMessage(
                        "MessageSender.Worker",
                        "InternalBeginAddRequest",
                        "Request queue length is {0}.", this.requestMessages.Count));

                try
                {
                    if (!this.requestMessages.TryDequeue(out requestMessage))
                    {
                        SessionBase.TraceSource.TraceInformation(
                            SoaHelper.CreateTraceMessage(
                                "MessageSender.Worker",
                                "InternalBeginAddRequest",
                                "Local response cache is empty."));
                    }
                }
                catch (Exception e)
                {
                    SessionBase.TraceSource.TraceInformation(
                        SoaHelper.CreateTraceMessage(
                            "MessageSender.Worker",
                            "InternalBeginAddRequest",
                            string.Format("Failed to get response from local cache, {0}", e)));
                }

                if (requestMessage == null)
                {
                    SessionBase.TraceSource.TraceInformation(
                        SoaHelper.CreateTraceMessage(
                            "MessageSender.Worker",
                            "InternalBeginAddRequest",
                            string.Format("Get null request from local cache, trigger the time to wait")));

                    this.TriggerTimer();

                    return;
                }

                try
                {
                    UniqueId messageId = SoaHelper.GetMessageId(requestMessage);

                    if (messageId == null)
                    {
                        messageId = new UniqueId();
                    }

                    ReliableQueueClient.ReliableState reliableState = new ReliableQueueClient.ReliableState(requestMessage, messageId);

                    byte[] messageData;

                    using (requestMessage)
                    {
                        messageData = AzureQueueMessageItem.Serialize(requestMessage);
                    }

                    this.waitHandler.Reset();

                    this.requestStorageClient.BeginAddMessage(messageData, messageId, this.AddMessageCallback, reliableState);
                }
                catch (Exception e)
                {
                    this.waitHandler.Set();

                    SessionBase.TraceSource.TraceInformation(
                        SoaHelper.CreateTraceMessage(
                            "MessageSender.Worker",
                            "InternalBeginAddRequest",
                            "Failed to add response message, {0}", e));

                    this.TriggerTimer();
                }
            }
示例#8
0
            /// <summary>
            /// Async Pattern. Callback of BeginProcessMessage method.
            /// </summary>
            /// <param name="state">state object</param>
            private void InternalBeginAddResponse(object state)
            {
                Message responseMessage = null;
                Tuple <ConcurrentQueue <Message>, AzureStorageClient> messageClient = null;

                try
                {
                    foreach (Tuple <ConcurrentQueue <Message>, AzureStorageClient> responseMessageClient in this.responseMessageClients.Values)
                    {
                        if (!responseMessageClient.Item1.TryDequeue(out responseMessage))
                        {
                            BrokerTracing.TraceInfo(
                                SoaHelper.CreateTraceMessage(
                                    "MessageSender.Worker",
                                    "InternalBeginAddResponse",
                                    "Local response cache is empty."));
                        }
                        else
                        {
                            messageClient = responseMessageClient;
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    BrokerTracing.TraceError(
                        SoaHelper.CreateTraceMessage(
                            "MessageSender.Worker",
                            "InternalBeginAddResponse",
                            string.Format("Failed to get response from local cache, {0}", e)));
                }

                if (responseMessage == null)
                {
                    this.TriggerTimer();

                    return;
                }

                BrokerTracing.TraceInfo(
                    SoaHelper.CreateTraceMessage(
                        "MessageSender.Worker",
                        "InternalBeginAddResponse",
                        "Retrieved message from local response cache."));

                try
                {
                    UniqueId messageId = SoaHelper.GetMessageId(responseMessage);

                    if (messageId == null)
                    {
                        messageId = new UniqueId();
                    }

                    ReliableQueueClient.ReliableState reliableState = new ReliableQueueClient.ReliableState(responseMessage, messageClient, messageId);

                    this.waitHandler.Reset();

                    byte[] messageData;

                    using (responseMessage)
                    {
                        messageData = AzureQueueMessageItem.Serialize(responseMessage);
                    }

                    messageClient.Item2.BeginAddMessage(messageData, messageId, this.AddMessageCallback, reliableState);
                }
                catch (Exception e)
                {
                    this.waitHandler.Set();

                    BrokerTracing.TraceError(
                        SoaHelper.CreateTraceMessage(
                            "MessageSender.Worker",
                            "InternalBeginAddResponse",
                            "Failed to add response message, {0}", e));

                    this.TriggerTimer();
                }
            }
示例#9
0
        /// <summary>
        /// Retrieve message id from a BrokerQueueItem instance
        /// </summary>
        /// <param name="messageItem">the BrokerQueueItem instance</param>
        /// <returns>message id of the message represented by the BrokerQueueItem instance</returns>
        private static string GetMessageId(BrokerQueueItem messageItem)
        {
            UniqueId messageId = SoaHelper.GetMessageId(messageItem.Message);

            return(messageId == null ? string.Empty : messageId.ToString());
        }