< Summary

Class:Azure.Messaging.EventHubs.AmqpError
Assembly:Azure.Messaging.EventHubs
File(s):C:\Git\azure-sdk-for-net\sdk\eventhub\Azure.Messaging.EventHubs\src\Amqp\AmqpError.cs
Covered lines:61
Uncovered lines:1
Coverable lines:62
Total lines:266
Line coverage:98.3% (61 of 62)
Covered branches:44
Total branches:46
Branch coverage:95.6% (44 of 46)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
get_TimeoutError()-100%100%
get_ServerBusyError()-100%100%
get_ArgumentError()-100%100%
get_ArgumentOutOfRangeError()-100%100%
get_NotFoundExpression()-100%100%
.cctor()-100%100%
CreateExceptionForResponse(...)-80%75%
CreateExceptionForError(...)-100%100%
ThrowIfErrorResponse(...)-100%87.5%
CreateException(...)-100%100%
DetermineErrorCondition(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\eventhub\Azure.Messaging.EventHubs\src\Amqp\AmqpError.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Text.RegularExpressions;
 7using Microsoft.Azure.Amqp;
 8using Microsoft.Azure.Amqp.Encoding;
 9using Microsoft.Azure.Amqp.Framing;
 10
 11namespace Azure.Messaging.EventHubs
 12{
 13    /// <summary>
 14    ///   The set of well-known error codes associated with an AMQP messages and
 15    ///   entities.
 16    /// </summary>
 17    ///
 18    internal static class AmqpError
 19    {
 20        /// <summary>
 21        ///   The status text that appears when an AMQP error was due to a missing resource.
 22        /// </summary>
 23        ///
 24        private const string NotFoundStatusText = "status-code: 404";
 25
 26        /// <summary>
 27        ///   Indicates that a timeout occurred on the link.
 28        /// </summary>
 29        ///
 14430        public static AmqpSymbol TimeoutError { get; } = AmqpConstants.Vendor + ":timeout";
 31
 32        /// <summary>
 33        ///   Indicates that the server was busy and could not allow the requested operation.
 34        /// </summary>
 35        ///
 16436        public static AmqpSymbol ServerBusyError { get; } = AmqpConstants.Vendor + ":server-busy";
 37
 38        /// <summary>
 39        ///   Indicates that an argument provided to the Event Hubs service was incorrect.
 40        /// </summary>
 41        ///
 11242        public static AmqpSymbol ArgumentError { get; } = AmqpConstants.Vendor + ":argument-error";
 43
 44        /// <summary>
 45        ///   Indicates that an argument provided to the Event Hubs service was incorrect.
 46        /// </summary>
 47        ///
 7848        public static AmqpSymbol ArgumentOutOfRangeError { get; } = AmqpConstants.Vendor + ":argument-out-of-range";
 49
 50        /// <summary>
 51        ///   The expression to test for when the service returns a "Not Found" response to determine the context.
 52        /// </summary>
 53        ///
 2654        private static Regex NotFoundExpression { get; } = new Regex("The messaging entity .* could not be found", Regex
 55
 56        /// <summary>The set of mappings from AMQP error conditions to response status codes.</summary>
 257        private static readonly IReadOnlyDictionary<AmqpResponseStatusCode, AmqpSymbol> StatusCodeMap = new Dictionary<A
 258        {
 259            { AmqpResponseStatusCode.NotFound, AmqpErrorCode.NotFound },
 260            { AmqpResponseStatusCode.NotImplemented, AmqpErrorCode.NotImplemented},
 261            { AmqpResponseStatusCode.Unauthorized, AmqpErrorCode.UnauthorizedAccess },
 262            { AmqpResponseStatusCode.Forbidden, AmqpErrorCode.ResourceLimitExceeded },
 263            { AmqpResponseStatusCode.Gone, AmqpErrorCode.Stolen.Value },
 264            { AmqpResponseStatusCode.InternalServerError, AmqpErrorCode.InternalError },
 265            { AmqpResponseStatusCode.BadRequest, ArgumentError },
 266            { AmqpResponseStatusCode.RequestTimeout, TimeoutError },
 267            { AmqpResponseStatusCode.ServiceUnavailable, ServerBusyError }
 268        };
 69
 70        /// <summary>
 71        ///   Creates the exception that corresponds to a given AMQP response message.
 72        /// </summary>
 73        ///
 74        /// <param name="response">The response to consider.</param>
 75        /// <param name="eventHubsResource">The Event Hubs resource associated with the request.</param>
 76        ///
 77        /// <returns>The exception that most accurately represents the response failure.</returns>
 78        ///
 79        public static Exception CreateExceptionForResponse(AmqpMessage response,
 80                                                           string eventHubsResource)
 81        {
 7082            if (response == null)
 83            {
 284                return new EventHubsException(eventHubsResource, Resources.UnknownCommunicationException, EventHubsExcep
 85            }
 86
 6887            if (!response.ApplicationProperties.Map.TryGetValue<string>(AmqpResponse.StatusDescription, out var descript
 88            {
 089                description = Resources.UnknownCommunicationException;
 90            }
 91
 6892            return CreateException(DetermineErrorCondition(response).Value, description, eventHubsResource);
 93        }
 94
 95        /// <summary>
 96        ///   Creates the exception that corresponds to a given AMQP error.
 97        /// </summary>
 98        ///
 99        /// <param name="error">The AMQP error to consider.</param>
 100        /// <param name="eventHubsResource">The Event Hubs resource associated with the operation.</param>
 101        ///
 102        /// <returns>The exception that most accurately represents the error that was encountered.</returns>
 103        ///
 104        public static Exception CreateExceptionForError(Error error,
 105                                                        string eventHubsResource)
 106        {
 70107            if (error == null)
 108            {
 2109                return new EventHubsException(true, eventHubsResource, Resources.UnknownCommunicationException);
 110            }
 111
 68112            return CreateException(error.Condition.Value, error.Description, eventHubsResource);
 113        }
 114
 115        /// <summary>
 116        ///   Determines if a given AMQP message response is an error and, if so, throws the
 117        ///   appropriate corresponding exception type.
 118        /// </summary>
 119        ///
 120        /// <param name="response">The AMQP response message to consider.</param>
 121        /// <param name="eventHubName">The name of the Event Hub associated with the request.</param>
 122        ///
 123        public static void ThrowIfErrorResponse(AmqpMessage response,
 124                                                string eventHubName)
 125        {
 22126            var statusCode = default(int);
 127
 22128            if ((response?.ApplicationProperties?.Map.TryGetValue(AmqpResponse.StatusCode, out statusCode) == false)
 22129                || (!AmqpResponse.IsSuccessStatus((AmqpResponseStatusCode)statusCode)))
 130            {
 18131                throw CreateExceptionForResponse(response, eventHubName);
 132            }
 4133        }
 134
 135        /// <summary>
 136        ///   Creates the exception that corresponds to a given AMQP failure scenario.
 137        /// </summary>
 138        ///
 139        /// <param name="condition">The error condition that represents the failure scenario.</param>
 140        /// <param name="description">The descriptive text to use for messaging the scenario.</param>
 141        /// <param name="eventHubsResource">The Event Hubs resource associated with the failure.</param>
 142        ///
 143        /// <returns>The exception that most accurately represents the failure scenario.</returns>
 144        ///
 145        private static Exception CreateException(string condition,
 146                                                 string description,
 147                                                 string eventHubsResource)
 148        {
 149            // The request timed out.
 150
 136151            if (string.Equals(condition, TimeoutError.Value, StringComparison.InvariantCultureIgnoreCase))
 152            {
 8153                return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.ServiceTi
 154            }
 155
 156            // The Event Hubs service was busy.
 157
 128158            if (string.Equals(condition, ServerBusyError.Value, StringComparison.InvariantCultureIgnoreCase))
 159            {
 36160                return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.ServiceBu
 161            }
 162
 163            // An argument was rejected by the Event Hubs service.
 164
 92165            if (string.Equals(condition, ArgumentError.Value, StringComparison.InvariantCultureIgnoreCase))
 166            {
 20167                return new ArgumentException(description);
 168            }
 169
 72170            if (string.Equals(condition, ArgumentOutOfRangeError.Value, StringComparison.InvariantCultureIgnoreCase))
 171            {
 4172                return new ArgumentOutOfRangeException(description);
 173            }
 174
 175            // The consumer was superseded by one with a higher owner level.
 176
 68177            if (string.Equals(condition, AmqpErrorCode.Stolen.Value, StringComparison.InvariantCultureIgnoreCase))
 178            {
 6179                return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.ConsumerD
 180            }
 181
 182            // Authorization was denied.
 183
 62184            if (string.Equals(condition, AmqpErrorCode.UnauthorizedAccess.Value, StringComparison.InvariantCultureIgnore
 185            {
 8186                return new UnauthorizedAccessException(description);
 187            }
 188
 189            // Requests are being throttled due to exceeding the service quota.
 190
 54191            if (string.Equals(condition, AmqpErrorCode.ResourceLimitExceeded.Value, StringComparison.InvariantCultureIgn
 192            {
 8193                return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.QuotaExce
 194            }
 195
 196            // The link was closed, generally this exception would be thrown for partition specific producers and would 
 197            // between an operation and a request to close a client.
 198
 46199            if (string.Equals(condition, AmqpErrorCode.IllegalState.Value, StringComparison.InvariantCultureIgnoreCase))
 200            {
 4201                return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.ClientClo
 202            }
 203
 204            // The service does not understand how to process the request.
 205
 42206            if (string.Equals(condition, AmqpErrorCode.NotAllowed.Value, StringComparison.InvariantCultureIgnoreCase))
 207            {
 4208                return new InvalidOperationException(description);
 209            }
 210
 38211            if (string.Equals(condition, AmqpErrorCode.NotImplemented.Value, StringComparison.InvariantCultureIgnoreCase
 212            {
 6213                return new NotSupportedException(description);
 214            }
 215
 216            // The Event Hubs resource was not valid or communication with the service was interrupted.
 217
 32218            if (string.Equals(condition, AmqpErrorCode.NotFound.Value, StringComparison.InvariantCultureIgnoreCase))
 219            {
 18220                if (NotFoundExpression.IsMatch(description)
 18221                    || (description.IndexOf(NotFoundStatusText, StringComparison.InvariantCultureIgnoreCase) >= 0))
 222                {
 12223                    return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.Resou
 224                }
 225
 6226                return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.ServiceCo
 227            }
 228
 229            // There was no specific exception that could be determined; fall back to a generic one.
 230
 14231            return new EventHubsException(eventHubsResource, description, EventHubsException.FailureReason.ServiceCommun
 232        }
 233
 234        /// <summary>
 235        ///   Determines the applicable error condition for a given response message.
 236        /// </summary>
 237        ///
 238        /// <param name="response">The AMQP response message to consider.</param>
 239        ///
 240        /// <returns>The AMQP error condition that best represents the response.</returns>
 241        ///
 242        private static AmqpSymbol DetermineErrorCondition(AmqpMessage response)
 243        {
 244
 245            // If there was an error condition present, use that.
 246
 68247            if (response.ApplicationProperties.Map.TryGetValue(AmqpResponse.ErrorCondition, out AmqpSymbol condition))
 248            {
 28249                return condition;
 250            }
 251
 252            // If no error condition was present, perform a reverse lookup in the mappings to determine the
 253            // condition from the response status code.
 254
 40255            if ((response.ApplicationProperties.Map.TryGetValue<int>(AmqpResponse.StatusCode, out var statusCode))
 40256                && (StatusCodeMap.TryGetValue((AmqpResponseStatusCode)statusCode, out condition)))
 257            {
 34258                return condition;
 259            }
 260
 261            // If no specific value could be determined, fall back to a generic condition.
 262
 6263            return AmqpErrorCode.InternalError;
 264        }
 265    }
 266}