public static RateLimitInfo Add(RateLimitInfo current, RateLimitInfo next) => new RateLimitInfo() { Limit = next.Limit, Remaining = next.Remaining, Cost = current.Cost + next.Cost, ResetAt = next.ResetAt };
public async Task <SearchResults <IReadOnlyList <IssueData> > > SearchIssuesAsync(string query, string accessToken) { var queryRequest = new GraphQlQueryRequest(Queries.SearchIssues); queryRequest.Variables["searchQuery"] = query; queryRequest.Variables["pageSize"] = PageSize; queryRequest.Variables["assigneeBatchSize"] = AssigneeBatchSize; queryRequest.Variables["labelBatchSize"] = LabelBatchSize; queryRequest.Variables["cursor"] = null; var issues = new List <IssueData>(); var pageIndex = 0; var data = default(SearchResults <Dtos.ConnectionResult <Dtos.Issue> >); var rateLimitInfo = new RateLimitInfo(); do { if (data != null) { queryRequest.Variables["cursor"] = data.Search.PageInfo.EndCursor; } var req = new HttpRequestMessage(HttpMethod.Post, GraphQlEndpoint); req.Headers.UserAgent.Add(new ProductInfoHeaderValue("hubbup.io", Startup.Version)); req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var json = JsonConvert.SerializeObject(queryRequest, _settings); req.Content = new StringContent(json); req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); _logger.LogTrace("Requesting page {PageIndex} of search results from GitHub for query '{Query}'", pageIndex, query); HttpResponseMessage resp; using (_metricsService.Time("GitHubDataSource:RequestSearchResultPage")) { resp = await _client.SendAsync(req); _metricsService.Increment($"GitHubDataSource:SearchResultResponses:{(int)resp.StatusCode}"); if (!resp.IsSuccessStatusCode) { var content = await resp.Content.ReadAsStringAsync(); throw new HttpRequestException($"Received {resp.StatusCode} response from GitHub: {content}"); } json = await resp.Content.ReadAsStringAsync(); } var result = JsonConvert.DeserializeObject <Dtos.GraphQlResult <SearchResults <Dtos.ConnectionResult <Dtos.Issue> > > >(json, _settings); if (result.Errors != null && result.Errors.Any()) { throw new InvalidOperationException(result.Errors.First().Message); } data = result.Data; // Add rate limit info _logger.LogTrace("Request completed, consumed {Cost} of rate limit {Limit}. Remaining: {Remaining}, resets at {ResetAt}", data.RateLimit.Cost, data.RateLimit.Limit, data.RateLimit.Remaining, data.RateLimit.ResetAt); rateLimitInfo = RateLimitInfo.Add(rateLimitInfo, data.RateLimit); var count = 0; foreach (var issue in data.Search.Nodes) { var issueData = new IssueData() { Id = issue.Id, IsPr = string.Equals(issue.Type, "PullRequest", StringComparison.Ordinal), Url = issue.Url, Number = issue.Number, Repository = issue.Repository, Title = issue.Title, Author = issue.Author, Milestone = issue.Milestone, CreatedAt = issue.CreatedAt.ToPacificTime(), UpdatedAt = issue.UpdatedAt.ToPacificTime(), CommentCount = issue.Comments.TotalCount }; _metricsService.Record("GitHubDataSource:LabelsPerIssue", issue.Labels.TotalCount); _metricsService.Record("GitHubDataSource:AssigneesPerIssue", issue.Assignees.TotalCount); // Log a warning if there are labels or assignees beyond the ones we fetched // We could make additional requests to fetch these if we find we need them. if (issue.Labels.PageInfo.HasNextPage) { _logger.LogWarning("Issue {RepositoryOwner}/{RepositoryName}#{IssueNumber} has more than the limit of {Limit} labels.", issue.Repository.Owner.Name, issue.Repository.Name, issue.Number, AssigneeBatchSize); } if (issue.Assignees.PageInfo.HasNextPage) { _logger.LogWarning("Issue {RepositoryOwner}/{RepositoryName}#{IssueNumber} has more than the limit of {Limit} assignees.", issue.Repository.Owner.Name, issue.Repository.Name, issue.Number, LabelBatchSize); } // Load the assignees and labels foreach (var assignee in issue.Assignees.Nodes) { issueData.Assignees.Add(assignee); } foreach (var label in issue.Labels.Nodes) { label.ForeColor = ColorMath.GetHexForeColorForBackColor(label.Color); issueData.Labels.Add(label); } // Add this to the list of issues issues.Add(issueData); count += 1; } _metricsService.Increment("GitHubDataSource:IssuesLoaded", count); pageIndex += 1; } while (data.Search.PageInfo.HasNextPage); return(new SearchResults <IReadOnlyList <IssueData> >(issues, rateLimitInfo, pageIndex)); }