/// <summary> /// Begins asynchronous processing of a single <see cref="T:MySpace.DataRelay.RelayMessage"/>. /// </summary> /// <param name="message">The <see cref="T:MySpace.DataRelay.RelayMessage"/>.</param> /// <param name="state">Callers can put any state they like here.</param> /// <param name="callback">The method to call upon completion.</param> /// <returns> /// Returns an <see cref="T:System.IAsyncResult"/>. /// </returns> public IAsyncResult BeginHandleMessage(RelayMessage message, object state, AsyncCallback callback) { if (!message.IsTwoWayMessage) { // cheat for now and just handle in messages synchronously // as long as the type doesn't use sync in messages then // we won't block on IO anyway. HandleMessage(message); return(SynchronousAsyncResult.CreateAndComplete(callback, state)); } SimpleLinkedList <Node> nodes = PrepareMessage(message, false); Node node; if (nodes.Pop(out node)) { var result = new AsynchronousResult <Node>((ar, n, m) => { n.EndHandleOutMessage(ar); int allowedRetries = NodeManager.Instance.GetRetryCountForMessage(message); while (message.ErrorType == RelayErrorType.NodeUnreachable && --allowedRetries >= 0) { if (PrepareMessage(message, true).Pop(out node)) { node.HandleOutMessage(message); } else { message.SetError(RelayErrorType.NoNodesAvailable); } } }, node, message); var origCallback = callback; if (callback != null) { callback = ar => { result.InnerResult = ar; origCallback(result); }; } result.InnerResult = node.BeginHandleOutMessage(message, callback, state); return(result); } else { message.SetError(RelayErrorType.NoNodesAvailable); } return(SynchronousAsyncResult.CreateAndComplete(callback, state)); }
/// <summary> /// Begins asynchronous processing of a single <see cref="T:MySpace.DataRelay.RelayMessage"/>. /// </summary> /// <param name="message">The <see cref="T:MySpace.DataRelay.RelayMessage"/>.</param> /// <param name="state">Callers can put any state they like here.</param> /// <param name="callback">The method to call upon completion.</param> /// <returns> /// Returns an <see cref="T:System.IAsyncResult"/>. /// </returns> public virtual IAsyncResult BeginHandleMessage(RelayMessage message, object state, AsyncCallback callback) { if (!message.IsTwoWayMessage) { // cheat for now and just handle in messages synchronously // as long as the type doesn't use sync in messages then // we won't block on IO anyway. HandleMessage(message); return(SynchronousAsyncResult.CreateAndComplete(callback, state)); } LinkedListStack <Node> nodes = PrepareMessage(message); Node node; if (nodes.Pop(out node)) { var result = new AsynchronousResult <Node>((ar, n, m) => { try { n.EndHandleOutMessage(ar); RetryHandleMessageOnError(message, node); } catch (Exception ex) { log.Error(ex); } }, node, message); var origCallback = callback; if (callback != null) { callback = ar => { result.InnerResult = ar; origCallback(result); }; } result.InnerResult = node.BeginHandleOutMessage(message, callback, state); return(result); } message.SetError(RelayErrorType.NoNodesAvailable); return(SynchronousAsyncResult.CreateAndComplete(callback, state)); }
/// <summary> /// Begins asynchronous processing of a <see cref="T:System.Collections.Generic.List`1"/> of <see cref="T:MySpace.DataRelay.RelayMessage"/>s. /// </summary> /// <param name="messages">The list of <see cref="T:MySpace.DataRelay.RelayMessage"/>s.</param> /// <param name="state">Callers can put any state they like here.</param> /// <param name="callback">The method to call upon completion.</param> /// <returns> /// Returns an <see cref="T:System.IAsyncResult"/>. /// </returns> /// <remarks> /// <para>This method simply redirects to the synchronous <see cref="HandleMessages"/> method for now. /// In the future this may change if we have compelling use-cases for making bulk message handling asynchronous.</para> /// </remarks> IAsyncResult IAsyncDataHandler.BeginHandleMessages(IList <RelayMessage> messages, object state, AsyncCallback callback) { // cheat and handle lists synchronously for now HandleMessages(messages); return(SynchronousAsyncResult.CreateAndComplete(callback, state)); }