{"id":22313565,"url":"https://github.com/mirsaeedi/octokit.net.extensions","last_synced_at":"2025-07-29T10:32:33.870Z","repository":{"id":48895999,"uuid":"138822967","full_name":"mirsaeedi/octokit.net.extensions","owner":"mirsaeedi","description":"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.","archived":false,"fork":false,"pushed_at":"2022-12-12T00:14:27.000Z","size":48,"stargazers_count":4,"open_issues_count":2,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-14T04:57:27.158Z","etag":null,"topics":["caching","github-api","logging","octokit","octokit-net","polly","rate-limiting","resiliency"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mirsaeedi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-27T03:05:42.000Z","updated_at":"2025-04-08T13:39:34.000Z","dependencies_parsed_at":"2023-01-27T09:45:48.797Z","dependency_job_id":null,"html_url":"https://github.com/mirsaeedi/octokit.net.extensions","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mirsaeedi/octokit.net.extensions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirsaeedi%2Foctokit.net.extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirsaeedi%2Foctokit.net.extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirsaeedi%2Foctokit.net.extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirsaeedi%2Foctokit.net.extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mirsaeedi","download_url":"https://codeload.github.com/mirsaeedi/octokit.net.extensions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirsaeedi%2Foctokit.net.extensions/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267670325,"owners_count":24125130,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caching","github-api","logging","octokit","octokit-net","polly","rate-limiting","resiliency"],"created_at":"2024-12-03T22:07:37.491Z","updated_at":"2025-07-29T10:32:33.586Z","avatar_url":"https://github.com/mirsaeedi.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# oktokit.Extensions\nThis 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. \n\nOctokit.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.\n\nThis project hosts the awesome [Polly](https://github.com/App-vNext/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.\n\n## Resiliency against sudden and random http failures\nIn 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.\n\n```C#\npublic  Policy DefaultHttpRequestExceptionPolicy =\u003e Policy.Handle\u003cHttpRequestException\u003e()\n.WaitAndRetryForeverAsync(sleepDurationProvider: retryAttempt =\u003e TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),\nonRetry: (exception, timespan) =\u003e\n{\n_logger?.LogInformation(\"A {exception} has occurred. Next try will happen in {time} seconds\",\"HttpRequestException\",timespan.TotalSeconds);\n});\n```\n#Policies\n\nAll the default policies are implemented inside [ResilientPolicies](https://github.com/mirsaeedi/octokit.net.extensions/blob/master/src/Octokit.Extensions/Resiliency/ResilientPolicies.cs) class. \n\n## Resiliency against http timeouts\nIn 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.\n\n```C#\npublic Policy DefaultTimeoutExceptionPolicy =\u003e Policy.Handle\u003cTaskCanceledException\u003e(ex =\u003e !ex.CancellationToken.IsCancellationRequested)\n.WaitAndRetryForeverAsync(sleepDurationProvider: retryAttempt =\u003e TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),\nonRetry: (exception, timespan) =\u003e\n{\n   _logger?.LogInformation(\"A {exception} has occurred. Next try will happen in {time} seconds\", \"TaskCanceledException\", timespan.TotalSeconds);\n});\n```\n## Resiliency against exceeeding GitHub's rate limit policy\nIn case of reaching the Github's [rate limit](https://developer.github.com/v3/#rate-limiting), 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\n\n```C#\npublic Policy DefaultRateLimitExceededExceptionPolicy =\u003e Policy.Handle\u003cRateLimitExceededException\u003e()\n.RetryAsync(retryCount: 1,onRetryAsync: async (exception, retryCount) =\u003e\n{\n  var e = exception as RateLimitExceededException;\n\n  var sleepMilliseconds = (int)(e.Reset.ToLocalTime() - DateTime.Now).TotalMilliseconds;\n\n  _logger?.LogInformation(\"A {exception} has occurred. Next try will happen in {time} seconds\", \"RateLimitExceededException\", sleepMilliseconds/1000);\n\n  await Task.Delay(sleepMilliseconds \u003c 0 ? 10 : sleepMilliseconds + 1000).ConfigureAwait(false);\n});\n```\n## Resiliency against GitHub's abuse policy\nIn case of [abusing](https://developer.github.com/v3/guides/best-practices-for-integrators/#dealing-with-abuse-rate-limits) 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\n\n```C#\npublic Policy DefaultAbuseExceptionExceptionPolicy =\u003e Policy.Handle\u003cAbuseException\u003e()\n.RetryAsync(retryCount: 1,onRetryAsync: async (exception, retryCount) =\u003e\n{\n  var e = exception as AbuseException;\n\n  var sleepMilliseconds = (int)TimeSpan.FromSeconds(e.RetryAfterSeconds.GetValueOrDefault(30)).TotalMilliseconds;\n\n  _logger?.LogInformation(\"A {exception} has occurred. Next try will happen in {time} seconds\", \"AbuseException\", sleepMilliseconds / 1000);\n\n  await Task.Delay(sleepMilliseconds).ConfigureAwait(false);\n});\n```\n## Caching\n\nYou can easily opt-in your cache provider of choice by implementing [ICacheProvider](https://github.com/mirsaeedi/octokit.net.extensions/blob/master/src/Octokit.Extensions/Caching/ICacheProvider.cs) interface. Also, there is an [in-memory](https://github.com/mirsaeedi/octokit.net.extensions/blob/master/src/Octokit.Extensions/Caching/InMemoryCacheProvider.cs) built-in cache provider available to you.\n\n\n```C#\n\nvar credentials = new Octokit.Credentials(token);\n\n// with default in-memory caching\nvar client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName), credentials,new InMemoryCacheProvider());\n\n// without caching\nvar client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName), credentials);\n\n```\n\n# Logging\n\nIntegrating 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.\n\n```C#\n\nvar logger = new LoggerFactory()\n            .AddConsole().AddDebug()\n            .CreateLogger(\"Github.Octokit.Logger\");\n\nvar credentials = new Octokit.Credentials(token);\n\n// with logging\nvar client = new ResilientGitHubClientFactory(logger).Create(new ProductHeaderValue(agentName), credentials);\n\n// withiut logging\nvar client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName), credentials);\n\n```\n\n# Policies\n\nYou 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](https://github.com/mirsaeedi/octokit.net.extensions/blob/618e4e936c188c28d613e4b548924aa447635548/src/Octokit.Extensions/Resiliency/ResilientPolicies.cs#L65)_ as its policies.\n\n```C#\n// using a custom policy.\nvar policy = Policy.Handle\u003cHttpRequestException\u003e().RetryAsync(2);\nvar client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName),policy);\n\n// using all the built-in policies automatically all-together\nvar client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName));\n\n// using built-in policies selectively\nvar builtinPolicies= new ResilientPolicies();\nvar client = new ResilientGitHubClientFactory().Create(new ProductHeaderValue(agentName),builtinPolicies.DefaultRateLimitExceededExceptionPolicy,\nbuiltinPolicies.DefaultAbuseExceptionExceptionPolicy);\n\n```\n\n# Install via [Nuget](https://www.nuget.org/packages/octokit.Extensions)\n\n```powershell\nInstall-Package  Octokit.Extensions\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirsaeedi%2Foctokit.net.extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmirsaeedi%2Foctokit.net.extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirsaeedi%2Foctokit.net.extensions/lists"}