/// <summary> /// Async method for add message. If the message size hits limit, store /// it in blob and add a referral message in queue. /// </summary> /// <param name="messageData">raw data of message</param> /// <param name="messageId">wcf message Id</param> /// <param name="callback">callback method</param> /// <param name="state">state object</param> /// <returns>async state</returns> public IAsyncResult BeginAddMessage(byte[] messageData, UniqueId messageId, AsyncCallback callback, ReliableQueueClient.ReliableState state) { CloudQueueMessage message = new CloudQueueMessage(messageData); try { if (messageData.Length <= MessageSizeBoundary) { message = new CloudQueueMessage(messageData); return(this.ReliableQueue.BeginAddMessage(message, callback, state)); } } catch (ArgumentException e) { // according to the test, when payload is <= 48KB, it can fit // in a queue message. otherwise, ArgumentException occurs. but // there is no doc about this. so catch ArgumentException here, // and store message to blob below. TraceUtils.TraceWarning("AzureStorageClient", "BeginAddMessage", "BeginAddMessage failed, {0}", e); } catch (Exception ex) { TraceUtils.TraceWarning("AzureStorageClient", "BeginAddMessage", "BeginAddMessage failed, {0}", ex); throw; } TraceUtils.TraceVerbose("AzureStorageClient", "BeginAddMessage", "Upload message {0} to storage blob.", messageId); this.UploadBlob(messageData, messageId); // Store a referral message in Azure queue with the same message Id // as the original message. It redirects proxy to get real message // from the blob. Message referralMessage = Message.CreateMessage(MessageVersion.Default, string.Empty); referralMessage.Headers.MessageId = messageId; referralMessage.Headers.Add( MessageHeader.CreateHeader(Constant.MessageHeaderBlob, Constant.HpcHeaderNS, string.Empty)); message = new CloudQueueMessage(AzureQueueMessageItem.Serialize(referralMessage)); return(this.ReliableQueue.BeginAddMessage(message, callback, state)); }
/// <summary> /// Convert a cloud queue message to wcf message, may need to access /// blob to get large message. /// </summary> /// <param name="message">queue message</param> /// <returns>wcf message</returns> public Message GetWcfMessageFromQueueMessage(CloudQueueMessage message) { Message wcfMessage = AzureQueueMessageItem.Deserialize(message.AsBytes); if (wcfMessage.Headers.FindHeader(Constant.MessageHeaderBlob, Constant.HpcHeaderNS) > 0) { using (wcfMessage) { byte[] data = this.DownloadBlob(wcfMessage.Headers.MessageId); return(AzureQueueMessageItem.Deserialize(data)); } } else { return(wcfMessage); } }
/// <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(); } }