mirsaeedi / octokit.net.extensions

This library extends octokit.net, the well-known GitHub client, by enriching it with caching, resilient connections and logging capabilities. In fact, this library free you from dealing with rate limit and abuse issues.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

oktokit.Extensions

This library extends octokit.net, the well-known GitHub client, by enriching it with caching, resilient connections and logging capabilities. In fact, using this library your process won't halt in case of happening exceptions such as Rate Limit, Abuse, Http Exceptions and you will consume your rate limit more wisely.

Octokit.Extension adds a middleware to the Octokit's HttpClient and will try to resend the requests if anything goes wrong. There are some built-in policies that define how Octokit.Extensions should act to handle the exceptions. However, you can easily define your own custom policies to deal with exceptions based on your requirements.

This project hosts the awesome Polly at its heart. We are using Polly to define policies and to incorporate the retry behaviour into Octokit.Extensions. Using this library you get the following policies and behavior out of the box.

Resiliency against sudden and random http failures

In case of happening HttpRequestException, the built-in policy tries to prevent the whole process from stopping by resending the request according to the following policy.

public  Policy DefaultHttpRequestExceptionPolicy => Policy.Handle<HttpRequestException>()
.WaitAndRetryForeverAsync(sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (exception, timespan) =>
{
_logger?.LogInformation("A {exception} has occurred. Next try will happen in {time} seconds","HttpRequestException",timespan.TotalSeconds);
});

#Policies

All the default policies are implemented inside ResilientPolicies class.

Resiliency against http timeouts

In case of happening timout exceptions which been carrying in TaskCanceledException exception, the built-in policy tries to prevent the whole process from stopping by resending the request according to the following policy.

public Policy DefaultTimeoutExceptionPolicy => Policy.Handle<TaskCanceledException>(ex => !ex.CancellationToken.IsCancellationRequested)
.WaitAndRetryForeverAsync(sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
onRetry: (exception, timespan) =>
{
   _logger?.LogInformation("A {exception} has occurred. Next try will happen in {time} seconds", "TaskCanceledException", timespan.TotalSeconds);
});

Resiliency against exceeeding GitHub's rate limit policy

In case of reaching the Github's rate limit, octokit throws RateLimitExceededException exception. To deal with the situation, the built-in policy tries to prevent the whole process from stopping by waiting untill the rate limit window expires. The default implemented policy is as follows

public Policy DefaultRateLimitExceededExceptionPolicy => Policy.Handle<RateLimitExceededException>()
.RetryAsync(retryCount: 1,onRetryAsync: async (exception, retryCount) =>
{
  var e = exception as RateLimitExceededException;

  var sleepMilliseconds = (int)(e.Reset.ToLocalTime() - DateTime.Now).TotalMilliseconds;

  _logger?.LogInformation("A {exception} has occurred. Next try will happen in {time} seconds", "RateLimitExceededException", sleepMilliseconds/1000);

  await Task.Delay(sleepMilliseconds < 0 ? 10 : sleepMilliseconds + 1000).ConfigureAwait(false);
});

Resiliency against GitHub's abuse policy

In case of abusing the Github policy, octokit throws AbuseException exception. To deal with the situation, the built-in policy tries to prevent the whole process from stopping by waiting untill the abuse time window expires. The default implemented policy is as follows

public Policy DefaultAbuseExceptionExceptionPolicy => Policy.Handle<AbuseException>()
.RetryAsync(retryCount: 1,onRetryAsync: async (exception, retryCount) =>
{
  var e = exception as AbuseException;

  var sleepMilliseconds = (int)TimeSpan.FromSeconds(e.RetryAfterSeconds.GetValueOrDefault(30)).TotalMilliseconds;

  _logger?.LogInformation("A {exception} has occurred. Next try will happen in {time} seconds", "AbuseException", sleepMilliseconds / 1000);

  await Task.Delay(sleepMilliseconds).ConfigureAwait(false);
});

Caching

You can easily opt-in your cache provider of choice by implementing ICacheProvider interface. Also, there is an in-memory built-in cache provider available to you.

var credentials = new Octokit.Credentials(token);

// with default in-memory caching
var client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName), credentials,new InMemoryCacheProvider());

// without caching
var client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName), credentials);

Logging

Integrating octokit.net.Extension in your source code is straightforward. In fact, instead of instantiating octokit's GithubClient via constructor, you just need to use the ResilientGitHubClientFactory which takes an optional ILogger to log the events.

var logger = new LoggerFactory()
            .AddConsole().AddDebug()
            .CreateLogger("Github.Octokit.Logger");

var credentials = new Octokit.Credentials(token);

// with logging
var client = new ResilientGitHubClientFactory(logger).Create(new ProductHeaderValue(agentName), credentials);

// withiut logging
var client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName), credentials);

Policies

You are able to replace the built-in Polly policies with your own. In fact, ResilientGitHubClientFactory.Create takes params IAsyncPolicy[] as its last parameter. These policies define how we should act in case of happening any pre-defined catastrophic situation. If you don't pass any policies, Octokit.Extention will use the _DefaultResilientPolicies_ as its policies.

// using a custom policy.
var policy = Policy.Handle<HttpRequestException>().RetryAsync(2);
var client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName),policy);

// using all the built-in policies automatically all-together
var client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName));

// using built-in policies selectively
var builtinPolicies= new ResilientPolicies();
var client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName),builtinPolicies.DefaultRateLimitExceededExceptionPolicy,
builtinPolicies.DefaultAbuseExceptionExceptionPolicy);

Install via Nuget

Install-Package  Octokit.Extensions

About

This library extends octokit.net, the well-known GitHub client, by enriching it with caching, resilient connections and logging capabilities. In fact, this library free you from dealing with rate limit and abuse issues.

License:MIT License


Languages

Language:C# 100.0%