Ejemplo n.º 1
0
        /// <summary>
        /// Sends the provided <paramref name="command"></paramref> and waits for an event of <typeparamref name="TEvent"/> or exits if the specified timeout is expired.
        /// </summary>
        /// <param name="command">The <typeparamref name="TCommand"/> to send.</param>
        /// <param name="condition">A delegate to be executed over and over until it returns the <typeparamref name="TEvent"/> that is desired, return null to keep trying.</param>
        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="F:System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param>
        /// <param name="eventReceiver">If provided, is the <see cref="IEventReceiver{TAuthenticationToken}" /> that the event is expected to be returned on.</param>
        public virtual TEvent SendAndWait <TCommand, TEvent>(TCommand command, Func <IEnumerable <IEvent <TAuthenticationToken> >, TEvent> condition, int millisecondsTimeout, IEventReceiver <TAuthenticationToken> eventReceiver = null)
            where TCommand : ICommand <TAuthenticationToken>
        {
            DateTimeOffset startedAt      = DateTimeOffset.UtcNow;
            Stopwatch      mainStopWatch  = Stopwatch.StartNew();
            string         responseCode   = "200";
            bool           wasSuccessfull = false;

            IDictionary <string, string> telemetryProperties = new Dictionary <string, string> {
                { "Type", "InProcessBus" }
            };
            string telemetryName      = string.Format("{0}/{1}", command.GetType().FullName, command.Id);
            var    telemeteredCommand = command as ITelemeteredMessage;

            if (telemeteredCommand != null)
            {
                telemetryName = telemeteredCommand.TelemetryName;
            }
            telemetryName = string.Format("Command/{0}", telemetryName);

            TEvent result;

            try
            {
                if (eventReceiver != null)
                {
                    throw new NotSupportedException("Specifying a different event receiver is not yet supported.");
                }
                RouteHandlerDelegate commandHandler;
                if (!PrepareAndValidateCommand(command, out commandHandler))
                {
                    return((TEvent)(object)null);
                }

                result = (TEvent)(object)null;
                EventWaits.Add(command.CorrelationId, new List <IEvent <TAuthenticationToken> >());

                Action <IMessage> handler = commandHandler.Delegate;
                handler(command);
                Logger.LogInfo(string.Format("A command was sent of type {0}.", command.GetType().FullName));
                wasSuccessfull = true;
            }
            finally
            {
                mainStopWatch.Stop();
                TelemetryHelper.TrackDependency("InProcessBus/CommandBus", "Command", telemetryName, null, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull, telemetryProperties);
            }

            SpinWait.SpinUntil(() =>
            {
                IList <IEvent <TAuthenticationToken> > events = EventWaits[command.CorrelationId];

                result = condition(events);

                return(result != null);
            }, millisecondsTimeout, SpinWait.DefaultSleepInMilliseconds);

            TelemetryHelper.TrackDependency("InProcessBus/CommandBus", "Command/AndWait", string.Format("Command/AndWait{0}", telemetryName.Substring(7)), null, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull, telemetryProperties);
            return(result);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Sends the provided <paramref name="command"></paramref> and waits for an event of <typeparamref name="TEvent"/> or exits if the specified timeout is expired.
        /// </summary>
        /// <param name="command">The <typeparamref name="TCommand"/> to send.</param>
        /// <param name="condition">A delegate to be executed over and over until it returns the <typeparamref name="TEvent"/> that is desired, return null to keep trying.</param>
        /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="F:System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param>
        /// <param name="eventReceiver">If provided, is the <see cref="IEventReceiver{TAuthenticationToken}" /> that the event is expected to be returned on.</param>
        public virtual TEvent SendAndWait <TCommand, TEvent>(TCommand command, Func <IEnumerable <IEvent <TAuthenticationToken> >, TEvent> condition, int millisecondsTimeout, IEventReceiver <TAuthenticationToken> eventReceiver = null)
            where TCommand : ICommand <TAuthenticationToken>
        {
            if (eventReceiver != null)
            {
                throw new NotSupportedException("Specifying a different event receiver is not yet supported.");
            }
            RouteHandlerDelegate commandHandler;

            if (!PrepareAndValidateCommand(command, out commandHandler))
            {
                return((TEvent)(object)null);
            }

            TEvent result = (TEvent)(object)null;

            EventWaits.Add(command.CorrelationId, new List <IEvent <TAuthenticationToken> >());

            Action <IMessage> handler = commandHandler.Delegate;

            handler(command);

            SpinWait.SpinUntil(() =>
            {
                IList <IEvent <TAuthenticationToken> > events = EventWaits[command.CorrelationId];

                result = condition(events);

                return(result != null);
            }, millisecondsTimeout, SpinWait.DefaultSleepInMilliseconds);

            return(result);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Takes an <see cref="ICommand{TAuthenticationToken}"/> off the queue of <paramref name="queueName"/>
        /// and calls <see cref="ReceiveCommand"/>. Repeats in a loop until the queue is empty.
        /// </summary>
        /// <param name="queueName">The name of the queue process.</param>
        protected void DequeuAndProcessCommand(string queueName)
        {
            SpinWait.SpinUntil
            (
                () =>
            {
                try
                {
                    ConcurrentQueue <ICommand <TAuthenticationToken> > queue;
                    if (QueueTracker.TryGetValue(queueName, out queue))
                    {
                        while (!queue.IsEmpty)
                        {
                            ICommand <TAuthenticationToken> command;
                            if (queue.TryDequeue(out command))
                            {
                                try
                                {
                                    CorrelationIdHelper.SetCorrelationId(command.CorrelationId);
                                }
                                catch (Exception exception)
                                {
                                    Logger.LogError(string.Format("Trying to set the CorrelationId from the command type {1} for a request for the queue '{0}' failed.", queueName, command.GetType()), exception: exception);
                                }
                                try
                                {
                                    AuthenticationTokenHelper.SetAuthenticationToken(command.AuthenticationToken);
                                }
                                catch (Exception exception)
                                {
                                    Logger.LogError(string.Format("Trying to set the AuthenticationToken from the command type {1} for a request for the queue '{0}' failed.", queueName, command.GetType()), exception: exception);
                                }
                                try
                                {
                                    ReceiveCommand(command);
                                }
                                catch (Exception exception)
                                {
                                    Logger.LogError(string.Format("Processing the command type {1} for a request for the queue '{0}' failed.", queueName, command.GetType()), exception: exception);
                                    queue.Enqueue(command);
                                }
                            }
                            else
                            {
                                Logger.LogDebug(string.Format("Trying to dequeue a command from the queue '{0}' failed.", queueName));
                            }
                        }
                    }
                    else
                    {
                        Logger.LogDebug(string.Format("Trying to find the queue '{0}' failed.", queueName));
                    }

                    Thread.Sleep(100);
                }
                catch (Exception exception)
                {
                    Logger.LogError(string.Format("Dequeuing and processing a request for the queue '{0}' failed.", queueName), exception: exception);
                }

                // Always return false to keep this spinning.
                return(false);
            },
                sleepInMilliseconds: 1000
            );
        }