Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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.");
        }
Пример #6
0
        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);
        }
Пример #7
0
 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);
     }
 }
Пример #8
0
        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();
            }
        }
Пример #9
0
        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));
            }
        }
Пример #13
0
        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);
        }