tgstation-server 5.12.7
The /tg/station 13 server suite
Loading...
Searching...
No Matches
GitHubClientFactory.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5using Microsoft.Extensions.Logging;
6using Microsoft.Extensions.Options;
7using Octokit;
8
11
13{
16 {
21 const uint ClientCacheDays = 7;
22
26 const string DefaultCacheKey = "~!@TGS_DEFAULT_GITHUB_CLIENT_CACHE_KEY@!~";
27
32
36 readonly ILogger<GitHubClientFactory> logger;
37
42
46 readonly Dictionary<string, (GitHubClient, DateTimeOffset)> clientCache;
47
56 ILogger<GitHubClientFactory> logger,
57 IOptions<GeneralConfiguration> generalConfigurationOptions)
58 {
59 this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
60 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
61 generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
62
63 clientCache = new Dictionary<string, (GitHubClient, DateTimeOffset)>();
64 }
65
68
70 public IGitHubClient CreateClient(string accessToken)
72 accessToken ?? throw new ArgumentNullException(nameof(accessToken)));
73
79 GitHubClient GetOrCreateClient(string accessToken)
80 {
81 GitHubClient client;
82 bool cacheHit;
83 lock (clientCache)
84 {
85 string cacheKey;
86 if (String.IsNullOrWhiteSpace(accessToken))
87 {
88 accessToken = null;
89 cacheKey = DefaultCacheKey;
90 }
91 else
92 cacheKey = accessToken;
93
94 cacheHit = clientCache.TryGetValue(cacheKey, out var tuple);
95
96 var now = DateTimeOffset.UtcNow;
97 if (!cacheHit)
98 {
99 logger.LogTrace("Creating new GitHubClient...");
100 client = new GitHubClient(
101 new ProductHeaderValue(
104
105 if (accessToken != null)
106 client.Credentials = new Credentials(accessToken);
107
108 clientCache.Add(cacheKey, (client, now));
109 }
110 else
111 {
112 logger.LogTrace("Cache hit for GitHubClient");
113 client = tuple.Item1;
114 tuple.Item2 = now;
115 }
116
117 // Prune the cache
118 var purgeCount = 0U;
119 var purgeAfter = now.AddDays(-ClientCacheDays);
120 foreach (var key in clientCache.Keys.ToList())
121 {
122 if (key == cacheKey)
123 continue; // save the hash lookup
124
125 tuple = clientCache[key];
126 if (tuple.Item2 <= purgeAfter)
127 {
128 clientCache.Remove(key);
129 ++purgeCount;
130 }
131 }
132
133 if (purgeCount > 0)
134 logger.LogDebug(
135 "Pruned {count} expired GitHub client(s) from cache that haven't been used in {purgeAfterHours} days.",
136 purgeCount,
138 }
139
140 var rateLimitInfo = client.GetLastApiInfo()?.RateLimit;
141 if (rateLimitInfo != null)
142 if (rateLimitInfo.Remaining == 0)
143 logger.LogWarning(
144 "Requested GitHub client has no requests remaining! Limit resets at {resetTime}",
145 rateLimitInfo.Reset.ToString("o"));
146 else if (rateLimitInfo.Remaining < 25) // good luck hitting these lines on codecov
147 logger.LogWarning(
148 "Requested GitHub client has only {remainingRequests} requests remaining! Limit resets at {resetTime}",
149 rateLimitInfo.Remaining,
150 rateLimitInfo.Reset.ToString("o"));
151 else
152 logger.LogDebug(
153 "Requested GitHub client has {remainingRequests} requests remaining. Limit resets at {resetTime}",
154 rateLimitInfo.Remaining,
155 rateLimitInfo.Reset.ToString("o"));
156
157 return client;
158 }
159 }
160}
string GitHubAccessToken
A GitHub personal access token to use for bypassing rate limits on requests. Requires no scopes.
IGitHubClient CreateClient()
Create a IGitHubClient client. Low rate limit unless the server's GitHubAccessToken is set to bypass ...
const string DefaultCacheKey
The clientCache KeyValuePair<TKey, TValue>.Key used in place of null when accessing a configuration-b...
GitHubClientFactory(IAssemblyInformationProvider assemblyInformationProvider, ILogger< GitHubClientFactory > logger, IOptions< GeneralConfiguration > generalConfigurationOptions)
Initializes a new instance of the GitHubClientFactory class.
readonly IAssemblyInformationProvider assemblyInformationProvider
The IAssemblyInformationProvider for the GitHubClientFactory.
IGitHubClient CreateClient(string accessToken)
Create a client with authentication using a personal access token. A new IGitHubClient.
readonly ILogger< GitHubClientFactory > logger
The ILogger for the GitHubClientFactory.
GitHubClient GetOrCreateClient(string accessToken)
Retrieve a GitHubClient from the clientCache or add a new one based on a given accessToken .
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the GitHubClientFactory.
const uint ClientCacheDays
Limit to the amount of days a GitHubClient can live in the clientCache.
readonly Dictionary< string,(GitHubClient, DateTimeOffset)> clientCache
Cache of created GitHubClients and last used times, keyed by access token.
ProductInfoHeaderValue ProductInfoHeaderValue
The ProductInfoHeaderValue for the assembly.