Documentation
¶
Index ¶
- Variables
- func NewErrorResponse(request *http.Request, category ResourceCategory) *http.Response
- func WithOverrideConfig(ctx context.Context, opts ...Option) context.Context
- type AtomicTime
- type CallbackContext
- type Config
- type ConfigOverridesKey
- type OnLimitReached
- type OnLimitReset
- type OnRequestPrevented
- type OnUnknownCategory
- type Option
- func GetConfigOverrides(ctx context.Context) []Option
- func WithBypassLimit() Option
- func WithLimitDetectedCallback(callback OnLimitReached) Option
- func WithLimitResetCallback(callback OnLimitReset) Option
- func WithRequestPreventedCallback(callback OnRequestPrevented) Option
- func WithSharedState(state *RateLimitState) Option
- func WithSleepUntilReset() Option
- func WithUnknownCategoryCallback(callback OnUnknownCategory) Option
- type ParsedResponse
- type PrimaryRateLimiter
- type RateLimitReachedError
- type RateLimitState
- type ResourceCategory
- type ResponseHeaderKey
- type SecondsSinceEpoch
- type UpdateContainer
Constants ¶
This section is empty.
Variables ¶
var PrimaryLimitStatusCodes = []int{ http.StatusForbidden, http.StatusTooManyRequests, }
Functions ¶
func NewErrorResponse ¶
func NewErrorResponse(request *http.Request, category ResourceCategory) *http.Response
Types ¶
type CallbackContext ¶
type CallbackContext struct {
RoundTripper *PrimaryRateLimiter
Request *http.Request
Response *http.Response
ResetTime *time.Time
Category ResourceCategory
}
CallbackContext is passed to all callbacks. Fields might be nillable, depending on the specific callback and field.
func (*CallbackContext) AsError ¶
func (ctx *CallbackContext) AsError() *RateLimitReachedError
type Config ¶
type Config struct {
// contains filtered or unexported fields
}
Config is the configuration for the rate limiter. It is used internally and generated from the options. It holds the state of the rate limiter in order to enable state sharing.
func (*Config) ApplyOptions ¶
ApplyOptions applies the options to the config.
func (*Config) TriggerLimitReached ¶
func (c *Config) TriggerLimitReached(ctx *CallbackContext)
func (*Config) TriggerLimitReset ¶
func (c *Config) TriggerLimitReset(ctx *CallbackContext)
func (*Config) TriggerRequestPrevented ¶
func (c *Config) TriggerRequestPrevented(ctx *CallbackContext)
func (*Config) TriggerUnknownCategory ¶
func (c *Config) TriggerUnknownCategory(ctx *CallbackContext)
type ConfigOverridesKey ¶
type ConfigOverridesKey struct{}
type OnLimitReached ¶
type OnLimitReached func(*CallbackContext)
OnLimitReached is called when a new rate limit is detected.
type OnLimitReset ¶
type OnLimitReset func(*CallbackContext)
OnLimitReset is called when a rate limit reset time is reached, which means that the category is available for use again.
type OnRequestPrevented ¶
type OnRequestPrevented func(*CallbackContext)
OnRequestPrevented is called when an existing rate limit is detected, such that the current request is not sent.
type OnUnknownCategory ¶
type OnUnknownCategory func(*CallbackContext)
OnUnknownCategory is called when an unknown category is detected at the response, which means that the rate limiter does not handle it.
type Option ¶
type Option func(*Config)
func GetConfigOverrides ¶
GetConfigOverrides returns the config overrides from the context, if any.
func WithBypassLimit ¶
func WithBypassLimit() Option
WithBypassLimit is used to flag that no requests shall be prevented. Callbacks are still called regardless of this flag. This is useful for testing, out-of-band token switching, etc.
func WithLimitDetectedCallback ¶
func WithLimitDetectedCallback(callback OnLimitReached) Option
WithLimitDetectedCallback adds a callback to be called when a new active rate limit is detected.
func WithLimitResetCallback ¶
func WithLimitResetCallback(callback OnLimitReset) Option
WithLimitResetCallback adds a callback to be called when a rate limit is reset, i.e., when an ongoing rate limit is no longer active.
func WithRequestPreventedCallback ¶
func WithRequestPreventedCallback(callback OnRequestPrevented) Option
WithRequestPreventedCallback adds a callback to be called when a request is prevented, i.e., when the rate limit is active. note: this callback is not called when the limit is first detected.
func WithSharedState ¶
func WithSharedState(state *RateLimitState) Option
WithSharedState is used to set the rate limiter state from an external source. Specifically, it is used to share the state between multiple rate limiters. e.g., `rateLimiterB := New(nil, WithSharedState(rateLimiterA.GetState()))`
func WithSleepUntilReset ¶
func WithSleepUntilReset() Option
WithSleepUntilReset is used to flag that the rate limiter shall sleep until the reset time. This is useful for testing, long-running offline applications, etc. Note: it is using the LimitDetectedCallback, so it will not be otherwise called.
func WithUnknownCategoryCallback ¶
func WithUnknownCategoryCallback(callback OnUnknownCategory) Option
WithUnknownCategoryCallback adds a callback to be called when a response from Github contains an unknown category. please open an issue if you encounter this to help improve the handling.
type ParsedResponse ¶
type ParsedResponse struct {
// contains filtered or unexported fields
}
ParsedResponse is a wrapper around http.Response that provides additional functionality. It is used to parse the response and extract rate limit information.
func (ParsedResponse) GetCatgory ¶
func (p ParsedResponse) GetCatgory() ResourceCategory
func (ParsedResponse) GetResetTime ¶
func (p ParsedResponse) GetResetTime() *SecondsSinceEpoch
type PrimaryRateLimiter ¶
type PrimaryRateLimiter struct {
Base http.RoundTripper
// contains filtered or unexported fields
}
PrimaryRateLimiter is a RoundTripper for avoiding GitHub primary rate limits. see notes @ ratelimit_state.go for design considerations.
func New ¶
func New(base http.RoundTripper, opts ...Option) *PrimaryRateLimiter
func (*PrimaryRateLimiter) GetState ¶
func (l *PrimaryRateLimiter) GetState() *RateLimitState
GetState can be used to share the primary rate limit knowledge - when multiple clients are involved. TODO add tests for state sharing
type RateLimitReachedError ¶
type RateLimitReachedError struct {
ResetTime *time.Time
Request *http.Request
Response *http.Response
Category ResourceCategory
}
RateLimitReachedError is an error type for when the primary rate limit is reached.
func (*RateLimitReachedError) Error ¶
func (e *RateLimitReachedError) Error() string
type RateLimitState ¶
type RateLimitState struct {
// contains filtered or unexported fields
}
func NewRateLimitState ¶
func NewRateLimitState(categories []ResourceCategory) *RateLimitState
func (*RateLimitState) GetResetTime ¶
func (s *RateLimitState) GetResetTime(category ResourceCategory) *SecondsSinceEpoch
func (*RateLimitState) Update ¶
func (s *RateLimitState) Update(config *Config, update UpdateContainer, callbackContext *CallbackContext) *SecondsSinceEpoch
type ResourceCategory ¶
type ResourceCategory string
General references (note there are some inconsistencies between them): https://docs.github.com/en/rest/rate-limit/rate-limit#about-rate-limits https://docs.github.com/en/rest/rate-limit/rate-limit#get-rate-limit-status-for-the-authenticated-user
const ( // The default category // used for all HTTP method/url with no other match. ResourceCategoryCore ResourceCategory = "core" // https://docs.github.com/en/rest/search/search#about-search // * /search (except for /search/code) ResourceCategorySearch ResourceCategory = "search" // https://docs.github.com/en/rest/search/search#search-code // * /search/code ResourceCategoryCodeSearch ResourceCategory = "code_search" // https://docs.github.com/en/graphql // * /graphql ResourceCategoryGraphQL ResourceCategory = "graphql" // https://docs.github.com/en/rest/migrations/source-imports#start-an-import // deprecated endpoint; still applicable // * /repos/{OWNER}/{REPO}/import ResourceCategorySourceImport ResourceCategory = "source_import" // https://docs.github.com/en/enterprise-cloud@latest/rest/enterprise-admin/audit-log#get-the-audit-log-for-an-enterprise // * /enterprises/{ENTERPRISE}/audit-log ResourceCategoryAuditLog ResourceCategory = "audit_log" // https://docs.github.com/en/rest/dependency-graph/dependency-submission // POST /app/manfiests/{code}/conversions ResourceCategoryIntegrationManifest ResourceCategory = "integration_manifest" // https://docs.github.com/en/rest/dependency-graph/dependency-submission#create-a-snapshot-of-dependencies-for-a-repository // POST /repos/{OWNER}/{REPO}/dependency-graph/snapshots ResourceCategoryDependencySnapshots ResourceCategory = "dependency_snapshots" // https://docs.github.com/en/rest/code-scanning/code-scanning#upload-an-analysis-as-sarif-data // POST /repos/{OWNER}/{REPO}/code-scanning/sarifs ResourceCategoryCodeScanningUpload ResourceCategory = "code_scanning_upload" // https://docs.github.com/en/rest/actions/self-hosted-runners#about-self-hosted-runners-in-github-actions // "... for registring self-hosted runners"; assuming only POST requests are counted // POST /orgs/{ORG}/actions/runners ResourceCategoryActionsRunnerRegistration ResourceCategory = "actions_runner_registration" // https://docs.github.com/en/enterprise-cloud@latest/rest/scim/scim // no explicit documentation; assuming only POST requests are counted // POST /scim ResourceCategoryScim ResourceCategory = "scim" // https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/streaming-the-audit-log-for-your-enterprise // no API endpoints ResourceCategoryAuditLogStreaming ResourceCategory = "audit_log_streaming" )
func GetAllCategories ¶
func GetAllCategories() []ResourceCategory
type ResponseHeaderKey ¶
type ResponseHeaderKey string
const ( ResponseHeaderKeyRemaining ResponseHeaderKey = "x-ratelimit-remaining" ResponseHeaderKeyReset ResponseHeaderKey = "x-ratelimit-reset" ResponseHeaderKeyCategory ResponseHeaderKey = "x-ratelimit-resource" )
type SecondsSinceEpoch ¶
type SecondsSinceEpoch int64
func (SecondsSinceEpoch) AsTime ¶
func (s SecondsSinceEpoch) AsTime() *time.Time
func (SecondsSinceEpoch) StartTimer ¶
func (s SecondsSinceEpoch) StartTimer() *time.Timer
type UpdateContainer ¶
type UpdateContainer interface {
GetCatgory() ResourceCategory
GetResetTime() *SecondsSinceEpoch
}
UpdateContainer is a simple abstraction over HTTP response, to isolate the perf-centric state management domain from the rest of the logic. It retains the wider-domain terminology of categories, but it is just a key-string as far as RateLimitState is concerned.