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 } }
/// <summary> /// Receives a <see cref="BrokeredMessage"/> from the command bus, identifies a key and queues it accordingly. /// </summary> protected override void ReceiveCommand(BrokeredMessage message) { try { Logger.LogDebug(string.Format("A command message arrived with the id '{0}'.", message.MessageId)); string messageBody = message.GetBody <string>(); ICommand <TAuthenticationToken> command = MessageSerialiser.DeserialiseCommand(messageBody); CorrelationIdHelper.SetCorrelationId(command.CorrelationId); Logger.LogInfo(string.Format("A command message arrived with the id '{0}' was of type {1}.", message.MessageId, 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 message.Complete(); 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); message.Abandon(); } }
protected virtual void ReceiveCommand(BrokeredMessage message) { try { Logger.LogDebug(string.Format("A command message arrived with the id '{0}'.", message.MessageId)); string messageBody = message.GetBody <string>(); ICommand <TAuthenticationToken> command = MessageSerialiser.DeserialiseCommand(messageBody); CorrelationIdHelper.SetCorrelationId(command.CorrelationId); Logger.LogInfo(string.Format("A command message arrived with the id '{0}' was of type {1}.", message.MessageId, command.GetType().FullName)); ReceiveCommand(command); // Remove message from queue message.Complete(); 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); message.Abandon(); } }
/// <summary> /// Receives a <see cref="EventData"/> from the command bus, identifies a key and queues it accordingly. /// </summary> protected override void ReceiveCommand(PartitionContext context, EventData eventData) { // Do a manual 10 try attempt with back-off for (int i = 0; i < 10; i++) { try { #if NET452 Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); #endif #if NETSTANDARD2_0 Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset)); #endif #if NET452 string messageBody = Encoding.UTF8.GetString(eventData.GetBytes()); #endif #if NETSTANDARD2_0 string messageBody = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count); #endif ICommand <TAuthenticationToken> command = MessageSerialiser.DeserialiseCommand(messageBody); CorrelationIdHelper.SetCorrelationId(command.CorrelationId); #if NET452 Logger.LogInfo(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' was of type {3}.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset, command.GetType().FullName)); #endif #if NETSTANDARD2_0 Logger.LogInfo(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' was of type {3}.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset, command.GetType().FullName)); #endif 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 { #if NET452 Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' was of type {3} but with no Rsn property.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset, commandType)); #endif #if NETSTANDARD2_0 Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' was of type {3} but with no Rsn property.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset, commandType)); #endif // 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 context.CheckpointAsync(eventData); #if NET452 Logger.LogDebug(string.Format("A command message arrived and was processed with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); #endif #if NETSTANDARD2_0 Logger.LogDebug(string.Format("A command message arrived and was processed with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset)); #endif return; } catch (Exception exception) { // Indicates a problem, unlock message in queue #if NET452 Logger.LogError(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but failed to be process.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); #endif #if NETSTANDARD2_0 Logger.LogError(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but failed to be process.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset), exception: exception); #endif switch (i) { case 0: case 1: // 10 seconds Thread.Sleep(10 * 1000); break; case 2: case 3: // 30 seconds Thread.Sleep(30 * 1000); break; case 4: case 5: case 6: // 1 minute Thread.Sleep(60 * 1000); break; case 7: case 8: case 9: // 3 minutes Thread.Sleep(3 * 60 * 1000); break; } } } // Eventually just accept it context.CheckpointAsync(eventData); }
public virtual ICommand <TAuthenticationToken> ReceiveCommand(string messageBody, Action <ICommand <TAuthenticationToken> > receiveCommandHandler, string messageId, Action skippedAction = null, Action lockRefreshAction = null) { ICommand <TAuthenticationToken> command; try { command = MessageSerialiser.DeserialiseCommand(messageBody); } catch (JsonSerializationException exception) { JsonSerializationException checkException = exception; bool safeToExit = false; do { if (checkException.Message.StartsWith("Could not load assembly")) { safeToExit = true; break; } } while ((checkException = checkException.InnerException as JsonSerializationException) != null); if (safeToExit) { const string pattern = @"(?<=^Error resolving type specified in JSON ').+?(?='\. Path '\$type')"; Match match = new Regex(pattern).Match(exception.Message); if (match.Success) { string[] typeParts = match.Value.Split(','); if (typeParts.Length == 2) { string classType = typeParts[0]; bool isRequired = BusHelper.IsEventRequired(string.Format("{0}.IsRequired", classType)); if (!isRequired) { if (skippedAction != null) { skippedAction(); } return(null); } } } } throw; } string commandTypeName = command.GetType().FullName; CorrelationIdHelper.SetCorrelationId(command.CorrelationId); Logger.LogInfo(string.Format("A command message arrived with the {0} was of type {1}.", messageId, commandTypeName)); bool canRefresh; if (!ConfigurationManager.TryGetSetting(string.Format("{0}.ShouldRefresh", commandTypeName), out canRefresh)) { canRefresh = false; } if (canRefresh) { if (lockRefreshAction == null) { Logger.LogWarning(string.Format("A command message arrived with the {0} was of type {1} and was destined to support lock renewal, but no action was provided.", messageId, commandTypeName)); } else { lockRefreshAction(); } } receiveCommandHandler(command); return(command); }
protected virtual void ReceiveCommand(BrokeredMessage message) { try { Logger.LogDebug(string.Format("A command message arrived with the id '{0}'.", message.MessageId)); string messageBody = message.GetBody <string>(); ICommand <TAuthenticationToken> command; try { command = MessageSerialiser.DeserialiseCommand(messageBody); } catch (JsonSerializationException exception) { JsonSerializationException checkException = exception; bool safeToExit = false; do { if (checkException.Message.StartsWith("Could not load assembly")) { safeToExit = true; break; } } while ((checkException = checkException.InnerException as JsonSerializationException) != null); if (safeToExit) { const string pattern = @"(?<=^Error resolving type specified in JSON ').+?(?='\. Path '\$type')"; Match match = new Regex(pattern).Match(exception.Message); if (match.Success) { string[] typeParts = match.Value.Split(','); if (typeParts.Length == 2) { string classType = typeParts[0]; bool isRequired = BusHelper.IsEventRequired(string.Format("{0}.IsRequired", classType)); if (!isRequired) { // Remove message from queue message.Complete(); Logger.LogDebug(string.Format("A command message arrived with the id '{0}' but processing was skipped due to command settings.", message.MessageId)); return; } } } } throw; } CorrelationIdHelper.SetCorrelationId(command.CorrelationId); Logger.LogInfo(string.Format("A command message arrived with the id '{0}' was of type {1}.", message.MessageId, command.GetType().FullName)); ReceiveCommand(command); // Remove message from queue message.Complete(); 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); message.Abandon(); } }
/// <summary> /// Deserialises and processes the <paramref name="messageBody"/> received from the network through the provided <paramref name="receiveCommandHandler"/>. /// </summary> /// <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> public virtual ICommand <TAuthenticationToken> ReceiveCommand(string messageBody, Func <ICommand <TAuthenticationToken>, bool?> receiveCommandHandler, string messageId, string signature, string signingTokenConfigurationKey, Action skippedAction = null, Action lockRefreshAction = null) { ICommand <TAuthenticationToken> command; try { command = MessageSerialiser.DeserialiseCommand(messageBody); } catch (JsonSerializationException exception) { JsonSerializationException checkException = exception; bool safeToExit = false; do { if (checkException.Message.StartsWith("Could not load assembly")) { safeToExit = true; break; } } while ((checkException = checkException.InnerException as JsonSerializationException) != null); if (safeToExit) { const string pattern = @"(?<=^Error resolving type specified in JSON ').+?(?='\. Path '\$type')"; Match match = new Regex(pattern).Match(exception.Message); if (match.Success) { string[] typeParts = match.Value.Split(','); if (typeParts.Length == 2) { string classType = typeParts[0]; bool isRequired = BusHelper.IsEventRequired(string.Format("{0}.IsRequired", classType)); if (!isRequired) { if (skippedAction != null) { skippedAction(); } return(null); } } } } throw; } string commandTypeName = command.GetType().FullName; CorrelationIdHelper.SetCorrelationId(command.CorrelationId); AuthenticationTokenHelper.SetAuthenticationToken(command.AuthenticationToken); string identifyMessage = null; var identifiedEvent = command as ICommandWithIdentity <TAuthenticationToken>; if (identifiedEvent != null) { identifyMessage = string.Format(" for aggregate {0}", identifiedEvent.Rsn); } Logger.LogInfo(string.Format("A command message arrived with the {0} was of type {1}{2}.", messageId, commandTypeName, identifyMessage)); VerifySignature(signingTokenConfigurationKey, signature, "A command", messageId, commandTypeName, identifyMessage, messageBody); bool canRefresh; if (!ConfigurationManager.TryGetSetting(string.Format("{0}.ShouldRefresh", commandTypeName), out canRefresh)) { canRefresh = false; } if (canRefresh) { if (lockRefreshAction == null) { Logger.LogWarning(string.Format("A command message arrived with the {0} was of type {1} and was destined to support lock renewal, but no action was provided.", messageId, commandTypeName)); } else { lockRefreshAction(); } } // a false response means the action wasn't handled, but didn't throw an error, so we assume, by convention, that this means it was skipped. bool?result = receiveCommandHandler(command); if (result != null && !result.Value) { if (skippedAction != null) { skippedAction(); } } return(command); }