/// <summary> /// Creates <see cref="AzureBus{TAuthenticationToken}.NumberOfReceiversCount"/> <see cref="IMessageReceiver"/>. /// If flushing is required, any flushed <see cref="IMessageReceiver"/> has <see cref="ClientEntity.Close()"/> called on it first. /// </summary> /// <param name="manager">The <see cref="Manager"/>.</param> /// <param name="serviceBusReceivers">The receivers collection to place <see cref="IMessageReceiver"/> instances into.</param> /// <param name="topicName">The topic name.</param> /// <param name="topicSubscriptionName">The topic subscription name.</param> #endif #if NETSTANDARD2_0 /// <summary> /// Creates <see cref="AzureBus{TAuthenticationToken}.NumberOfReceiversCount"/> <see cref="IMessageReceiver"/>. /// If flushing is required, any flushed <see cref="IMessageReceiver"/> has <see cref="ClientEntity.CloseAsync()"/> called on it first. /// </summary> /// <param name="manager">The <see cref="Manager"/>.</param> /// <param name="serviceBusReceivers">The receivers collection to place <see cref="IMessageReceiver"/> instances into.</param> /// <param name="topicName">The topic name.</param> /// <param name="topicSubscriptionName">The topic subscription name.</param> #endif protected virtual void InstantiateReceiving(Manager manager, IDictionary <int, IMessageReceiver> serviceBusReceivers, string topicName, string topicSubscriptionName) { for (int i = 0; i < NumberOfReceiversCount; i++) { #if NET452 IMessageReceiver serviceBusReceiver = SubscriptionClient.CreateFromConnectionString(ConnectionString, topicName, topicSubscriptionName); #endif #if NETSTANDARD2_0 IMessageReceiver serviceBusReceiver = new MessageReceiver(ConnectionString, EntityNameHelper.FormatSubscriptionPath(topicName, topicSubscriptionName)); #endif if (serviceBusReceivers.ContainsKey(i)) { serviceBusReceivers[i] = serviceBusReceiver; } else { serviceBusReceivers.Add(i, serviceBusReceiver); } } // Remove any if the number has decreased for (int i = NumberOfReceiversCount; i < serviceBusReceivers.Count; i++) { IMessageReceiver serviceBusReceiver; if (serviceBusReceivers.TryGetValue(i, out serviceBusReceiver)) { #if NET452 serviceBusReceiver.Close(); #endif #if NETSTANDARD2_0 serviceBusReceiver.CloseAsync().Wait(1500); #endif } serviceBusReceivers.Remove(i); } }
protected override void ReceiveCommand(IMessageReceiver client, BrokeredMessage message) #endif { try { Logger.LogDebug(string.Format("A command message arrived with the id '{0}'.", message.MessageId)); string messageBody = message.GetBodyAsString(); ICommand <TAuthenticationToken> command = MessageSerialiser.DeserialiseCommand(messageBody); CorrelationIdHelper.SetCorrelationId(command.CorrelationId); #if NET452 string topicPath = serviceBusReceiver == null ? "UNKNOWN" : serviceBusReceiver.TopicPath; #endif #if NETSTANDARD2_0 string topicPath = client == null ? "UNKNOWN" : client.Path; #endif Logger.LogInfo($"A command message arrived from topic {topicPath} with the {message.MessageId} was of type {command.GetType().FullName}."); Type commandType = command.GetType(); string targetQueueName = commandType.FullName; try { object rsn = commandType.GetProperty("Rsn").GetValue(command, null); targetQueueName = string.Format("{0}.{1}", targetQueueName, rsn); } catch { Logger.LogDebug(string.Format("A command message arrived with the id '{0}' was of type {1} but with no Rsn property.", message.MessageId, commandType)); // Do nothing if there is no rsn. Just use command type name } CreateQueueAndAttachListenerIfNotExist(targetQueueName); EnqueueCommand(targetQueueName, command); // remove the original message from the incoming queue #if NET452 message.Complete(); #endif #if NETSTANDARD2_0 client.CompleteAsync(message.SystemProperties.LockToken).Wait(1500); #endif Logger.LogDebug(string.Format("A command message arrived and was processed with the id '{0}'.", message.MessageId)); } catch (Exception exception) { // Indicates a problem, unlock message in queue Logger.LogError(string.Format("A command message arrived with the id '{0}' but failed to be process.", message.MessageId), exception: exception); #if NET452 message.Abandon(); #endif #if NETSTANDARD2_0 client.AbandonAsync(message.SystemProperties.LockToken).Wait(1500); #endif } }
public async Task GetMessageAsync(CancellationToken cancellationToken, string Label, Func <BrokeredMessage, Task> callback, OnMessageOptions options) { var receiverFactory = MessagingFactory.CreateFromConnectionString(ServiceBusConnectionString); subscriptionClient = receiverFactory.CreateSubscriptionClient(topicName, subscriptionname); var doneReceiving = new TaskCompletionSource <bool>(); cancellationToken.Register( async() => { await subscriptionClient.CloseAsync(); await receiverFactory.CloseAsync(); doneReceiving.SetResult(true); }); subscriptionClient.OnMessageAsync(callback, options); await doneReceiving.Task; }
public async Task GetMessageAsync(CancellationToken cancellationToken, string Label) { var receiverFactory = MessagingFactory.CreateFromConnectionString(ServiceBusConnectionString); subscriptionClient = receiverFactory.CreateSubscriptionClient(topicName, subscriptionname); var doneReceiving = new TaskCompletionSource <bool>(); cancellationToken.Register( async() => { await subscriptionClient.CloseAsync(); await receiverFactory.CloseAsync(); doneReceiving.SetResult(true); }); subscriptionClient.OnMessageAsync( async message => { if (message.Label != null && message.ContentType != null && message.Label.Equals(Label, StringComparison.InvariantCultureIgnoreCase) && message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase)) { var body = message.GetBody <Stream>(); Message = JsonConvert.DeserializeObject(new StreamReader(body, true).ReadToEnd()).ToString(); message.Complete(); } else { await message.DeadLetterAsync("ProcessingError", "Don't know what to do with this message"); } }, new OnMessageOptions { AutoComplete = false, MaxConcurrentCalls = 1 }); await doneReceiving.Task; }
protected virtual void ReceiveEvent(IMessageReceiver client, BrokeredMessage message) #endif { DateTimeOffset startedAt = DateTimeOffset.UtcNow; Stopwatch mainStopWatch = Stopwatch.StartNew(); string responseCode = "200"; // Null means it was skipped bool? wasSuccessfull = true; string telemetryName = string.Format("Cqrs/Handle/Event/{0}", message.MessageId); ISingleSignOnToken authenticationToken = null; Guid? guidAuthenticationToken = null; string stringAuthenticationToken = null; int?intAuthenticationToken = null; IDictionary <string, string> telemetryProperties = ExtractTelemetryProperties(message, "Azure/Servicebus"); TelemetryHelper.TrackMetric("Cqrs/Handle/Event", CurrentHandles++, telemetryProperties); var brokeredMessageRenewCancellationTokenSource = new CancellationTokenSource(); try { try { Logger.LogDebug(string.Format("An event message arrived with the id '{0}'.", message.MessageId)); string messageBody = message.GetBodyAsString(); IEvent <TAuthenticationToken> @event = AzureBusHelper.ReceiveEvent(messageBody, ReceiveEvent, string.Format("id '{0}'", message.MessageId), ExtractSignature(message), SigningTokenConfigurationKey, () => { wasSuccessfull = null; telemetryName = string.Format("Cqrs/Handle/Event/Skipped/{0}", message.MessageId); responseCode = "204"; // Remove message from queue try { #if NET452 message.Complete(); #endif #if NETSTANDARD2_0 client.CompleteAsync(message.SystemProperties.LockToken).Wait(1500); #endif } catch (AggregateException aggregateException) { if (aggregateException.InnerException is MessageLockLostException) { throw new MessageLockLostException(string.Format("The lock supplied for the skipped event message '{0}' is invalid.", message.MessageId), aggregateException.InnerException); } else { throw; } } catch (MessageLockLostException exception) { throw new MessageLockLostException(string.Format("The lock supplied for the skipped event message '{0}' is invalid.", message.MessageId), exception); } Logger.LogDebug(string.Format("An event message arrived with the id '{0}' but processing was skipped due to event settings.", message.MessageId)); TelemetryHelper.TrackEvent("Cqrs/Handle/Event/Skipped", telemetryProperties); }, () => { #if NET452 AzureBusHelper.RefreshLock(brokeredMessageRenewCancellationTokenSource, message, "event"); #endif #if NETSTANDARD2_0 AzureBusHelper.RefreshLock(client, brokeredMessageRenewCancellationTokenSource, message, "event"); #endif } ); if (wasSuccessfull != null) { if (@event != null) { telemetryName = string.Format("{0}/{1}/{2}", @event.GetType().FullName, @event.GetIdentity(), @event.Id); authenticationToken = @event.AuthenticationToken as ISingleSignOnToken; if (AuthenticationTokenIsGuid) { guidAuthenticationToken = @event.AuthenticationToken as Guid?; } if (AuthenticationTokenIsString) { stringAuthenticationToken = @event.AuthenticationToken as string; } if (AuthenticationTokenIsInt) { intAuthenticationToken = @event.AuthenticationToken as int?; } var telemeteredMessage = @event as ITelemeteredMessage; if (telemeteredMessage != null) { telemetryName = telemeteredMessage.TelemetryName; } telemetryName = string.Format("Cqrs/Handle/Event/{0}", telemetryName); } // Remove message from queue try { #if NET452 message.Complete(); #endif #if NETSTANDARD2_0 client.CompleteAsync(message.SystemProperties.LockToken).Wait(1500); #endif } catch (AggregateException aggregateException) { if (aggregateException.InnerException is MessageLockLostException) { throw new MessageLockLostException(string.Format("The lock supplied for event '{0}' of type {1} is invalid.", @event.Id, @event.GetType().Name), aggregateException.InnerException); } else { throw; } } catch (MessageLockLostException exception) { throw new MessageLockLostException(string.Format("The lock supplied for event '{0}' of type {1} is invalid.", @event.Id, @event.GetType().Name), exception); } } Logger.LogDebug(string.Format("An event message arrived and was processed with the id '{0}'.", message.MessageId)); IList <IEvent <TAuthenticationToken> > events; if (EventWaits.TryGetValue(@event.CorrelationId, out events)) { events.Add(@event); } } catch (AggregateException aggregateException) { throw aggregateException.InnerException; } } catch (MessageLockLostException exception) { IDictionary <string, string> subTelemetryProperties = new Dictionary <string, string>(telemetryProperties); subTelemetryProperties.Add("TimeTaken", mainStopWatch.Elapsed.ToString()); TelemetryHelper.TrackException(exception, null, subTelemetryProperties); if (ThrowExceptionOnReceiverMessageLockLostExceptionDuringComplete) { Logger.LogError(exception.Message, exception: exception); // Indicates a problem, unlock message in queue #if NET452 message.Abandon(); #endif #if NETSTANDARD2_0 client.AbandonAsync(message.SystemProperties.LockToken).Wait(1500); #endif wasSuccessfull = false; } else { Logger.LogWarning(exception.Message, exception: exception); try { #if NET452 message.DeadLetter("LockLostButHandled", "The message was handled but the lock was lost."); #endif #if NETSTANDARD2_0 client.DeadLetterAsync(message.SystemProperties.LockToken, "LockLostButHandled", "The message was handled but the lock was lost.").Wait(1500); #endif } catch (Exception) { // Oh well, move on. #if NET452 message.Abandon(); #endif #if NETSTANDARD2_0 client.AbandonAsync(message.SystemProperties.LockToken).Wait(1500); #endif } } responseCode = "599"; } catch (UnAuthorisedMessageReceivedException exception) { TelemetryHelper.TrackException(exception, null, telemetryProperties); // Indicates a problem, unlock message in queue Logger.LogError(string.Format("An event message arrived with the id '{0}' but was not authorised.", message.MessageId), exception: exception); #if NET452 message.DeadLetter("UnAuthorisedMessageReceivedException", exception.Message); #endif #if NETSTANDARD2_0 client.DeadLetterAsync(message.SystemProperties.LockToken, "UnAuthorisedMessageReceivedException", exception.Message).Wait(1500); #endif wasSuccessfull = false; responseCode = "401"; telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); } catch (NoHandlersRegisteredException exception) { TelemetryHelper.TrackException(exception, null, telemetryProperties); // Indicates a problem, unlock message in queue Logger.LogError(string.Format("An event message arrived with the id '{0}' but no handlers were found to process it.", message.MessageId), exception: exception); #if NET452 message.DeadLetter("NoHandlersRegisteredException", exception.Message); #endif #if NETSTANDARD2_0 client.DeadLetterAsync(message.SystemProperties.LockToken, "NoHandlersRegisteredException", exception.Message).Wait(1500); #endif wasSuccessfull = false; responseCode = "501"; telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); } catch (NoHandlerRegisteredException exception) { TelemetryHelper.TrackException(exception, null, telemetryProperties); // Indicates a problem, unlock message in queue Logger.LogError(string.Format("An event message arrived with the id '{0}' but no handler was found to process it.", message.MessageId), exception: exception); #if NET452 message.DeadLetter("NoHandlerRegisteredException", exception.Message); #endif #if NETSTANDARD2_0 client.DeadLetterAsync(message.SystemProperties.LockToken, "NoHandlerRegisteredException", exception.Message).Wait(1500); #endif wasSuccessfull = false; responseCode = "501"; telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); } catch (Exception exception) { TelemetryHelper.TrackException(exception, null, telemetryProperties); // Indicates a problem, unlock message in queue Logger.LogError(string.Format("An event message arrived with the id '{0}' but failed to be process.", message.MessageId), exception: exception); #if NET452 message.Abandon(); #endif #if NETSTANDARD2_0 client.AbandonAsync(message.SystemProperties.LockToken).Wait(1500); #endif wasSuccessfull = false; responseCode = "500"; telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); } finally { // Cancel the lock of renewing the task brokeredMessageRenewCancellationTokenSource.Cancel(); TelemetryHelper.TrackMetric("Cqrs/Handle/Event", CurrentHandles--, telemetryProperties); mainStopWatch.Stop(); if (guidAuthenticationToken != null) { TelemetryHelper.TrackRequest ( telemetryName, guidAuthenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } else if (intAuthenticationToken != null) { TelemetryHelper.TrackRequest ( telemetryName, intAuthenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } else if (stringAuthenticationToken != null) { TelemetryHelper.TrackRequest ( telemetryName, stringAuthenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } else { TelemetryHelper.TrackRequest ( telemetryName, authenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } TelemetryHelper.Flush(); } }
/// <summary> /// Deserialises and processes the <paramref name="messageBody"/> received from the network through the provided <paramref name="receiveCommandHandler"/>. /// </summary> /// <param name="serviceBusReceiver">The channel the message was received on.</param> /// <param name="messageBody">A serialised <see cref="IMessage"/>.</param> /// <param name="receiveCommandHandler">The handler method that will process the <see cref="ICommand{TAuthenticationToken}"/>.</param> /// <param name="messageId">The network id of the <see cref="IMessage"/>.</param> /// <param name="signature">The signature of the <see cref="IMessage"/>.</param> /// <param name="signingTokenConfigurationKey">The configuration key for the signing token as used by <see cref="IConfigurationManager"/>.</param> /// <param name="skippedAction">The <see cref="Action"/> to call when the <see cref="ICommand{TAuthenticationToken}"/> is being skipped.</param> /// <param name="lockRefreshAction">The <see cref="Action"/> to call to refresh the network lock.</param> /// <returns>The <see cref="ICommand{TAuthenticationToken}"/> that was processed.</returns> #endif #if NETSTANDARD2_0 /// <summary> /// Deserialises and processes the <paramref name="messageBody"/> received from the network through the provided <paramref name="receiveCommandHandler"/>. /// </summary> /// <param name="client">The channel the message was received on.</param> /// <param name="messageBody">A serialised <see cref="IMessage"/>.</param> /// <param name="receiveCommandHandler">The handler method that will process the <see cref="ICommand{TAuthenticationToken}"/>.</param> /// <param name="messageId">The network id of the <see cref="IMessage"/>.</param> /// <param name="signature">The signature of the <see cref="IMessage"/>.</param> /// <param name="signingTokenConfigurationKey">The configuration key for the signing token as used by <see cref="IConfigurationManager"/>.</param> /// <param name="skippedAction">The <see cref="Action"/> to call when the <see cref="ICommand{TAuthenticationToken}"/> is being skipped.</param> /// <param name="lockRefreshAction">The <see cref="Action"/> to call to refresh the network lock.</param> /// <returns>The <see cref="ICommand{TAuthenticationToken}"/> that was processed.</returns> #endif public virtual ICommand <TAuthenticationToken> ReceiveCommand( #if NET452 IMessageReceiver serviceBusReceiver
/// <summary> /// Receives a <see cref="BrokeredMessage"/> from the command bus. /// </summary> #if NET452 protected virtual void ReceiveCommand(IMessageReceiver serviceBusReceiver, BrokeredMessage message)
public StockListenerService(SubscriptionClient subscriptionClient, StockItemHandler handler) { _subscriptionClient = subscriptionClient; _handler = handler; }
/// <summary> /// Receives a <see cref="BrokeredMessage"/> from the event bus, identifies a key and queues it accordingly. /// </summary> #if NET452 protected override void ReceiveEvent(IMessageReceiver serviceBusReceiver, BrokeredMessage message)
/// <summary> /// Receives a <see cref="BrokeredMessage"/> from the event bus. /// </summary> #if NET452 protected virtual void ReceiveEvent(IMessageReceiver serviceBusReceiver, BrokeredMessage message)