public Future <RelayMessage> Send(RelayMessage relayMessage)
        {
            var publisher = new FuturePublisher <RelayMessage>();
            var stopwatch = Stopwatch.StartNew();

            try
            {
                _transport.BeginSendMessage(relayMessage, relayMessage.IsTwoWayMessage,
                                            asyncResult =>
                {
                    try
                    {
                        _transport.EndSendMessage(asyncResult);

                        publisher.SetRelayMessageResult(relayMessage);

                        UpdateStatistics(!publisher.Future.HasError, stopwatch.ElapsedTicks);
                    }
                    catch (Exception ex)
                    {
                        UpdateStatistics(false, stopwatch.ElapsedTicks);
                        publisher.SetError(ex);
                    }
                }, null);
            }
            catch (Exception ex)
            {
                UpdateStatistics(false, stopwatch.ElapsedTicks);
                publisher.SetError(ex);
            }

            return(publisher.Future);
        }
        /// <summary>
        /// A convenience method to create an error Future for when a type is not present in the Data Relay configuration.
        /// </summary>
        /// <typeparam name="T">The type to create an error future for.</typeparam>
        /// <returns>The error future.</returns>
        public static Future <T> InvalidTypeFuture <T>()
        {
            var futureObject = new FuturePublisher <T>();

            futureObject.SetError(new InvalidOperationException(String.Format("The type \"{0}\" is not configured for use with Data Relay.", typeof(T).FullName)));
            return(futureObject.Future);
        }
Beispiel #3
0
        private Future <RelayMessage> NoMatchingServer(TypeSetting typeSetting, RelayMessage relayMessage)
        {
            var noMatchingServerMessage = String.Format("No Data Relay server is in the server mapping for group/id {0}/{1}", typeSetting.GroupName, relayMessage.Id);

            _log.ErrorFormat(noMatchingServerMessage);

            var serverNotFoundFuture = new FuturePublisher <RelayMessage>();

            serverNotFoundFuture.SetError(new ApplicationException(noMatchingServerMessage));  // TODO: use a better exception type
            return(serverNotFoundFuture.Future);
        }
Beispiel #4
0
 private static void TryNextServer(FuturePublisher <RelayMessage> publisher, RelayMessage relayMessage, Exception lastException, IEnumerator <RelayEndPoint> servers)
 {
     if (servers.MoveNext())
     {
         if (!publisher.Future.IsCanceled)
         {
             var serverResponse = servers.Current.RelayMessageSender.Send(relayMessage);
             serverResponse.OnSuccess(() => publisher.SetResult(serverResponse.Result));
             serverResponse.OnError(ex => TryNextServer(publisher, relayMessage, ex, servers));
         }
     }
     else
     {
         publisher.SetError(new ApplicationException("Send Message failed for all available matching servers.", lastException));
     }
 }
Beispiel #5
0
        /// <summary>
        /// Sends the relay message.
        /// </summary>
        /// <param name="typeSetting">The type setting.</param>
        /// <param name="relayMessage">The relay message.</param>
        /// <returns>A future with the possibly resuling RelayMessage.  Result will be null if it is a miss.</returns>
        public Future <RelayMessage> SendRelayMessage(TypeSetting typeSetting, RelayMessage relayMessage)
        {
            var endPoints = _servers.GetEndPoints(typeSetting.GroupName, relayMessage.Id);

            var endPointEnumerator = endPoints.GetEnumerator();

            if (!endPointEnumerator.MoveNext())
            {
                return(NoMatchingServer(typeSetting, relayMessage));
            }
            endPointEnumerator.Reset();

            var publisher = new FuturePublisher <RelayMessage>();

            TryNextServer(publisher, relayMessage, null, endPointEnumerator);
            return(publisher.Future);
        }
Beispiel #6
0
 /// <summary>
 /// Completes a FuturePublisher{RelayMessage} with the results of a Future{Stream}.
 /// </summary>
 /// <param name="publisher">The publisher.</param>
 /// <param name="futureStream">The future stream.</param>
 /// <returns></returns>
 public static FuturePublisher <RelayMessage> CompleteWith(this FuturePublisher <RelayMessage> publisher, Future <Stream> futureStream)
 {
     futureStream.OnComplete(() =>
     {
         if (futureStream.HasError)
         {
             publisher.SetError(futureStream.Error);
         }
         else if (futureStream.IsCanceled)
         {
             publisher.SetError(new ApplicationException("Transport operation was cancelled."));
         }
         else
         {
             try
             {
                 using (var reply = futureStream.Result)
                 {
                     if (reply == null || reply.Length == 0)
                     {
                         publisher.SetResult(default(RelayMessage));
                     }
                     else
                     {
                         var replyMessage = Serializer.Deserialize <RelayMessage>(reply, SerializerFlags.Default);
                         SetRelayMessageResult(publisher, replyMessage);
                     }
                 }
             }
             catch (Exception ex)
             {
                 publisher.SetError(ex);
             }
         }
     });
     return(publisher);
 }
Beispiel #7
0
        /// <summary>
        /// Completes a FuturePublisher{RelayMessage} with a RelayMessage.
        /// </summary>
        /// <param name="publisher">The publisher.</param>
        /// <param name="relayMessage">The relay message.</param>
        /// <returns></returns>
        public static FuturePublisher <RelayMessage> SetRelayMessageResult(this FuturePublisher <RelayMessage> publisher, RelayMessage relayMessage)
        {
            if (relayMessage.MessageType == MessageType.Get)
            {
                publisher.SetResult(relayMessage);
            }
            else
            {
                switch (relayMessage.ResultOutcome)
                {
                case RelayOutcome.Success:
                    publisher.SetResult(relayMessage);
                    break;

                case RelayOutcome.Timeout:
                    publisher.SetError(new TimeoutException(String.Format("{0} timed out.", relayMessage.MessageType)));
                    break;

                case null:
                    if (!relayMessage.IsTwoWayMessage)
                    {
                        publisher.SetResult(relayMessage);
                    }
                    else
                    {
                        publisher.SetError(new Exception(String.Format("{0} failed with {1}.", relayMessage.MessageType, relayMessage.ResultOutcome)));
                    }
                    break;

                default:
                    publisher.SetError(new Exception(String.Format("{0} failed with {1}.", relayMessage.MessageType, relayMessage.ResultOutcome)));
                    break;
                }
            }
            return(publisher);
        }