72 lines
1.8 KiB
Go
72 lines
1.8 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// rateLimitResponse mirrors the GitHub GET /rate_limit JSON shape. The
|
|
// endpoint includes additional resource buckets, but these are the buckets
|
|
// Kandev tracks and displays.
|
|
type rateLimitResponse struct {
|
|
Resources rateLimitResources `json:"resources"`
|
|
}
|
|
|
|
type rateLimitResources struct {
|
|
Core rateLimitBucket `json:"core"`
|
|
GraphQL rateLimitBucket `json:"graphql"`
|
|
Search rateLimitBucket `json:"search"`
|
|
}
|
|
|
|
type rateLimitBucket struct {
|
|
Limit int `json:"limit"`
|
|
Remaining int `json:"remaining"`
|
|
Reset int64 `json:"reset"`
|
|
}
|
|
|
|
func recordRateLimitResources(tracker *RateTracker, resources rateLimitResources) {
|
|
if tracker == nil {
|
|
return
|
|
}
|
|
now := time.Now().UTC()
|
|
record := func(resource Resource, bucket rateLimitBucket) {
|
|
if bucket.Limit == 0 && bucket.Remaining == 0 && bucket.Reset == 0 {
|
|
return
|
|
}
|
|
tracker.Record(RateSnapshot{
|
|
Resource: resource,
|
|
Limit: bucket.Limit,
|
|
Remaining: bucket.Remaining,
|
|
ResetAt: time.Unix(bucket.Reset, 0).UTC(),
|
|
UpdatedAt: now,
|
|
})
|
|
}
|
|
record(ResourceCore, resources.Core)
|
|
record(ResourceGraphQL, resources.GraphQL)
|
|
record(ResourceSearch, resources.Search)
|
|
}
|
|
|
|
// FetchRateLimit calls GET /rate_limit and seeds the client's tracker with
|
|
// the current REST, GraphQL, and search buckets.
|
|
func (c *TokenClient) FetchRateLimit(ctx context.Context) error {
|
|
if c.rateTracker == nil {
|
|
return nil
|
|
}
|
|
var raw rateLimitResponse
|
|
if err := c.get(ctx, "/rate_limit", &raw); err != nil {
|
|
return fmt.Errorf("fetch rate limit: %w", err)
|
|
}
|
|
recordRateLimitResources(c.rateTracker, raw.Resources)
|
|
return nil
|
|
}
|
|
|
|
func decodeRateLimitResponse(data []byte) (rateLimitResponse, error) {
|
|
var raw rateLimitResponse
|
|
if err := json.Unmarshal(data, &raw); err != nil {
|
|
return rateLimitResponse{}, err
|
|
}
|
|
return raw, nil
|
|
}
|