public void AmqpExceptionSerializeTest() { const string errorDescription = "No link found..."; var amqpException1 = new AmqpException(AmqpErrorCode.NotFound, errorDescription); IFormatter formatter = new NetDataContractSerializer(); using (MemoryStream memoryStream = new MemoryStream()) { formatter.Serialize(memoryStream, amqpException1); memoryStream.Position = 0; AmqpException amqpException2 = (AmqpException)formatter.Deserialize(memoryStream); Assert.False(object.ReferenceEquals(amqpException1, amqpException2), "Exceptions should not be the same instance!"); Assert.Equal(amqpException1.Message, amqpException2.Message); Assert.Equal(amqpException1.Error.Condition, amqpException2.Error.Condition); Assert.Equal(amqpException1.Error.Description, amqpException2.Error.Description); } }
public void CloseConsumerLinkDetectsAStolenPartition() { var eventHub = "fake-hub"; var terminalException = new AmqpException(new Error { Condition = AmqpErrorCode.Stolen }); var link = new ReceivingAmqpLink(new AmqpLinkSettings()); var mockConsumer = new MockAmqpConsumer(eventHub, true, terminalException); try { mockConsumer.InvokeCloseConsumerLink(link); Assert.That(GetActivePartitionStolenException(mockConsumer), Is.SameAs(terminalException)); } finally { link?.SafeClose(); } }
public static Exception GetClientException(Exception exception, string referenceId) { StringBuilder builder = new StringBuilder(); builder.AppendFormat(CultureInfo.InvariantCulture, exception.Message); if (referenceId != null) { builder.AppendFormat(CultureInfo.InvariantCulture, $"Reference: {referenceId}, {DateTime.UtcNow}"); } string message = builder.ToString(); if (exception is SocketException || exception is IOException) { return(new ServiceBusCommunicationException(message, exception)); } if (exception is AmqpException) { AmqpException amqpException = exception as AmqpException; return(ToMessagingContractException(amqpException.Error)); } if (exception is OperationCanceledException) { AmqpException amqpException = exception.InnerException as AmqpException; if (amqpException != null) { return(ToMessagingContractException(amqpException.Error)); } return(new ServiceBusException(true, message, exception)); } if (exception is TimeoutException && referenceId != null) { return(new TimeoutException(message, exception)); } return(exception); }
void HandleException(Exception ex, AmqpMessage incoming, IList <AmqpMessage> outgoing) { // Get AmqpException AmqpException amqpException = AmqpExceptionsHelper.GetAmqpException(ex); var rejected = new Rejected { Error = amqpException.Error }; ((IReceivingAmqpLink)this.Link).DisposeMessage(incoming, rejected, true, true); incoming?.Dispose(); if (outgoing != null) { foreach (AmqpMessage message in outgoing) { message.Dispose(); } } Events.ErrorSending(ex, this); }
public async Task ReceiveAsyncDetectsAndCapturesAStolenPartition() { var eventHub = "fake-hub"; var terminalException = new AmqpException(AmqpErrorCode.Stolen, "This is a terminal exception message."); var expectedException = terminalException.TranslateServiceException(eventHub); var capturedException = default(Exception); var mockConsumer = new MockAmqpConsumer(eventHub, true, terminalException); mockConsumer.MockConnectionScope .Setup(scope => scope.OpenConsumerLinkAsync( It.IsAny <string>(), It.IsAny <string>(), It.IsAny <EventPosition>(), It.IsAny <TimeSpan>(), It.IsAny <TimeSpan>(), It.IsAny <uint>(), It.IsAny <long?>(), It.IsAny <long?>(), It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <CancellationToken>())) .Throws(terminalException); try { await mockConsumer.ReceiveAsync(10, TimeSpan.FromSeconds(1), CancellationToken.None); } catch (Exception ex) { capturedException = ex; } Assert.That(capturedException, Is.Not.Null, "An exception should have been surfaced."); Assert.That(capturedException.GetType(), Is.EqualTo(expectedException.GetType()), "The captured exception was not of the expected type."); Assert.That(capturedException.Message, Is.EqualTo(expectedException.Message), "The mocked terminal exception should have been surfaced."); var preservedException = GetActivePartitionStolenException(mockConsumer); Assert.That(preservedException, Is.SameAs(terminalException), "The preserved exception should match the terminal exception."); }
public async Task ReceiveAsyncSurfacesStolenPartitionWhenInvalidated() { var eventHub = "fake-hub"; var terminalException = new AmqpException(AmqpErrorCode.Stolen, "This is a terminal exception message."); var expectedException = terminalException.TranslateServiceException(eventHub); var capturedException = default(Exception); var mockConsumer = new MockAmqpConsumer(eventHub, true, terminalException); SetActivePartitionStolenException(mockConsumer, terminalException); try { await mockConsumer.ReceiveAsync(10, TimeSpan.FromSeconds(1), CancellationToken.None); } catch (Exception ex) { capturedException = ex; } Assert.That(capturedException, Is.Not.Null, "An exception should have been surfaced."); Assert.That(capturedException.GetType(), Is.EqualTo(expectedException.GetType()), "The captured exception was not of the expected type."); Assert.That(capturedException.Message, Is.EqualTo(expectedException.Message), "The mocked terminal exception should have been surfaced."); // Because the terminal exception was injected, it should not attempt to open the actual link. mockConsumer.MockConnectionScope .Verify(scope => scope.OpenConsumerLinkAsync( It.IsAny <string>(), It.IsAny <string>(), It.IsAny <EventPosition>(), It.IsAny <TimeSpan>(), It.IsAny <TimeSpan>(), It.IsAny <uint>(), It.IsAny <long?>(), It.IsAny <long?>(), It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <CancellationToken>()), Times.Never); }
private void InvokeChannelActionInternal(Action <IModel> channelAction, DateTime startTime) { if (this.IsTimedOut(startTime)) { ConsoleLogger.ErrorWrite("Channel action timed out. Throwing exception to client."); throw new TimeoutException("The operation requested on PersistentChannel timed out."); } try { channelAction(this.Channel);//执行这个方法,ClientCommandDispatcherSingleton类的Invoke<T>方法中定义的cs.SetResult(channelAction(channel));话会被执行。 } catch (OperationInterruptedException exception) { try { AmqpException amqpException = AmqpExceptionGrammar.ParseExceptionString(exception.Message);//将AMQP错误信息,转成C#定义的异常类型 if (amqpException.Code == AmqpException.ConnectionClosed) { this.OnConnectionDisconnected(null); this.WaitForReconnectionOrTimeout(startTime); this.InvokeChannelActionInternal(channelAction, startTime); } else { this.OpenChannel(); throw; } } catch (Sprache.ParseException) { throw exception; } } catch (Exception) { this.OnConnectionDisconnected(null); this.WaitForReconnectionOrTimeout(startTime); this.InvokeChannelActionInternal(channelAction, startTime); } }
public async Task Process_CompleteWithError_WhenIncomingLinkEntityNotFound() { const string linkName = "abcd"; const string entity = "entity"; ISecurityContext securityContext = Substitute.For <ISecurityContext>(); IEntityLookup entityLookup = Substitute.For <IEntityLookup>(); ILoggerProvider loggerProvider = Substitute.For <ILoggerProvider>(); var linkProcessor = new LinkProcessor(securityContext, entityLookup, loggerProvider); entityLookup.Find(Arg.Any <string>()).Returns((Entities.IEntity)null); securityContext.IsAuthorized(Arg.Any <Connection>()).Returns(true); AmqpException exception = null; Session session = await TestAmqpHost.OpenAndLinkProcessorAsync(linkProcessor); try { var sender = new SenderLink(session, linkName, entity); var message = new Message { Properties = new Properties { MessageId = "message1" }, BodySection = new Data { Binary = Encoding.UTF8.GetBytes("hello!") } }; Func <Task> action = async() => await sender.SendAsync(message); linkProcessor.ShouldSatisfyAllConditions( () => exception = action.ShouldThrow <AmqpException>(), () => exception.Error.Condition.ShouldBe((Symbol)ErrorCode.NotFound), () => exception.Error.Description.ShouldBe("Entity not found.") ); } finally { await session.Connection.CloseAsync(); } }
public async Task Process_CompleteWithError_WhenLinkNameEmpty() { const string emptyLinkName = ""; const string entity = "entity"; ISecurityContext securityContext = Substitute.For <ISecurityContext>(); IEntityLookup entityLookup = Substitute.For <IEntityLookup>(); ILoggerProvider loggerProvider = Substitute.For <ILoggerProvider>(); var linkProcessor = new LinkProcessor(securityContext, entityLookup, loggerProvider); AmqpException exception = null; Session session = await TestAmqpHost.OpenAndLinkProcessorAsync(linkProcessor); try { var sender = new SenderLink(session, emptyLinkName, entity); var message = new Message { Properties = new Properties { MessageId = "message1" }, BodySection = new Data { Binary = Encoding.UTF8.GetBytes("hello!") } }; Func <Task> action = async() => await sender.SendAsync(message); linkProcessor.ShouldSatisfyAllConditions( () => exception = action.ShouldThrow <AmqpException>(), () => exception.Error.Condition.ShouldBe((Symbol)ErrorCode.InvalidField), () => exception.Error.Description.ShouldBe("Empty link name not allowed.") ); } finally { await session.Connection.CloseAsync(); } }
public static string GenerateTrackingId(this AmqpException exception, string backendId, string partitionId) { return(exception.GenerateTrackingId(TrackingHelper.GatewayId, backendId, partitionId)); }
public static string GenerateTrackingId(this AmqpException exception) { return(exception.GenerateTrackingId(TrackingHelper.GatewayId, string.Empty, string.Empty)); }
public static Exception ToIotHubClientContract(AmqpException amqpException) { Error error = amqpException.Error; AmqpSymbol amqpSymbol = error.Condition; string message = error.ToString(); // Generic AMQP error if (Equals(AmqpErrorCode.InternalError, amqpSymbol)) { return(new IotHubCommunicationException(message, amqpException)); } else if (Equals(AmqpErrorCode.NotFound, amqpSymbol)) { return(new DeviceNotFoundException(message, amqpException)); } else if (Equals(AmqpErrorCode.UnauthorizedAccess, amqpSymbol)) { return(new UnauthorizedException(message, amqpException)); } else if (Equals(AmqpErrorCode.DecodeError, amqpSymbol)) { return(new IotHubException(message, amqpException)); } else if (Equals(AmqpErrorCode.ResourceLimitExceeded, amqpSymbol)) { return(new IotHubException(message, amqpException)); } else if (Equals(AmqpErrorCode.NotAllowed, amqpSymbol)) { return(new InvalidOperationException(message, amqpException)); } else if (Equals(AmqpErrorCode.InvalidField, amqpSymbol)) { return(new InvalidOperationException(message, amqpException)); } else if (Equals(AmqpErrorCode.NotImplemented, amqpSymbol)) { return(new NotSupportedException(message, amqpException)); } else if (Equals(AmqpErrorCode.ResourceLocked, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.PreconditionFailed, amqpSymbol)) { return(new IotHubException(message, amqpException)); } else if (Equals(AmqpErrorCode.ResourceDeleted, amqpSymbol)) { return(new IotHubException(message, amqpException)); } else if (Equals(AmqpErrorCode.IllegalState, amqpSymbol)) { return(new IotHubException(message, amqpException)); } else if (Equals(AmqpErrorCode.FrameSizeTooSmall, amqpSymbol)) { return(new IotHubException(message, amqpException)); } // AMQP Connection Error else if (Equals(AmqpErrorCode.ConnectionForced, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.FramingError, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.ConnectionRedirect, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } // AMQP Session Error else if (Equals(AmqpErrorCode.WindowViolation, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.ErrantLink, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.HandleInUse, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.UnattachedHandle, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } // AMQP Link Error else if (Equals(AmqpErrorCode.DetachForced, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.TransferLimitExceeded, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.MessageSizeExceeded, amqpSymbol)) { return(new MessageTooLargeException(message, amqpException)); } else if (Equals(AmqpErrorCode.LinkRedirect, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } else if (Equals(AmqpErrorCode.Stolen, amqpSymbol)) { return(new AmqpIotResourceException(message, amqpException, true)); } // AMQP Transaction Error else if (Equals(AmqpErrorCode.TransactionUnknownId, amqpSymbol)) { return(new IotHubException(message, amqpException)); } else if (Equals(AmqpErrorCode.TransactionRollback, amqpSymbol)) { return(new IotHubCommunicationException(message, amqpException)); } else if (Equals(AmqpErrorCode.TransactionTimeout, amqpSymbol)) { return(new IotHubCommunicationException(message, amqpException)); } else { return(new IotHubException(message, amqpException)); } }
public static Error ToAmqpError(Exception exception, string gatewayId, bool includeStackTrace) { if (exception == null) { throw new ArgumentNullException("exception"); } Error error = new Error(); error.Description = exception.Message; if (exception is AmqpException) { AmqpException amqpException = (AmqpException)exception; error.Condition = amqpException.Error.Condition; error.Info = amqpException.Error.Info; } else if (exception is UnauthorizedAccessException || exception is UnauthorizedException) { error.Condition = AmqpErrorCode.UnauthorizedAccess; } else if (exception is NotSupportedException) { error.Condition = AmqpErrorCode.NotImplemented; } else if (exception is DeviceNotFoundException) { error.Condition = AmqpErrorCode.NotFound; } else if (exception is IotHubNotFoundException) { error.Condition = IotHubNotFoundError; } else if (exception is DeviceMessageLockLostException) { error.Condition = MessageLockLostError; } else if (exception is MessageTooLargeException) { error.Condition = AmqpErrorCode.MessageSizeExceeded; } else if (exception is DeviceMaximumQueueDepthExceededException) { error.Condition = AmqpErrorCode.ResourceLimitExceeded; } else if (exception is TimeoutException) { error.Condition = TimeoutError; } else if (exception is InvalidOperationException) { error.Condition = AmqpErrorCode.NotAllowed; } else if (exception is ArgumentOutOfRangeException) { error.Condition = ArgumentOutOfRangeError; } else if (exception is ArgumentException) { error.Condition = ArgumentError; } else if (exception is IotHubSuspendedException) { error.Condition = IotHubSuspended; } else { error.Condition = AmqpErrorCode.InternalError; error.Description = error.Description; } // we will always need this to add trackingId if (error.Info == null) { error.Info = new Fields(); } string stackTrace; if (includeStackTrace && !string.IsNullOrEmpty(stackTrace = exception.StackTrace)) { if (stackTrace.Length > MaxSizeInInfoMap) { stackTrace = stackTrace.Substring(0, MaxSizeInInfoMap); } // error.Info came from AmqpExcpetion then it contains StackTraceName already. string dummy; if (!error.Info.TryGetValue(StackTraceName, out dummy)) { error.Info.Add(StackTraceName, stackTrace); } } string trackingId; error.Info.TryGetValue(TrackingId, out trackingId); trackingId = AmqpIoTTrackingHelper.CheckAndAddGatewayIdToTrackingId(gatewayId, trackingId); error.Info.Add(TrackingId, trackingId); return(error); }