Skip to content

Commit

Permalink
More updates to exceptions thrown (#2081)
Browse files Browse the repository at this point in the history
  • Loading branch information
vinagesh authored Jul 12, 2021
1 parent df9b34a commit 69ea493
Show file tree
Hide file tree
Showing 8 changed files with 22 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
namespace Microsoft.Azure.Devices.Client.Exceptions
{
/// <summary>
/// The exception that is thrown when an attempt to enqueue a message fails because the message queue for the device is already full.
/// This exception actually corresponds to IoTHubQuotaExceeded. For more information on what causes this error
/// and steps to resolve, see <see href="https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-troubleshoot-error-403002-iothubquotaexceeded"/>.
/// The exception type has not been changed to avoid breaking changes but the inner exception has the correct exception type.
/// </summary>
[Serializable]
public sealed class DeviceMaximumQueueDepthExceededException : IotHubException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
namespace Microsoft.Azure.Devices.Client.Exceptions
{
/// <summary>
/// The exception that is thrown when an attempt to communicate with a device fails because the lock token was lost (if the connection is lost and regained for example). This timeout has the same effect as if the message was abandonned.
/// This exception is thrown when attempting to reject/abandon/complete a cloud-to-device message with a lock
/// token that has already expired. The lock token expires after the lock timeout set by the service, or if your
/// client connection was lost and regained while receiving the message but before you could reject/abandon/complete it.
/// </summary>
/// <remarks>
/// An abandoned message will be re-enqueued in the per-device queue, and the <see cref="DeviceClient"/> instance will receive it again. A rejected message will be deleted from the queue and not received again by the device.
/// An abandoned message will be re-enqueued in the per-device/module queue, and the <see cref="DeviceClient"/> instance will receive it again.
/// A rejected message will be deleted from the queue and not received again by the device.
/// For more information on the cause for this error and how to resolve, see <see href="https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-troubleshoot-error-412002-devicemessagelocklost"/>.
/// For more information on cloud-to-device message lifecycle, see <see href="https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messages-c2d#the-cloud-to-device-message-life-cycle"/>.
/// </remarks>
[Serializable]
public class DeviceMessageLockLostException : IotHubException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
namespace Microsoft.Azure.Devices.Client.Exceptions
{
/// <summary>
/// The exception that is thrown when an attempt to communicate with a device fails because the given device identifier cannot be found.
/// The exception is thrown when the device is disabled and will be used to set the status to device disabled in the
/// connection status handler. This exception also corresponds to the following error codes on operation responses:
/// <list>
/// <item>AmqpErrorCode.NotFound</item>
/// <item>HttpStatusCode.NotFound</item>
/// <item>HttpStatusCode.NoContent</item>
/// </list>
/// </summary>
[Serializable]
public sealed class DeviceNotFoundException : IotHubException
Expand Down
2 changes: 1 addition & 1 deletion iothub/device/src/Common/Exceptions/ServerBusyException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Devices.Client.Exceptions
/// The exception that is thrown when the IoT Hub is busy.
/// </summary>
/// <remarks>
/// This exception typically means the service is unavilable due to high load or an unexpected error and is usually transient. The best course of action is to retry your operation after some time. By default, the SDK will utilize the <see cref="ExponentialBackoff"/> retry strategy.
/// This exception typically means the service is unavailable due to high load or an unexpected error and is usually transient. The best course of action is to retry your operation after some time. By default, the SDK will utilize the <see cref="ExponentialBackoff"/> retry strategy.
/// </remarks>
[Serializable]
public sealed class ServerBusyException : IotHubException
Expand Down
181 changes: 0 additions & 181 deletions iothub/service/src/Common/Data/AmqpErrorMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,187 +10,6 @@ namespace Microsoft.Azure.Devices.Common.Exceptions
{
internal static class AmqpErrorMapper
{
private const int MaxSizeInInfoMap = 32 * 1024;

public static Tuple<string, string, string> GenerateError(Exception ex)
{
if (ex is DeviceNotFoundException deviceNotFoundException)
{
return Tuple.Create(AmqpErrorCode.NotFound.ToString(), deviceNotFoundException.Message, deviceNotFoundException.TrackingId);
}

if (ex is DeviceAlreadyExistsException deviceAlreadyExistsException)
{
return Tuple.Create(IotHubAmqpErrorCode.DeviceAlreadyExists.ToString(), deviceAlreadyExistsException.Message, deviceAlreadyExistsException.TrackingId);
}

if (ex is IotHubThrottledException deviceContainerThrottledException)
{
return Tuple.Create(IotHubAmqpErrorCode.DeviceContainerThrottled.ToString(), deviceContainerThrottledException.Message, deviceContainerThrottledException.TrackingId);
}

if (ex is QuotaExceededException quotaExceededException)
{
return Tuple.Create(IotHubAmqpErrorCode.QuotaExceeded.ToString(), quotaExceededException.Message, quotaExceededException.TrackingId);
}

if (ex is DeviceMessageLockLostException messageLockLostException)
{
return Tuple.Create(IotHubAmqpErrorCode.MessageLockLostError.ToString(), messageLockLostException.Message, messageLockLostException.TrackingId);
}

if (ex is MessageTooLargeException deviceMessageTooLargeException)
{
return Tuple.Create(AmqpErrorCode.MessageSizeExceeded.ToString(), deviceMessageTooLargeException.Message, deviceMessageTooLargeException.TrackingId);
}

if (ex is DeviceMaximumQueueDepthExceededException queueDepthExceededException)
{
return Tuple.Create(AmqpErrorCode.ResourceLimitExceeded.ToString(), queueDepthExceededException.Message, queueDepthExceededException.TrackingId);
}

if (ex is PreconditionFailedException preconditionFailedException)
{
return Tuple.Create(IotHubAmqpErrorCode.PreconditionFailed.ToString(), preconditionFailedException.Message, preconditionFailedException.TrackingId);
}

if (ex is IotHubSuspendedException iotHubSuspendedException)
{
return Tuple.Create(IotHubAmqpErrorCode.IotHubSuspended.ToString(), iotHubSuspendedException.Message, iotHubSuspendedException.TrackingId);
}

return Tuple.Create(AmqpErrorCode.InternalError.ToString(), ex.ToStringSlim(), (string)null);
}

public static AmqpException ToAmqpException(Exception exception)
{
return ToAmqpException(exception, false);
}

public static AmqpException ToAmqpException(Exception exception, bool includeStackTrace)
{
Error amqpError = ToAmqpError(exception, includeStackTrace);
return new AmqpException(amqpError);
}

public static Error ToAmqpError(Exception exception)
{
return ToAmqpError(exception, false);
}

public static Error ToAmqpError(Exception exception, bool includeStackTrace)
{
if (exception == null)
{
throw new ArgumentNullException(nameof(exception));
}

var error = new Error
{
Description = exception.Message
};

if (exception is AmqpException)
{
var 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 = IotHubAmqpErrorCode.IotHubNotFoundError;
}
else if (exception is DeviceMessageLockLostException)
{
error.Condition = IotHubAmqpErrorCode.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 = IotHubAmqpErrorCode.TimeoutError;
}
else if (exception is InvalidOperationException)
{
error.Condition = AmqpErrorCode.NotAllowed;
}
else if (exception is ArgumentOutOfRangeException)
{
error.Condition = IotHubAmqpErrorCode.ArgumentOutOfRangeError;
}
else if (exception is ArgumentException)
{
error.Condition = IotHubAmqpErrorCode.ArgumentError;
}
else if (exception is PreconditionFailedException)
{
error.Condition = IotHubAmqpErrorCode.PreconditionFailed;
}
else if (exception is IotHubSuspendedException)
{
error.Condition = IotHubAmqpErrorCode.IotHubSuspended;
}
else if (exception is QuotaExceededException)
{
error.Condition = IotHubAmqpErrorCode.QuotaExceeded;
}
else if (exception is TimeoutException)
{
error.Condition = IotHubAmqpErrorCode.TimeoutError;
}
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 AmqpException then it contains StackTraceName already.
if (!error.Info.TryGetValue(IotHubAmqpProperty.StackTraceName, out string _))
{
error.Info.Add(IotHubAmqpProperty.StackTraceName, stackTrace);
}
}

error.Info.TryGetValue(IotHubAmqpProperty.TrackingId, out string trackingId);
#pragma warning disable CS0618 // Type or member is obsolete only for external dependency.
trackingId = TrackingHelper.CheckAndAddGatewayIdToTrackingId(trackingId);
#pragma warning restore CS0618 // Type or member is obsolete only for external dependency.
error.Info[IotHubAmqpProperty.TrackingId] = trackingId;

return error;
}

public static Exception GetExceptionFromOutcome(Outcome outcome)
{
Exception retException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
namespace Microsoft.Azure.Devices.Common.Exceptions
{
/// <summary>
/// The exception that is thrown when an attempt to communicate with a device fails
/// because the lock token was lost (if the connection is lost and regained for example).
/// This timeout has the same effect as if the message was abandoned.
/// This exception is not directly returned by the service for ServiceClient operations. However, the status code
/// HttpStatusCode.PreconditionFailed is converted to this exception.
/// </summary>
[Serializable]
public class DeviceMessageLockLostException : IotHubException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Devices.Common.Exceptions
/// The exception that is thrown when the IoT Hub is busy.
/// </summary>
/// <remarks>
/// This exception typically means the service is unavilable due to high load or an unexpected error and is usually transient. The best course of action is to retry your operation after some time.
/// This exception typically means the service is unavailable due to high load or an unexpected error and is usually transient. The best course of action is to retry your operation after some time.
/// </remarks>
[Serializable]
public sealed class ServerBusyException : IotHubException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Devices.Common.Exceptions
/// The exception that is thrown when the IoT Hub returned an internal service error.
/// </summary>
/// <remarks>
/// This exception typically means the IoT Hub service has encountered an unexpected error and is usually transient. Please review the <see href="https://docs.microsoft.com/azure/iot-hub/iot-hub-troubleshoot-error-500xxx-internal-errors">500xxx Internal errors</see> guide for more information. The best course of action is to retry your operation after some time. By default, the SDK will utilize the <see cref="ExponentialBackoff"/> retry strategy.
/// This exception typically means the IoT Hub service has encountered an unexpected error and is usually transient. Please review the <see href="https://docs.microsoft.com/azure/iot-hub/iot-hub-troubleshoot-error-500xxx-internal-errors">500xxx Internal errors</see> guide for more information. The best course of action is to retry your operation after some time.
/// </remarks>
[Serializable]
public sealed class ServerErrorException : IotHubException
Expand Down

0 comments on commit 69ea493

Please sign in to comment.