From 4a8b7461b801c070c8cba9fba2f907bc200219e7 Mon Sep 17 00:00:00 2001 From: Anita Ruangrotsakun <138700973+anitarua@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:05:52 -0700 Subject: [PATCH] chore: improve resource exhausted error message (#584) * chore: improve resource exhausted error message * remove unused imports * make LimitExceededMessageWrapper a static class with static members instead * create separate method CreateWithMessageWrapper --- .../Exceptions/CacheExceptionMapper.cs | 3 +- .../Exceptions/LimitExceededException.cs | 85 ++++++++++++++++++- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/Momento.Sdk/Exceptions/CacheExceptionMapper.cs b/src/Momento.Sdk/Exceptions/CacheExceptionMapper.cs index 9ad290ee..c27b6fd6 100644 --- a/src/Momento.Sdk/Exceptions/CacheExceptionMapper.cs +++ b/src/Momento.Sdk/Exceptions/CacheExceptionMapper.cs @@ -1,5 +1,4 @@ using System; -using System.Threading.Tasks; using Grpc.Core; using Microsoft.Extensions.Logging; @@ -79,7 +78,7 @@ public SdkException Convert(Exception e, Metadata? transportMetadata = null) return new AuthenticationException(ex.Message, transportDetails); case StatusCode.ResourceExhausted: - return new LimitExceededException(ex.Message, transportDetails); + return LimitExceededException.CreateWithMessageWrapper(ex.Message, transportDetails, ex); case StatusCode.NotFound: return new NotFoundException(ex.Message, transportDetails); diff --git a/src/Momento.Sdk/Exceptions/LimitExceededException.cs b/src/Momento.Sdk/Exceptions/LimitExceededException.cs index 40cf3fee..aa99ced0 100644 --- a/src/Momento.Sdk/Exceptions/LimitExceededException.cs +++ b/src/Momento.Sdk/Exceptions/LimitExceededException.cs @@ -1,6 +1,6 @@ namespace Momento.Sdk.Exceptions; -using System; +using Grpc.Core; /// /// Requested operation couldn't be completed because system limits were hit. @@ -8,8 +8,87 @@ public class LimitExceededException : SdkException { /// - public LimitExceededException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.LIMIT_EXCEEDED_ERROR, message, transportDetails, e) + public LimitExceededException(string messageWrapper, string message, MomentoErrorTransportDetails transportDetails, RpcException? e = null) : base(MomentoErrorCode.LIMIT_EXCEEDED_ERROR, message, transportDetails, e) { + this.MessageWrapper = messageWrapper; + } + + /// + /// Creates a LimitExceededException with a message wrapper that specifies the limit that was exceeded. + /// + /// + /// + /// + /// + public static LimitExceededException CreateWithMessageWrapper(string message, MomentoErrorTransportDetails transportDetails, RpcException? e = null) { - this.MessageWrapper = "Request rate exceeded the limits for this account. To resolve this error, reduce your request rate, or contact us at support@momentohq.com to request a limit increase"; + var messageWrapper = LimitExceededMessageWrapper.UnknownLimitExceeded; + var errMetadata = e?.Trailers.Get("err")?.Value; + if (errMetadata != null) { + messageWrapper = errMetadata switch + { + "topic_subscriptions_limit_exceeded" => LimitExceededMessageWrapper.TopicSubscriptionsLimitExceeded, + "operations_rate_limit_exceeded" => LimitExceededMessageWrapper.OperationsRateLimitExceeded, + "throughput_rate_limit_exceeded" => LimitExceededMessageWrapper.ThroughputRateLimitExceeded, + "request_size_limit_exceeded" => LimitExceededMessageWrapper.RequestSizeLimitExceeded, + "item_size_limit_exceeded" => LimitExceededMessageWrapper.ItemSizeLimitExceeded, + "element_size_limit_exceeded" => LimitExceededMessageWrapper.ElementSizeLimitExceeded, + _ => LimitExceededMessageWrapper.UnknownLimitExceeded, + }; + } else { + var lowerCasedMessage = message.ToLower(); + if (lowerCasedMessage.Contains("subscribers")) { + messageWrapper = LimitExceededMessageWrapper.TopicSubscriptionsLimitExceeded; + } else if (lowerCasedMessage.Contains("operations")) { + messageWrapper = LimitExceededMessageWrapper.OperationsRateLimitExceeded; + } else if (lowerCasedMessage.Contains("throughput")) { + messageWrapper = LimitExceededMessageWrapper.ThroughputRateLimitExceeded; + } else if (lowerCasedMessage.Contains("request limit")) { + messageWrapper = LimitExceededMessageWrapper.RequestSizeLimitExceeded; + } else if (lowerCasedMessage.Contains("item size")) { + messageWrapper = LimitExceededMessageWrapper.ItemSizeLimitExceeded; + } else if (lowerCasedMessage.Contains("element size")) { + messageWrapper = LimitExceededMessageWrapper.ElementSizeLimitExceeded; + } else { + messageWrapper = LimitExceededMessageWrapper.UnknownLimitExceeded; + } + } + + return new LimitExceededException(messageWrapper, message, transportDetails, e); } } + +/// +/// Provides a specific reason for the limit exceeded error. +/// +public static class LimitExceededMessageWrapper +{ + /// + /// Topic subscriptions limit exceeded for this account. + /// + public static string TopicSubscriptionsLimitExceeded = "Topic subscriptions limit exceeded for this account"; + /// + /// Request rate limit exceeded for this account. + /// + public static string OperationsRateLimitExceeded = "Request rate limit exceeded for this account"; + + /// + /// Bandwidth limit exceeded for this account. + /// + public static string ThroughputRateLimitExceeded = "Bandwidth limit exceeded for this account"; + /// + /// Request size limit exceeded for this account. + /// + public static string RequestSizeLimitExceeded = "Request size limit exceeded for this account"; + /// + /// Item size limit exceeded for this account. + /// + public static string ItemSizeLimitExceeded = "Item size limit exceeded for this account"; + /// + /// Element size limit exceeded for this account. + /// + public static string ElementSizeLimitExceeded = "Element size limit exceeded for this account"; + /// + /// Unknown limit exceeded for this account. + /// + public static string UnknownLimitExceeded = "Limit exceeded for this account"; +} \ No newline at end of file