diff --git a/src/Momento.Sdk/Config/Configurations.cs b/src/Momento.Sdk/Config/Configurations.cs
index e7ecd0b8..9a8a716b 100644
--- a/src/Momento.Sdk/Config/Configurations.cs
+++ b/src/Momento.Sdk/Config/Configurations.cs
@@ -14,8 +14,8 @@ namespace Momento.Sdk.Config;
public class Configurations
{
///
- /// Laptop config provides defaults suitable for a medium-to-high-latency dev environment. Permissive timeouts, retries, potentially
- /// a higher number of connections, etc.
+ /// Laptop config provides defaults suitable for a medium-to-high-latency dev environment. Permissive timeouts, retries, and
+ /// relaxed latency and throughput targets.
///
public class Laptop : Configuration
{
@@ -25,11 +25,17 @@ private Laptop(ILoggerFactory loggerFactory, IRetryStrategy retryStrategy, ITran
}
+ ///
+ /// Provides the latest recommended configuration for a Laptop environment.
+ ///
+ ///
+ ///
public static Laptop Latest(ILoggerFactory? loggerFactory = null)
{
var finalLoggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
IRetryStrategy retryStrategy = new FixedCountRetryStrategy(finalLoggerFactory, maxAttempts: 3);
ITransportStrategy transportStrategy = new StaticTransportStrategy(
+ loggerFactory: finalLoggerFactory,
maxConcurrentRequests: 100,
grpcConfig: new StaticGrpcConfiguration(deadline: TimeSpan.FromMilliseconds(15000))
);
@@ -54,11 +60,17 @@ private Default(ILoggerFactory loggerFactory, IRetryStrategy retryStrategy, ITra
}
+ ///
+ /// Provides the latest recommended configuration for an InRegion environment.
+ ///
+ ///
+ ///
public static Default Latest(ILoggerFactory? loggerFactory = null)
{
var finalLoggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
IRetryStrategy retryStrategy = new FixedCountRetryStrategy(finalLoggerFactory, maxAttempts: 3);
ITransportStrategy transportStrategy = new StaticTransportStrategy(
+ loggerFactory: finalLoggerFactory,
maxConcurrentRequests: 200,
grpcConfig: new StaticGrpcConfiguration(deadline: TimeSpan.FromMilliseconds(1100)));
return new Default(finalLoggerFactory, retryStrategy, transportStrategy);
@@ -78,11 +90,18 @@ private LowLatency(ILoggerFactory loggerFactory, IRetryStrategy retryStrategy, I
}
+ ///
+ /// Provides the latest recommended configuration for a low-latency in-region
+ /// environment.
+ ///
+ ///
+ ///
public static LowLatency Latest(ILoggerFactory? loggerFactory = null)
{
var finalLoggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
IRetryStrategy retryStrategy = new FixedCountRetryStrategy(finalLoggerFactory, maxAttempts: 3);
ITransportStrategy transportStrategy = new StaticTransportStrategy(
+ loggerFactory: finalLoggerFactory,
maxConcurrentRequests: 20,
grpcConfig: new StaticGrpcConfiguration(deadline: TimeSpan.FromMilliseconds(500))
);
diff --git a/src/Momento.Sdk/Config/Middleware/LoggingMiddleware.cs b/src/Momento.Sdk/Config/Middleware/LoggingMiddleware.cs
index 06886cd1..fc630600 100644
--- a/src/Momento.Sdk/Config/Middleware/LoggingMiddleware.cs
+++ b/src/Momento.Sdk/Config/Middleware/LoggingMiddleware.cs
@@ -14,11 +14,16 @@ public class LoggingMiddleware : IMiddleware
{
private readonly ILogger _logger;
+ ///
+ ///
+ ///
+ ///
public LoggingMiddleware(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger();
}
+ ///
public async Task> WrapRequest(
TRequest request,
CallOptions callOptions,
diff --git a/src/Momento.Sdk/Config/Middleware/PassThroughMiddleware.cs b/src/Momento.Sdk/Config/Middleware/PassThroughMiddleware.cs
index 21e79618..7dc680ff 100644
--- a/src/Momento.Sdk/Config/Middleware/PassThroughMiddleware.cs
+++ b/src/Momento.Sdk/Config/Middleware/PassThroughMiddleware.cs
@@ -7,15 +7,24 @@
namespace Momento.Sdk.Config.Middleware;
+///
+/// No-op middleware. Provided only to illustrate the simplest possible example
+/// of a middleware implementation.
+///
public class PassThroughMiddleware : IMiddleware
{
private readonly ILogger _logger;
+ ///
+ ///
+ ///
+ ///
public PassThroughMiddleware(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger();
}
+ ///
public Task> WrapRequest(
TRequest request,
CallOptions callOptions,
diff --git a/src/Momento.Sdk/Config/Retry/FixedCountRetryStrategy.cs b/src/Momento.Sdk/Config/Retry/FixedCountRetryStrategy.cs
index 78031226..d2f9e3ab 100644
--- a/src/Momento.Sdk/Config/Retry/FixedCountRetryStrategy.cs
+++ b/src/Momento.Sdk/Config/Retry/FixedCountRetryStrategy.cs
@@ -6,14 +6,26 @@
namespace Momento.Sdk.Config.Retry;
+///
+/// The most basic retry strategy; simply retries an eligible failed request the specified number of times.
+///
public class FixedCountRetryStrategy : IRetryStrategy
{
private ILoggerFactory _loggerFactory;
private ILogger _logger;
private readonly IRetryEligibilityStrategy _eligibilityStrategy;
+ ///
+ /// The maximum number of attempts that should be made before giving up on an individual request.
+ ///
public int MaxAttempts { get; }
+ ///
+ ///
+ ///
+ ///
+ /// The maximum number of attempts that should be made before giving up on an individual request.
+ /// The strategy used to determine whether a particular failed request is eligible for retry.
public FixedCountRetryStrategy(ILoggerFactory loggerFactory, int maxAttempts, IRetryEligibilityStrategy? eligibilityStrategy = null)
{
_loggerFactory = loggerFactory;
@@ -22,11 +34,17 @@ public FixedCountRetryStrategy(ILoggerFactory loggerFactory, int maxAttempts, IR
MaxAttempts = maxAttempts;
}
+ ///
+ /// Copy constructor that updates maxAttempts
+ ///
+ ///
+ /// A new FixedCountRetryStrategy instance with updated maximum number of attempts
public FixedCountRetryStrategy WithMaxAttempts(int maxAttempts)
{
return new(_loggerFactory, maxAttempts, _eligibilityStrategy);
}
+ ///
public int? DetermineWhenToRetryRequest(Status grpcStatus, TRequest grpcRequest, int attemptNumber) where TRequest : class
{
_logger.LogDebug($"Determining whether request is eligible for retry; status code: {grpcStatus.StatusCode}, request type: {grpcRequest.GetType()}, attemptNumber: {attemptNumber}, maxAttempts: {MaxAttempts}");
diff --git a/src/Momento.Sdk/Config/Retry/IRetryEligibilityStrategy.cs b/src/Momento.Sdk/Config/Retry/IRetryEligibilityStrategy.cs
index c0ebb211..59484b7a 100644
--- a/src/Momento.Sdk/Config/Retry/IRetryEligibilityStrategy.cs
+++ b/src/Momento.Sdk/Config/Retry/IRetryEligibilityStrategy.cs
@@ -4,10 +4,20 @@
namespace Momento.Sdk.Config.Retry
{
+ ///
+ /// Used to determine whether a failed request is eligible for retry.
+ ///
public interface IRetryEligibilityStrategy
{
- public ILoggerFactory? LoggerFactory { get; }
- public IRetryEligibilityStrategy WithLoggerFactory(ILoggerFactory loggerFactory);
+ ///
+ /// Given the status code and request object for a failed request, returns
+ /// true
if the request is eligible for retry, false
+ /// otherwise.
+ ///
+ ///
+ /// The gRPC status of the failed request
+ /// The original gRPC request object
+ ///
public bool IsEligibleForRetry(Status status, TRequest request) where TRequest : class;
}
}
diff --git a/src/Momento.Sdk/Config/Transport/IGrpcConfiguration.cs b/src/Momento.Sdk/Config/Transport/IGrpcConfiguration.cs
index 10bbaf08..a81b671c 100644
--- a/src/Momento.Sdk/Config/Transport/IGrpcConfiguration.cs
+++ b/src/Momento.Sdk/Config/Transport/IGrpcConfiguration.cs
@@ -20,6 +20,17 @@ public interface IGrpcConfiguration
///
public GrpcChannelOptions GrpcChannelOptions { get; }
+ ///
+ /// Copy constructor to override the Deadline
+ ///
+ ///
+ /// A new IGrpcConfiguration with the specified Deadline
public IGrpcConfiguration WithDeadline(TimeSpan deadline);
+
+ ///
+ /// Copy constructor to override the channel options
+ ///
+ ///
+ /// A new IGrpcConfiguration with the specified channel options
public IGrpcConfiguration WithGrpcChannelOptions(GrpcChannelOptions grpcChannelOptions);
}
diff --git a/src/Momento.Sdk/Config/Transport/ITransportStrategy.cs b/src/Momento.Sdk/Config/Transport/ITransportStrategy.cs
index 03e4c844..e47d9813 100644
--- a/src/Momento.Sdk/Config/Transport/ITransportStrategy.cs
+++ b/src/Momento.Sdk/Config/Transport/ITransportStrategy.cs
@@ -8,11 +8,35 @@ namespace Momento.Sdk.Config.Transport;
///
public interface ITransportStrategy
{
+ ///
+ /// The maximum number of concurrent requests that the Momento client will
+ /// allow onto the wire at a given time.
+ ///
public int MaxConcurrentRequests { get; }
+ ///
+ /// Configures the low-level gRPC settings for the Momento client's communication
+ /// with the Momento server.
+ ///
public IGrpcConfiguration GrpcConfig { get; }
- public ITransportStrategy WithLoggerFactory(ILoggerFactory loggerFactory);
+ ///
+ /// Copy constructor to update the maximum number of concurrent requests.
+ ///
+ ///
+ /// A new ITransportStrategy with the specified maxConccurrentRequests
public ITransportStrategy WithMaxConcurrentRequests(int maxConcurrentRequests);
+
+ ///
+ /// Copy constructor to update the gRPC configuration
+ ///
+ ///
+ /// A new ITransportStrategy with the specified grpcConfig
public ITransportStrategy WithGrpcConfig(IGrpcConfiguration grpcConfig);
+
+ ///
+ /// Copy constructor to update the client timeout
+ ///
+ ///
+ /// A new ITransportStrategy with the specified client timeout
public ITransportStrategy WithClientTimeout(TimeSpan clientTimeout);
}
diff --git a/src/Momento.Sdk/Config/Transport/StaticTransportStrategy.cs b/src/Momento.Sdk/Config/Transport/StaticTransportStrategy.cs
index 3f98db8a..74e0f023 100644
--- a/src/Momento.Sdk/Config/Transport/StaticTransportStrategy.cs
+++ b/src/Momento.Sdk/Config/Transport/StaticTransportStrategy.cs
@@ -5,12 +5,26 @@
namespace Momento.Sdk.Config.Transport;
-
+///
+/// The simplest way to configure gRPC for the Momento client; specifies static values for
+/// request deadline and channel options.
+///
public class StaticGrpcConfiguration : IGrpcConfiguration
{
+ ///
+ /// Maximum amount of time before a request will timeout
+ ///
public TimeSpan Deadline { get; }
+ ///
+ /// Customizations to low-level gRPC channel configuration
+ ///
public GrpcChannelOptions GrpcChannelOptions { get; }
+ ///
+ ///
+ ///
+ /// Maximum amount of time before a request will timeout
+ /// Customizations to low-level gRPC channel configuration
public StaticGrpcConfiguration(TimeSpan deadline, GrpcChannelOptions? grpcChannelOptions = null)
{
Utils.ArgumentStrictlyPositive(deadline, nameof(deadline));
@@ -18,52 +32,74 @@ public StaticGrpcConfiguration(TimeSpan deadline, GrpcChannelOptions? grpcChanne
this.GrpcChannelOptions = grpcChannelOptions ?? new GrpcChannelOptions();
}
+ ///
+ /// Copy constructor for overriding the deadline
+ ///
+ ///
+ /// A new GrpcConfiguration with the updated deadline
public IGrpcConfiguration WithDeadline(TimeSpan deadline)
{
return new StaticGrpcConfiguration(deadline, this.GrpcChannelOptions);
}
+ ///
+ /// Copy constructor for overriding the gRPC channel options
+ ///
+ ///
+ /// A new GrpcConfiguration with the specified channel options
public IGrpcConfiguration WithGrpcChannelOptions(GrpcChannelOptions grpcChannelOptions)
{
return new StaticGrpcConfiguration(this.Deadline, grpcChannelOptions);
}
}
+///
+/// The simplest way to configure the transport layer for the Momento client.
+/// Provides static values for the maximum number of concurrent requests and the
+/// gRPC configuration.
+///
public class StaticTransportStrategy : ITransportStrategy
{
- public ILoggerFactory? LoggerFactory { get; }
+ private readonly ILoggerFactory _loggerFactory;
+
+ ///
+ /// The maximum number of concurrent requests that the Momento client will
+ /// allow on the wire at one time.
+ ///
public int MaxConcurrentRequests { get; }
+ ///
+ /// Configures how Momento client interacts with the Momento service via gRPC
+ ///
public IGrpcConfiguration GrpcConfig { get; }
- public StaticTransportStrategy(int maxConcurrentRequests, IGrpcConfiguration grpcConfig, ILoggerFactory? loggerFactory = null)
+ ///
+ ///
+ ///
+ ///
+ /// The maximum number of concurrent requests that the Momento client will allow on the wire at one time.
+ /// Configures how Momento client interacts with the Momento service via gRPC
+ public StaticTransportStrategy(ILoggerFactory loggerFactory, int maxConcurrentRequests, IGrpcConfiguration grpcConfig)
{
- LoggerFactory = loggerFactory;
+ _loggerFactory = loggerFactory;
MaxConcurrentRequests = maxConcurrentRequests;
GrpcConfig = grpcConfig;
}
- public StaticTransportStrategy WithLoggerFactory(ILoggerFactory loggerFactory)
- {
- return new(MaxConcurrentRequests, GrpcConfig, loggerFactory);
- }
-
- ITransportStrategy ITransportStrategy.WithLoggerFactory(ILoggerFactory loggerFactory)
- {
- return WithLoggerFactory(loggerFactory);
- }
-
+ ///
public ITransportStrategy WithMaxConcurrentRequests(int maxConcurrentRequests)
{
- return new StaticTransportStrategy(maxConcurrentRequests, GrpcConfig, LoggerFactory);
+ return new StaticTransportStrategy(_loggerFactory, maxConcurrentRequests, GrpcConfig);
}
+ ///
public ITransportStrategy WithGrpcConfig(IGrpcConfiguration grpcConfig)
{
- return new StaticTransportStrategy(MaxConcurrentRequests, grpcConfig, LoggerFactory);
+ return new StaticTransportStrategy(_loggerFactory, MaxConcurrentRequests, grpcConfig);
}
+ ///
public ITransportStrategy WithClientTimeout(TimeSpan clientTimeout)
{
- return new StaticTransportStrategy(MaxConcurrentRequests, GrpcConfig.WithDeadline(clientTimeout), LoggerFactory);
+ return new StaticTransportStrategy(_loggerFactory, MaxConcurrentRequests, GrpcConfig.WithDeadline(clientTimeout));
}
}
diff --git a/src/Momento.Sdk/Exceptions/AlreadyExistsException.cs b/src/Momento.Sdk/Exceptions/AlreadyExistsException.cs
index 0d9c7ea0..b0ab6a38 100644
--- a/src/Momento.Sdk/Exceptions/AlreadyExistsException.cs
+++ b/src/Momento.Sdk/Exceptions/AlreadyExistsException.cs
@@ -7,6 +7,7 @@
///
public class AlreadyExistsException : SdkException
{
+ ///
public AlreadyExistsException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.ALREADY_EXISTS_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "A cache with the specified name already exists. To resolve this error, either delete the existing cache and make a new one, or use a different name";
diff --git a/src/Momento.Sdk/Exceptions/AuthenticationException.cs b/src/Momento.Sdk/Exceptions/AuthenticationException.cs
index 68a406fc..d5c53cb6 100644
--- a/src/Momento.Sdk/Exceptions/AuthenticationException.cs
+++ b/src/Momento.Sdk/Exceptions/AuthenticationException.cs
@@ -7,6 +7,7 @@
///
public class AuthenticationException : SdkException
{
+ ///
public AuthenticationException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.AUTHENTICATION_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "Invalid authentication credentials to connect to cache service";
diff --git a/src/Momento.Sdk/Exceptions/BadRequestException.cs b/src/Momento.Sdk/Exceptions/BadRequestException.cs
index 43698589..813022ed 100644
--- a/src/Momento.Sdk/Exceptions/BadRequestException.cs
+++ b/src/Momento.Sdk/Exceptions/BadRequestException.cs
@@ -7,6 +7,7 @@
///
public class BadRequestException : SdkException
{
+ ///
public BadRequestException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.BAD_REQUEST_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "The request was invalid; please contact us at support@momentohq.com";
diff --git a/src/Momento.Sdk/Exceptions/CancelledException.cs b/src/Momento.Sdk/Exceptions/CancelledException.cs
index e4bdbd2c..3bbab726 100644
--- a/src/Momento.Sdk/Exceptions/CancelledException.cs
+++ b/src/Momento.Sdk/Exceptions/CancelledException.cs
@@ -2,6 +2,9 @@
using System;
+///
+/// Operation was cancelled.
+///
public class CancelledException : SdkException
{
///
diff --git a/src/Momento.Sdk/Exceptions/FailedPreconditionException.cs b/src/Momento.Sdk/Exceptions/FailedPreconditionException.cs
index 8c46862f..192b7389 100644
--- a/src/Momento.Sdk/Exceptions/FailedPreconditionException.cs
+++ b/src/Momento.Sdk/Exceptions/FailedPreconditionException.cs
@@ -10,6 +10,7 @@ namespace Momento.Sdk.Exceptions;
///
public class FailedPreconditionException : SdkException
{
+ ///
public FailedPreconditionException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.FAILED_PRECONDITION_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "System is not in a state required for the operation's execution";
diff --git a/src/Momento.Sdk/Exceptions/InternalServerException.cs b/src/Momento.Sdk/Exceptions/InternalServerException.cs
index d2323fa2..2edc500d 100644
--- a/src/Momento.Sdk/Exceptions/InternalServerException.cs
+++ b/src/Momento.Sdk/Exceptions/InternalServerException.cs
@@ -7,6 +7,7 @@ namespace Momento.Sdk.Exceptions;
///
public class InternalServerException : SdkException
{
+ ///
public InternalServerException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.INTERNAL_SERVER_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "An unexpected error occurred while trying to fulfill the request; please contact us at support@momentohq.com";
diff --git a/src/Momento.Sdk/Exceptions/InvalidArgumentException.cs b/src/Momento.Sdk/Exceptions/InvalidArgumentException.cs
index 7828a5c5..82aff724 100644
--- a/src/Momento.Sdk/Exceptions/InvalidArgumentException.cs
+++ b/src/Momento.Sdk/Exceptions/InvalidArgumentException.cs
@@ -7,6 +7,7 @@ namespace Momento.Sdk.Exceptions;
///
public class InvalidArgumentException : SdkException
{
+ ///
public InvalidArgumentException(string message, MomentoErrorTransportDetails? transportDetails = null, Exception? e = null) : base(MomentoErrorCode.INVALID_ARGUMENT_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "Invalid argument passed to Momento client";
diff --git a/src/Momento.Sdk/Exceptions/LimitExceededException.cs b/src/Momento.Sdk/Exceptions/LimitExceededException.cs
index 86dbe010..40cf3fee 100644
--- a/src/Momento.Sdk/Exceptions/LimitExceededException.cs
+++ b/src/Momento.Sdk/Exceptions/LimitExceededException.cs
@@ -7,6 +7,7 @@
///
public class LimitExceededException : SdkException
{
+ ///
public LimitExceededException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.LIMIT_EXCEEDED_ERROR, message, transportDetails, e)
{
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";
diff --git a/src/Momento.Sdk/Exceptions/NotFoundException.cs b/src/Momento.Sdk/Exceptions/NotFoundException.cs
index 748a1bf6..0859be3d 100644
--- a/src/Momento.Sdk/Exceptions/NotFoundException.cs
+++ b/src/Momento.Sdk/Exceptions/NotFoundException.cs
@@ -7,6 +7,7 @@
///
public class NotFoundException : SdkException
{
+ ///
public NotFoundException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.NOT_FOUND_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "A cache with the specified name does not exist. To resolve this error, make sure you have created the cache before attempting to use it";
diff --git a/src/Momento.Sdk/Exceptions/PermissionDeniedException.cs b/src/Momento.Sdk/Exceptions/PermissionDeniedException.cs
index 93d8d0e6..06fa92d3 100644
--- a/src/Momento.Sdk/Exceptions/PermissionDeniedException.cs
+++ b/src/Momento.Sdk/Exceptions/PermissionDeniedException.cs
@@ -7,6 +7,7 @@
///
public class PermissionDeniedException : SdkException
{
+ ///
public PermissionDeniedException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.PERMISSION_ERROR, message, transportDetails, e)
{
}
diff --git a/src/Momento.Sdk/Exceptions/SdkException.cs b/src/Momento.Sdk/Exceptions/SdkException.cs
index 33acd7bd..cf3c5ab6 100644
--- a/src/Momento.Sdk/Exceptions/SdkException.cs
+++ b/src/Momento.Sdk/Exceptions/SdkException.cs
@@ -3,6 +3,10 @@
namespace Momento.Sdk.Exceptions;
+///
+/// A list of all available Momento error codes. These can be used to check
+/// for specific types of errors on a failure response.
+///
public enum MomentoErrorCode
{
///
@@ -67,12 +71,31 @@ public enum MomentoErrorCode
UNKNOWN_ERROR
}
+///
+/// Captures low-level information about an error, at the gRPC level. Hopefully
+/// this is only needed in rare cases, by Momento engineers, for debugging.
+///
public class MomentoGrpcErrorDetails
{
+ ///
+ /// The gRPC status code of the error repsonse
+ ///
public StatusCode Code { get; }
+ ///
+ /// Detailed information about the error
+ ///
public string Details { get; }
+ ///
+ /// Headers and other information about the error response
+ ///
public Metadata? Metadata { get; set; }
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
public MomentoGrpcErrorDetails(StatusCode code, string details, Metadata? metadata = null)
{
this.Code = code;
@@ -81,22 +104,54 @@ public MomentoGrpcErrorDetails(StatusCode code, string details, Metadata? metada
}
}
+///
+/// Container for low-level error information, including details from the transport layer.
+///
public class MomentoErrorTransportDetails
{
+ ///
+ ///
+ ///
public MomentoGrpcErrorDetails Grpc { get; }
+ ///
+ ///
+ ///
+ ///
public MomentoErrorTransportDetails(MomentoGrpcErrorDetails grpc)
{
this.Grpc = grpc;
}
}
+///
+/// Base class for all Momento client exceptions
+///
public abstract class SdkException : Exception
{
+ ///
+ /// Enumeration of all possible Momento error types. Should be used in
+ /// code to distinguish between different types of errors.
+ ///
public MomentoErrorCode ErrorCode { get; }
+ ///
+ /// Low-level error details, from the transport layer. Hopefully only needed
+ /// in rare cases, by Momento engineers, for debugging.
+ ///
public MomentoErrorTransportDetails? TransportDetails { get; }
+ ///
+ /// Prefix with basic information about the error class; this will be appended
+ /// with specific information about the individual error instance at runtime.
+ ///
public string MessageWrapper { get; set; }
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
protected SdkException(MomentoErrorCode errorCode, string message, MomentoErrorTransportDetails? transportDetails = null, Exception? e = null) : base(message, e)
{
this.ErrorCode = errorCode;
diff --git a/src/Momento.Sdk/Exceptions/ServerUnavailableException.cs b/src/Momento.Sdk/Exceptions/ServerUnavailableException.cs
index 188995f6..ba8b5a11 100644
--- a/src/Momento.Sdk/Exceptions/ServerUnavailableException.cs
+++ b/src/Momento.Sdk/Exceptions/ServerUnavailableException.cs
@@ -7,6 +7,7 @@ namespace Momento.Sdk.Exceptions;
///
public class ServerUnavailableException : SdkException
{
+ ///
public ServerUnavailableException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.SERVER_UNAVAILABLE, message, transportDetails, e)
{
this.MessageWrapper = "The server was unable to handle the request; consider retrying. If the error persists, please contact us at support@momentohq.com";
diff --git a/src/Momento.Sdk/Exceptions/TimeoutException.cs b/src/Momento.Sdk/Exceptions/TimeoutException.cs
index 2af69c8e..fc2a2ee5 100644
--- a/src/Momento.Sdk/Exceptions/TimeoutException.cs
+++ b/src/Momento.Sdk/Exceptions/TimeoutException.cs
@@ -7,6 +7,7 @@
///
public class TimeoutException : SdkException
{
+ ///
public TimeoutException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.TIMEOUT_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "The client's configured timeout was exceeded; you may need to use a Configuration with more lenient timeouts";
diff --git a/src/Momento.Sdk/Exceptions/UnknownException.cs b/src/Momento.Sdk/Exceptions/UnknownException.cs
index 6ac835ae..a0fc4619 100644
--- a/src/Momento.Sdk/Exceptions/UnknownException.cs
+++ b/src/Momento.Sdk/Exceptions/UnknownException.cs
@@ -7,6 +7,7 @@ namespace Momento.Sdk.Exceptions;
///
public class UnknownException : SdkException
{
+ ///
public UnknownException(string message, MomentoErrorTransportDetails? transportDetails = null, Exception? e = null) : base(MomentoErrorCode.UNKNOWN_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "Unknown error has occurred";
diff --git a/src/Momento.Sdk/Exceptions/UnknownServiceException.cs b/src/Momento.Sdk/Exceptions/UnknownServiceException.cs
index 3e3ef78c..f9205166 100644
--- a/src/Momento.Sdk/Exceptions/UnknownServiceException.cs
+++ b/src/Momento.Sdk/Exceptions/UnknownServiceException.cs
@@ -7,6 +7,7 @@ namespace Momento.Sdk.Exceptions;
///
public class UnknownServiceException : SdkException
{
+ ///
public UnknownServiceException(string message, MomentoErrorTransportDetails transportDetails, Exception? e = null) : base(MomentoErrorCode.BAD_REQUEST_ERROR, message, transportDetails, e)
{
this.MessageWrapper = "Service returned an unknown response; please contact us at support@momentohq.com";
diff --git a/src/Momento.Sdk/Internal/Retry/DefaultRetryEligibilityStrategy.cs b/src/Momento.Sdk/Internal/Retry/DefaultRetryEligibilityStrategy.cs
index f5b04a14..8af57af6 100644
--- a/src/Momento.Sdk/Internal/Retry/DefaultRetryEligibilityStrategy.cs
+++ b/src/Momento.Sdk/Internal/Retry/DefaultRetryEligibilityStrategy.cs
@@ -9,6 +9,11 @@
namespace Momento.Sdk.Internal.Retry
{
+ ///
+ /// A retry eligibility strategy that returns true for status codes that
+ /// are commonly understood to be retry-able (Unavailable, Internal), and
+ /// for idempotent request types.
+ ///
public class DefaultRetryEligibilityStrategy : IRetryEligibilityStrategy
{
private readonly HashSet _retryableStatusCodes = new HashSet
@@ -38,25 +43,18 @@ public class DefaultRetryEligibilityStrategy : IRetryEligibilityStrategy
typeof(_GetRequest)
};
- public ILoggerFactory? LoggerFactory { get; }
-
private readonly ILogger _logger;
- public DefaultRetryEligibilityStrategy(ILoggerFactory? loggerFactory)
- {
- _logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger();
- }
-
- public DefaultRetryEligibilityStrategy WithLoggerFactory(ILoggerFactory loggerFactory)
- {
- return new(loggerFactory);
- }
-
- IRetryEligibilityStrategy IRetryEligibilityStrategy.WithLoggerFactory(ILoggerFactory loggerFactory)
+ ///
+ ///
+ ///
+ ///
+ public DefaultRetryEligibilityStrategy(ILoggerFactory loggerFactory)
{
- return WithLoggerFactory(loggerFactory);
+ _logger = loggerFactory.CreateLogger();
}
+ ///
public bool IsEligibleForRetry(Status status, TRequest request)
where TRequest : class
{
diff --git a/src/Momento.Sdk/docs.xml b/src/Momento.Sdk/docs.xml
index 3b932584..26dcf199 100644
--- a/src/Momento.Sdk/docs.xml
+++ b/src/Momento.Sdk/docs.xml
@@ -45,6 +45,29 @@
+
+
+
+ Base class for capturing information about errors that occur during Momento
+ API calls.
+
+ -
+ message:
+
+ string describing the error.
+
+
+ -
+ transportDetails:
+
+ Low-level information about the error, potentially including wire-level
+ status information.
+
+
+
+
+
+