From e5898b434451702bec2a5d1a4956a260e2bcec7c Mon Sep 17 00:00:00 2001 From: Parvathi Mallampalli Date: Mon, 20 Sep 2021 13:38:42 -0700 Subject: [PATCH] Clientside RateLimit configuration --- .../sellingpartner-api-aa-csharp/README.md | 17 ++++++- .../RateLimitConfiguration.cs | 12 +++++ .../RateLimitConfigurationOnRequests.cs | 29 ++++++++++++ .../templates/ApiClient.mustache | 47 +++++++++++++++++-- .../templates/Configuration.mustache | 6 +++ .../templates/IReadableConfiguration.mustache | 6 +++ .../swagger-codegen/templates/api.mustache | 11 ++++- 7 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfiguration.cs create mode 100644 clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfigurationOnRequests.cs diff --git a/clients/sellingpartner-api-aa-csharp/README.md b/clients/sellingpartner-api-aa-csharp/README.md index a58a97c..7ae8977 100644 --- a/clients/sellingpartner-api-aa-csharp/README.md +++ b/clients/sellingpartner-api-aa-csharp/README.md @@ -63,6 +63,21 @@ restRequest = new AWSSigV4Signer(awsAuthenticationCredentials) ``` Note the IRestRequest reference is treated as **mutable** when signed. +## RateLimitConfiguration + +Interface to set and get rateLimit configurations that are used with RateLimiter. RateLimiter is used on client side to restrict the rate at which requests are made. RateLimiter Configuration takes Permit, rate which requests are made and TimeOut + + +*Example* +``` +RateLimitConfiguration rateLimitConfig = new RateLimitConfigurationOnRequests + { + RateLimitPermit = .., + WaitTimeOutInMilliSeconds = ... + }; + +``` + ## Resources This package features Mustache templates designed for use with [swagger codegen](https://swagger.io/tools/swagger-codegen/). When you build Selling Partner API Swagger models with these templates, they help generate a rich SDK with functionality to invoke Selling Partner APIs built in. The templates are located in *resources/swagger-codegen*. @@ -72,7 +87,7 @@ This package is built as a .NET Standard Library via a Visual Studio Solution wi ## Dependencies All dependencies can be installed via NuGet -- RestSharp - 105.1.0 +- RestSharp - 106.12.0 - Newtonsoft.Json 12.0.3 - NETStandard.Library 2.0.3 (platform-specific implementation requirements are documented on the [Microsoft .NET Guide](https://docs.microsoft.com/en-us/dotnet/standard/net-standard)) diff --git a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfiguration.cs b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfiguration.cs new file mode 100644 index 0000000..e01a3f0 --- /dev/null +++ b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfiguration.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Amazon.SellingPartnerAPIAA +{ + public interface RateLimitConfiguration + { + int getRateLimitPermit(); + int getTimeOut(); + } +} \ No newline at end of file diff --git a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfigurationOnRequests.cs b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfigurationOnRequests.cs new file mode 100644 index 0000000..7dfbd30 --- /dev/null +++ b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/RateLimitConfigurationOnRequests.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Amazon.SellingPartnerAPIAA +{ + public class RateLimitConfigurationOnRequests : RateLimitConfiguration + { + /** + * RateLimiter Permit + */ + public int RateLimitPermit; + + /** + * Timeout for RateLimiter + */ + public int WaitTimeOutInMilliSeconds; + + public int getRateLimitPermit() + { + return RateLimitPermit; + } + + public int getTimeOut() + { + return WaitTimeOutInMilliSeconds; + } + } +} \ No newline at end of file diff --git a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/ApiClient.mustache b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/ApiClient.mustache index 3a98a34..faad469 100644 --- a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/ApiClient.mustache +++ b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/ApiClient.mustache @@ -22,6 +22,8 @@ using RestSharp.Portable.HttpClient; using RestSharp; {{/netStandard}} using Amazon.SellingPartnerAPIAA; +using RateLimiter; +using System.Threading; namespace {{packageName}}.Client { @@ -32,7 +34,9 @@ namespace {{packageName}}.Client { private LWAAuthorizationSigner lwaAuthorizationSigner; private AWSSigV4Signer awsSigV4Signer; - + private RateLimitConfiguration rateLimitConfig; + private TimeLimiter rateLimiter; + private JsonSerializerSettings serializerSettings = new JsonSerializerSettings { ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor @@ -71,6 +75,11 @@ namespace {{packageName}}.Client lwaAuthorizationSigner = new LWAAuthorizationSigner(Configuration.AuthorizationCredentials); awsSigV4Signer = new AWSSigV4Signer(Configuration.AuthenticationCredentials); + rateLimitConfig = Configuration.RateLimitConfig; + if(rateLimitConfig != null) + { + rateLimiter = TimeLimiter.GetFromMaxCountByInterval(rateLimitConfig.getRateLimitPermit(), TimeSpan.FromSeconds(1)); + } } /// @@ -134,7 +143,7 @@ namespace {{packageName}}.Client {{/netStandard}} {{^netStandard}} {{^supportsUWP}} - request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentType); + request.AddFile(param.Value.Name, param.Value.Writer, param.Value.FileName, param.Value.ContentLength, param.Value.ContentType); {{/supportsUWP}} {{#supportsUWP}} byte[] paramWriter = null; @@ -187,6 +196,22 @@ namespace {{packageName}}.Client RestClient.UserAgent = Configuration.UserAgent; InterceptRequest(request); + if(rateLimitConfig != null) + { + var cancellationSource = new CancellationTokenSource(rateLimitConfig.getTimeOut()); + try + { + var response = rateLimiter.Enqueue(() => RestClient.Execute(request), cancellationSource.Token); + InterceptResponse(request, response.Result); + return response.Result; + } + catch (AggregateException e) + { + throw new ApiException(429, "Throttled at client"); + } + } + else + { {{#netStandard}} var response = RestClient.Execute(request).Result; {{/netStandard}} @@ -202,6 +227,7 @@ namespace {{packageName}}.Client InterceptResponse(request, response); return (Object) response; + } } {{#supportsAsync}} /// @@ -227,9 +253,19 @@ namespace {{packageName}}.Client path, method, queryParams, postBody, headerParams, formParams, fileParams, pathParams, contentType); InterceptRequest(request); - var response = await RestClient.Execute{{^netStandard}}TaskAsync{{/netStandard}}(request); - InterceptResponse(request, response); - return (Object)response; + if (rateLimitConfig != null) + { + var cancellationSource = new CancellationTokenSource(rateLimitConfig.getTimeOut()); + var response = await rateLimiter.Enqueue(() => RestClient.ExecuteTaskAsync(request), cancellationSource.Token); + InterceptResponse(request, response); + return response; + } + else + { + var response = await RestClient.Execute{{^netStandard}}TaskAsync{{/netStandard}}(request); + InterceptResponse(request, response); + return (Object)response; + } }{{/supportsAsync}} /// @@ -574,3 +610,4 @@ namespace {{packageName}}.Client } } } + diff --git a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/Configuration.mustache b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/Configuration.mustache index 77b0154..247498a 100644 --- a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/Configuration.mustache +++ b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/Configuration.mustache @@ -274,6 +274,12 @@ namespace {{packageName}}.Client /// /// The AWSAuthenticationCredentials public virtual AWSAuthenticationCredentials AuthenticationCredentials { get; set; } + + /// + /// Gets or sets the RateLimitConfiguration for Amazon Selling Partner API Authentication + /// + /// The RateLimitConfiguration + public virtual RateLimitConfiguration RateLimitConfig { get; set; } /// /// Gets the API key with prefix. diff --git a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/IReadableConfiguration.mustache b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/IReadableConfiguration.mustache index 525e9ce..aa890fc 100644 --- a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/IReadableConfiguration.mustache +++ b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/IReadableConfiguration.mustache @@ -94,5 +94,11 @@ namespace {{packageName}}.Client /// /// AuthenticationCredentials AWSAuthenticationCredentials AuthenticationCredentials { get; } + + /// + /// Gets the RateLimitConfigurationOnRequests for Amazon Selling Partner API RateLimit + /// + /// RateLimitConfiguration + RateLimitConfiguration RateLimitConfig { get; } } } diff --git a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/api.mustache b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/api.mustache index a9b1bcc..32b375e 100644 --- a/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/api.mustache +++ b/clients/sellingpartner-api-aa-csharp/src/Amazon.SellingPartnerAPIAA/resources/swagger-codegen/templates/api.mustache @@ -436,6 +436,7 @@ namespace {{packageName}}.{{apiPackage}} { private LWAAuthorizationCredentials lwaAuthorizationCredentials; private AWSAuthenticationCredentials awsAuthenticationCredentials; + private RateLimitConfiguration rateLimitConfiguration; public Builder SetLWAAuthorizationCredentials(LWAAuthorizationCredentials lwaAuthorizationCredentials) { @@ -448,6 +449,13 @@ namespace {{packageName}}.{{apiPackage}} this.awsAuthenticationCredentials = awsAuthenticationCredentials; return this; } + + + public Builder SetRateLimitConfiguration(RateLimitConfiguration rateLimitConfiguration) + { + this.rateLimitConfiguration = rateLimitConfiguration; + return this; + } public {{classname}} Build() { @@ -464,7 +472,8 @@ namespace {{packageName}}.{{apiPackage}} {{packageName}}.Client.Configuration configuration = new {{packageName}}.Client.Configuration() { AuthorizationCredentials = lwaAuthorizationCredentials, - AuthenticationCredentials = awsAuthenticationCredentials + AuthenticationCredentials = awsAuthenticationCredentials, + RateLimitConfig = rateLimitConfiguration }; // default HTTP connection timeout (in milliseconds)