Skip to content

[Devtooling-1090] Added logging for retries #1004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions resources/sdk/pureclouddotnet/templates/ApiClient.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ namespace {{packageName}}.Client
}
}

if ((int)response.StatusCode < 200 || (int)response.StatusCode >= 300)
if ((int)response.StatusCode < 200 || (int)response.StatusCode >= 300) {
Configuration.Logger.Error(method.ToString(), url, postBody, response.Content, (int)response.StatusCode, headerParams, response.Headers?
.GroupBy(header => header?.Name)
.Select(header => new
Expand All @@ -373,7 +373,10 @@ namespace {{packageName}}.Client
Value = header.Select(x => x?.Value)?.ToList()
}).ToDictionary(header => header?.Name?.ToString(), header => String.Join(", ", header?.Value?.ToArray()))
?? new Dictionary<string, string>());

if ((int)response.StatusCode == 429) {
Console.WriteLine("Max number of retries exceeded");
}
}

return (Object) response;
}
Expand Down Expand Up @@ -1128,6 +1131,7 @@ namespace {{packageName}}.Client
{
try
{
Console.WriteLine("Rate limit encountered. Retry the request in [{0}] seconds", retryAfterMs/1000);
Thread.Sleep((int) retryAfterMs);
}
catch (ThreadInterruptedException)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,36 @@ public class ApiClientTests
stopwatch.Stop();
}

[Test]
public void InvokeTestWith_429_And_Max_Retries_Exceeded()
{
var retryConfig = new ApiClient.RetryConfiguration
{
MaxRetryTimeSec = 6,
RetryAfterDefaultMs = 100,
RetryMax = 0
};

var mockHttp = new MockHttpMessageHandler();
mockHttp.When("*").Respond((req) =>
{
var response = new HttpResponseMessage((System.Net.HttpStatusCode)429);
response.Headers.Add("Retry-After", "3");
return Task.FromResult(response);
});

var apiClient = new ApiClient(new {{packageName}}.Client.Configuration());
apiClient.RetryConfig = retryConfig;
apiClient.ClientOptions.HttpMessageHandler = mockHttp;

stopwatch = Stopwatch.StartNew();
RestResponse user = (RestResponse)apiClient.CallApi(path, method, queryParams, postBody, headerParams, formParams, fileParams, pathParams, contentType);

Assert.IsTrue(stopwatch.ElapsedMilliseconds >= 3000 && stopwatch.ElapsedMilliseconds < 3100, "Since RetryMax is 0, after one retry exception is thrown");
Assert.AreEqual(429, (int)user.StatusCode);
stopwatch.Stop();
}

[Test]
public void InvokeTestWith_502()
{
Expand Down
19 changes: 17 additions & 2 deletions resources/sdk/purecloudgo/templates/apiclient.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"log"
"io/ioutil"
"net/http"
"net/url"
Expand Down Expand Up @@ -48,6 +49,7 @@ func NewAPIClient(c *Configuration) APIClient {
client := retryablehttp.NewClient()
client.Logger = nil
client.HTTPClient.Timeout = timeout
client.Backoff = customBackoff

return APIClient{
client: *client,
Expand Down Expand Up @@ -219,8 +221,13 @@ func (c *APIClient) CallAPI(path string, method string,
}
}


c.client.CheckRetry = DefaultRetryPolicy
c.client.CheckRetry = func(ctx context.Context, resp *http.Response, err error) (bool, error) {
retry, err := DefaultRetryPolicy(ctx, resp, err)
if !retry && resp.StatusCode == http.StatusTooManyRequests {
log.Println("Max Retries Exceeded")
}
return retry, err
}

if c.configuration.ProxyConfiguration != nil {
var proxyUrl *url.URL
Expand Down Expand Up @@ -472,3 +479,11 @@ func getFieldName(t reflect.Type, field string) string {
func toTime(o interface{}) *time.Time {
return o.(*time.Time)
}

func customBackoff(min, max time.Duration, attemptNumber int, resp *http.Response) time.Duration {
sleep := retryablehttp.DefaultBackoff(min, max, attemptNumber, resp)
if resp != nil && resp.StatusCode == http.StatusTooManyRequests {
log.Printf("Rate limit encountered. Retry the request in [%.0f] seconds\n", sleep.Seconds())
}
return sleep
}
18 changes: 17 additions & 1 deletion resources/sdk/purecloudpython/templates/rest.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class RESTClientObject(object):
proxy_username = Configuration().proxy_username
proxy_password = Configuration().proxy_password

retries = urllib3.util.Retry()
retries = CustomRetry()
retries.allowed_methods = {'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'TRACE'}
# https pool manager
if proxy:
Expand Down Expand Up @@ -270,3 +270,19 @@ class ApiException(Exception):
error_message += "HTTP response body: {0}\n".format(self.body)

return error_message

class CustomRetry(urllib3.util.Retry):
def __init__(self, total=0, connect=None, read=None, redirect=None, status=None, other=None, backoff_factor=0):
super().__init__(total=total, connect=connect, read=read, redirect=redirect, status=status, other=other, backoff_factor=backoff_factor)

def sleep(self, response=None):
sleep_duration = self.get_backoff_time()
print(f"Rate limit encountered. Retry the request in [{sleep_duration}] seconds")
super().sleep(response)

def increment(self, method=None, url=None, repsonse=None, error=None, _pool=None, _stacktrace=None):
retry = super.increment(method, url, repsonse, error, _pool, _stacktrace)
if retry.is_exhausted():
print(f"Max number of retries exceeded: {e}")

return retry
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ public class ApiClient implements AutoCloseable {
return new ApiResponseWrapper<>(statusCode, reasonPhrase, headers, body, entity);
}
else {
String message = "error";
String message = (statusCode == 429) ? "Max number of retries exceeded" : "error";
String body = response.readBody();
throw new WebMessagingException(statusCode, message, headers, body);
}
Expand Down