/// <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); }
/// <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); }
/// <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 ); }