Skip to content
This repository has been archived by the owner on Aug 10, 2022. It is now read-only.

Commit

Permalink
Check RemainingRequests for both GraphQL API & REST API
Browse files Browse the repository at this point in the history
  • Loading branch information
brminnick committed Oct 26, 2020
1 parent 73d27be commit b6c4df5
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 67 deletions.
17 changes: 0 additions & 17 deletions GitHubReadmeWebTrends.Common/Services/GitHubApiService.cs

This file was deleted.

42 changes: 42 additions & 0 deletions GitHubReadmeWebTrends.Common/Services/GitHubApiStatusService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Net;
using System.Threading.Tasks;
using Refit;

namespace GitHubReadmeWebTrends.Common
{
public class GitHubApiStatusService : GitHubApiStatus.GitHubApiStatusService
{
readonly GitHubRestApiService _gitHubRestApiService;
readonly GitHubGraphQLApiService _gitHubGraphQLApiService;

public GitHubApiStatusService(GitHubRestApiService gitHubRestApiService, GitHubGraphQLApiService gitHubGraphQLApiService) =>
(_gitHubRestApiService, _gitHubGraphQLApiService) = (gitHubRestApiService, gitHubGraphQLApiService);

public bool HasReachedMaximimApiCallLimit(in Exception exception) => exception switch
{
ApiException apiException when apiException.StatusCode is HttpStatusCode.Forbidden => HasReachedMaximimApiCallLimit(apiException.Headers),
GraphQLException graphQLException => HasReachedMaximimApiCallLimit(graphQLException.ResponseHeaders),
_ => false
};

public async Task<(int gitHubRestApiRequestsRemaining, int gitHubGraphQLApiRequestsRemaining)> GetRemaininRequestCount()
{
int gitHubRestApiRequestsRemaining, gitHubGraphQLApiRequestsRemaining;
try
{
var restApiResponse = await _gitHubRestApiService.GetResponseMessage().ConfigureAwait(false);
var graphQLApiResponse = await _gitHubGraphQLApiService.GetViewerInformationResponse().ConfigureAwait(false);

gitHubRestApiRequestsRemaining = GetRemainingRequestCount(restApiResponse.Headers);
gitHubGraphQLApiRequestsRemaining = GetRemainingRequestCount(graphQLApiResponse.Headers);
}
catch (Exception e) when (HasReachedMaximimApiCallLimit(e))
{
gitHubRestApiRequestsRemaining = gitHubGraphQLApiRequestsRemaining = 0;
}

return (gitHubRestApiRequestsRemaining, gitHubGraphQLApiRequestsRemaining);
}
}
}
32 changes: 26 additions & 6 deletions GitHubReadmeWebTrends.Common/Services/GitHubGraphQLApiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,30 @@ public class GitHubGraphQLApiService

public GitHubGraphQLApiService(IGitHubGraphQLApiClient gitHubGraphQLApiClient) => _gitHubGraphQLApiClient = gitHubGraphQLApiClient;

public Task<ApiResponse<GraphQLResponse<CreateBranchResponseModel>>> CreateBranch(string repositoryId, string repositoryName, string branchOid, Guid guid) =>
ExecuteGraphQLRequest(_gitHubGraphQLApiClient.CreateBranchMutation(new CreateBranchMutationContent(repositoryId, repositoryName, branchOid, guid)));

public Task<ApiResponse<GraphQLResponse<RepositoryConnectionResponse>>> GetRepository(string repositoryOwner, string repositoryName) =>
ExecuteGraphQLRequest(_gitHubGraphQLApiClient.RepositoryConnectionQuery(new RepositoryConnectionQueryContent(repositoryOwner, repositoryName)));
public Task<CreateBranchResponseModel> CreateBranch(string repositoryId, string repositoryName, string branchOid, Guid guid) =>
GetGraphQLResponseData(CreateBranchResponse(repositoryId, repositoryName, branchOid, guid));

public Task<ApiResponse<GraphQLResponse<CreatePullRequestResponseModel>>> CreatePullRequest(in string repositoryId, in string baseRefName, in string headRefName, in string title, in string body, in Guid clientMutationId, in bool maintainerCanModify = true, in bool draft = false) =>
public Task<RepositoryConnectionResponse> GetRepository(string repositoryOwner, string repositoryName) =>
GetGraphQLResponseData(GetRepositoryResponse(repositoryOwner, repositoryName));

public Task<CreatePullRequestResponseModel> CreatePullRequest(in string repositoryId, in string baseRefName, in string headRefName, in string title, in string body, in Guid clientMutationId, in bool maintainerCanModify = true, in bool draft = false) =>
GetGraphQLResponseData(CreatePullRequestResponse(repositoryId, baseRefName, headRefName, title, body, clientMutationId, maintainerCanModify, draft));

public Task<GitHubViewerResponse> GetViewerInformation() =>
GetGraphQLResponseData(GetViewerInformationResponse());

public Task<ApiResponse<GraphQLResponse<CreateBranchResponseModel>>> CreateBranchResponse(string repositoryId, string repositoryName, string branchOid, Guid guid) =>
ExecuteGraphQLRequest(_gitHubGraphQLApiClient.CreateBranchMutation(new CreateBranchMutationContent(repositoryId, repositoryName, branchOid, guid)));

public Task<ApiResponse<GraphQLResponse<RepositoryConnectionResponse>>> GetRepositoryResponse(string repositoryOwner, string repositoryName) =>
ExecuteGraphQLRequest(_gitHubGraphQLApiClient.RepositoryConnectionQuery(new RepositoryConnectionQueryContent(repositoryOwner, repositoryName)));

public Task<ApiResponse<GraphQLResponse<CreatePullRequestResponseModel>>> CreatePullRequestResponse(in string repositoryId, in string baseRefName, in string headRefName, in string title, in string body, in Guid clientMutationId, in bool maintainerCanModify = true, in bool draft = false) =>
ExecuteGraphQLRequest(_gitHubGraphQLApiClient.CreatePullRequestMutation(new CreatePullRequestMutationContent(repositoryId, baseRefName, headRefName, title, body, clientMutationId, maintainerCanModify, draft)));

public Task<ApiResponse<GraphQLResponse<GitHubViewerResponse>>> GetViewerInformation() => ExecuteGraphQLRequest(_gitHubGraphQLApiClient.ViewerLoginQuery(new ViewerLoginQueryContent()));
public Task<ApiResponse<GraphQLResponse<GitHubViewerResponse>>> GetViewerInformationResponse() =>
ExecuteGraphQLRequest(_gitHubGraphQLApiClient.ViewerLoginQuery(new ViewerLoginQueryContent()));

public async IAsyncEnumerable<IEnumerable<Repository>> GetRepositories(string repositoryOwner, int numberOfRepositoriesPerRequest = 100)
{
Expand All @@ -36,6 +50,12 @@ public async IAsyncEnumerable<IEnumerable<Repository>> GetRepositories(string re
while (repositoryConnection?.PageInfo?.HasNextPage is true);
}

async Task<T> GetGraphQLResponseData<T>(Task<ApiResponse<GraphQLResponse<T>>> graphQLRequestTask)
{
var response = await ExecuteGraphQLRequest(graphQLRequestTask).ConfigureAwait(false);
return response.Content.Data;
}

async Task<ApiResponse<GraphQLResponse<T>>> ExecuteGraphQLRequest<T>(Task<ApiResponse<GraphQLResponse<T>>> graphQLRequestTask)
{
var response = await graphQLRequestTask.ConfigureAwait(false);
Expand Down
2 changes: 1 addition & 1 deletion GitHubReadmeWebTrends.Common/Services/StartupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static void ConfigureServices(in IServiceCollection services)
services.AddSingleton<GitHubRestApiService>();
services.AddSingleton<GitHubGraphQLApiService>();
services.AddSingleton<CloudAdvocateService>();
services.AddSingleton<GitHubApiExceptionService>();
services.AddSingleton<GitHubApiStatusService>();

static TimeSpan sleepDurationProvider(int attemptNumber) => TimeSpan.FromSeconds(Math.Pow(2, attemptNumber));

Expand Down
74 changes: 31 additions & 43 deletions GitHubReadmeWebTrends.Functions/Functions/GetReadmeFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@ public class GetReadmeFunction
readonly CloudQueueClient _cloudQueueClient;
readonly GitHubRestApiService _gitHubRestApiService;
readonly GitHubGraphQLApiService _gitHubGraphQLApiService;
readonly GitHubApiExceptionService _gitHubApiExceptionService;
readonly GitHubApiStatusService _gitHubApiStatusService;

public GetReadmeFunction(CloudQueueClient cloudQueueClient,
IHttpClientFactory httpClientFactory,
GitHubRestApiService gitHubApiService,
GitHubGraphQLApiService gitHubGraphQLApiService,
GitHubApiExceptionService gitHubApiExceptionService)
GitHubApiStatusService gitHubApiStatusService,
GitHubGraphQLApiService gitHubGraphQLApiService)
{
_httpClient = httpClientFactory.CreateClient();

_cloudQueueClient = cloudQueueClient;
_gitHubRestApiService = gitHubApiService;
_gitHubApiStatusService = gitHubApiStatusService;
_gitHubGraphQLApiService = gitHubGraphQLApiService;
_gitHubApiExceptionService = gitHubApiExceptionService;
}

[FunctionName(nameof(GetReadmeQueueTriggerFunction))]
Expand All @@ -41,52 +41,39 @@ public async Task GetReadmeQueueTriggerFunction([QueueTrigger(QueueConstants.Rep
{
const int minimumApiRequests = 2000;

int gitHubRestApiRequestsRemaining, gitHubGraphQLApiRequestsRemaining;

log.LogInformation($"{nameof(GetReadmeFunction)} Stared");

var (repository, gitHubUser) = data;

try
{
var restApiResponse = await _gitHubRestApiService.GetResponseMessage().ConfigureAwait(false);
var graphQLApiResponse = await _gitHubGraphQLApiService.GetViewerInformation().ConfigureAwait(false);
var (gitHubRestApiRequestsRemaining, gitHubGraphQLApiRequestsRemaining) = await _gitHubApiStatusService.GetRemaininRequestCount().ConfigureAwait(false);

gitHubRestApiRequestsRemaining = _gitHubApiExceptionService.GetRemainingRequestCount(restApiResponse.Headers);
gitHubGraphQLApiRequestsRemaining = _gitHubApiExceptionService.GetRemainingRequestCount(graphQLApiResponse.Headers);
}
catch (Exception e) when (_gitHubApiExceptionService.HasReachedMaximimApiCallLimit(e))
{
gitHubRestApiRequestsRemaining = gitHubGraphQLApiRequestsRemaining = 0;
}

log.LogInformation($"{nameof(gitHubRestApiRequestsRemaining)}: {gitHubRestApiRequestsRemaining}");
log.LogInformation($"{nameof(gitHubGraphQLApiRequestsRemaining)}: {gitHubGraphQLApiRequestsRemaining}");

try
log.LogInformation($"{nameof(gitHubGraphQLApiRequestsRemaining)}: {gitHubGraphQLApiRequestsRemaining}");


// The GitHub API Limits requests to 5,0000 per hour https://docs.github.com/en/free-pro-team@latest/rest#rate-limiting
// If the API Limit is approaching, output to RemainingRepositoriesQueue, where it will be handled by GetReadmeTimerTriggerFunction which runs once an hour
// Otherwise, process the data and place it on VerifyWebTrendsQueue
if (gitHubRestApiRequestsRemaining < minimumApiRequests
|| gitHubGraphQLApiRequestsRemaining < minimumApiRequests)
{

// The GitHub API Limits requests to 5,0000 per hour https://docs.github.com/en/free-pro-team@latest/rest#rate-limiting
// If the API Limit is approaching, output to RemainingRepositoriesQueue, where it will be handled by GetReadmeTimerTriggerFunction which runs once an hour
// Otherwise, process the data and place it on VerifyWebTrendsQueue
if (gitHubRestApiRequestsRemaining < minimumApiRequests
|| gitHubGraphQLApiRequestsRemaining < minimumApiRequests)
{
log.LogInformation($"Maximum API Requests Reached");

remainingRepositoriesData.Add(data);

log.LogInformation($"Added Data to RemainingRepositoriesQueue");
}
else
{
await RetrieveReadme(repository, gitHubUser, log, completedRepositoriesData).ConfigureAwait(false);
}
log.LogInformation($"Maximum API Requests Reached");

remainingRepositoriesData.Add(data);

log.LogInformation($"Added Data to RemainingRepositoriesQueue");
}
catch (Refit.ApiException e) when (e.StatusCode is System.Net.HttpStatusCode.NotFound)
else
{
//If a Readme doesn't exist, GitHubApiService.GetReadme will return a 404 Not Found response
}
try
{
await RetrieveReadme(repository, gitHubUser, log, completedRepositoriesData).ConfigureAwait(false);
}
catch (Refit.ApiException e) when (e.StatusCode is System.Net.HttpStatusCode.NotFound)
{
//If a Readme doesn't exist, GitHubApiService.GetReadme will return a 404 Not Found response
}
}

log.LogInformation($"{nameof(GetReadmeFunction)} Completed");
}
Expand Down Expand Up @@ -116,9 +103,10 @@ public async Task GetReadmeTimerTriggerFunction([TimerTrigger(_runEveryHour, Run

try
{
var response = await _gitHubRestApiService.GetResponseMessage().ConfigureAwait(false);
var (gitHubRestApiRequestsRemaining, gitHubGraphQLApiRequestsRemaining) = await _gitHubApiStatusService.GetRemaininRequestCount().ConfigureAwait(false);

if (GitHubApiExceptionService.GetNumberOfApiRequestsRemaining(response.Headers) >= 2000)
if (gitHubRestApiRequestsRemaining > 2000
&& gitHubGraphQLApiRequestsRemaining > 2000)
{
await RetrieveReadme(repository, gitHubUser, log, completedRepositoriesData).ConfigureAwait(false);
await remainingRepositoriesQueue.DeleteMessageAsync(queueMessage).ConfigureAwait(false);
Expand Down

0 comments on commit b6c4df5

Please sign in to comment.