-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from gofri/gofri/per_req
feat: per-request overrides
- Loading branch information
Showing
6 changed files
with
204 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package github_ratelimit | ||
|
||
import ( | ||
"context" | ||
"time" | ||
) | ||
|
||
// SecondaryRateLimitConfig is the config for the secondary rate limit waiter. | ||
// Use the options to set the config. | ||
type SecondaryRateLimitConfig struct { | ||
// limits | ||
singleSleepLimit *time.Duration | ||
totalSleepLimit *time.Duration | ||
|
||
// callbacks | ||
onLimitDetected OnLimitDetected | ||
onSingleLimitExceeded OnSingleLimitExceeded | ||
onTotalLimitExceeded OnTotalLimitExceeded | ||
} | ||
|
||
// newConfig creates a new config with the given options. | ||
func newConfig(opts ...Option) *SecondaryRateLimitConfig { | ||
var config SecondaryRateLimitConfig | ||
config.ApplyOptions(opts...) | ||
return &config | ||
} | ||
|
||
// ApplyOptions applies the options to the config. | ||
func (c *SecondaryRateLimitConfig) ApplyOptions(opts ...Option) { | ||
for _, o := range opts { | ||
if o == nil { | ||
continue | ||
} | ||
o(c) | ||
} | ||
} | ||
|
||
// IsAboveSingleSleepLimit returns true if the single sleep time is above the limit. | ||
func (c *SecondaryRateLimitConfig) IsAboveSingleSleepLimit(sleepTime time.Duration) bool { | ||
return c.singleSleepLimit != nil && sleepTime > *c.singleSleepLimit | ||
} | ||
|
||
// IsAboveTotalSleepLimit returns true if the total sleep time is above the limit. | ||
func (c *SecondaryRateLimitConfig) IsAboveTotalSleepLimit(sleepTime time.Duration, totalSleepTime time.Duration) bool { | ||
return c.totalSleepLimit != nil && totalSleepTime+sleepTime > *c.totalSleepLimit | ||
} | ||
|
||
type secondaryRateLimitConfigOverridesKey struct{} | ||
|
||
// WithOverrideConfig adds config overrides to the context. | ||
// The overrides are applied on top of the existing config. | ||
// Allows for request-specific overrides. | ||
func WithOverrideConfig(ctx context.Context, opts ...Option) context.Context { | ||
return context.WithValue(ctx, secondaryRateLimitConfigOverridesKey{}, opts) | ||
} | ||
|
||
// GetConfigOverrides returns the config overrides from the context, if any. | ||
func GetConfigOverrides(ctx context.Context) []Option { | ||
cfg := ctx.Value(secondaryRateLimitConfigOverridesKey{}) | ||
if cfg == nil { | ||
return nil | ||
} | ||
return cfg.([]Option) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,32 @@ | ||
package github_ratelimit | ||
|
||
import ( | ||
"context" | ||
"time" | ||
) | ||
|
||
type Option func(*SecondaryRateLimitWaiter) | ||
type Option func(*SecondaryRateLimitConfig) | ||
|
||
// WithLimitDetectedCallback adds a callback to be called when a new active rate limit is detected. | ||
func WithLimitDetectedCallback(callback OnLimitDetected) Option { | ||
return func(t *SecondaryRateLimitWaiter) { | ||
t.onLimitDetected = callback | ||
return func(c *SecondaryRateLimitConfig) { | ||
c.onLimitDetected = callback | ||
} | ||
} | ||
|
||
// WithSingleSleepLimit adds a limit to the duration allowed to wait for a single sleep (rate limit). | ||
// The callback parameter is nillable. | ||
func WithSingleSleepLimit(limit time.Duration, callback OnSingleLimitExceeded) Option { | ||
return func(t *SecondaryRateLimitWaiter) { | ||
t.singleSleepLimit = &limit | ||
t.onSingleLimitExceeded = callback | ||
return func(c *SecondaryRateLimitConfig) { | ||
c.singleSleepLimit = &limit | ||
c.onSingleLimitExceeded = callback | ||
} | ||
} | ||
|
||
// WithTotalSleepLimit adds a limit to the accumulated duration allowed to wait for all sleeps (one or more rate limits). | ||
// The callback parameter is nillable. | ||
func WithTotalSleepLimit(limit time.Duration, callback OnTotalLimitExceeded) Option { | ||
return func(t *SecondaryRateLimitWaiter) { | ||
t.totalSleepLimit = &limit | ||
t.onTotalLimitExceeded = callback | ||
} | ||
} | ||
|
||
// WithUserContext sets the user context to be passed to callbacks. | ||
func WithUserContext(ctx context.Context) Option { | ||
return func(t *SecondaryRateLimitWaiter) { | ||
t.userContext = &ctx | ||
} | ||
} | ||
|
||
func applyOptions(w *SecondaryRateLimitWaiter, opts ...Option) { | ||
for _, o := range opts { | ||
if o == nil { | ||
continue | ||
} | ||
o(w) | ||
return func(c *SecondaryRateLimitConfig) { | ||
c.totalSleepLimit = &limit | ||
c.onTotalLimitExceeded = callback | ||
} | ||
} |
Oops, something went wrong.