Documentation ¶
Overview ¶
Package limiter provides a way of limiting the number of something that belongs to one or more limit groups. It can be used concurrently.
You first create a Limiter with a callback that provides the limit of each group. Then when you want to have something in one or more of those groups, you call Increment(). If limits have not been reached, it returns true. When your "something" is done, Decrement().
Your callback is only called once per group while that group is in use: the limit you provide is stored in memory. But Decrement() removes groups from memory when the count becomes zero, so that unused groups don't fill up memory. If a subsequent Increment() uses a group that was removed from memory, your callback will be called again to find out the limit. It is intended that you don't store all your limits in memory yourself, but retrieve them from disk. If you need to change the limit of a group, your callback should start returning the new limit, and you should call SetLimit() to change the memorised limit, if any.
import "github.com/VertebrateResequencing/wr/limiter" cb := func(name string) int { if name == "l1" { return 3 } else if name == "l2" { return 2 } return 0 } l := limiter.New(cb) if l.Increment([]string{"l1", "l2"}) { // true // do something that can only be done if neither l1 nor l2 have reached // their limit, then afterwards: l.Decrement([]string{"l1", "l2"}) } l.Increment([]string{"l2"}) // true l.Increment([]string{"l2"}) // true l.Increment([]string{"l2"}) // false l.Increment([]string{"l1", "l2"}) // false l.Decrement([]string{"l1", "l2"}) // l1 ignored since never incremented l.Increment([]string{"l1", "l2"}) // true l.Increment([]string{"l3"}) // true since callback returns 0 l.Decrement([]string{"l3"}) // ignored
Index ¶
- Constants
- type Error
- type Limiter
- func (l *Limiter) Decrement(groups []string)
- func (l *Limiter) GetLimit(ctx context.Context, name string) int
- func (l *Limiter) GetLimits() map[string]int
- func (l *Limiter) GetLowestLimit(ctx context.Context, groups []string) int
- func (l *Limiter) GetRemainingCapacity(ctx context.Context, groups []string) int
- func (l *Limiter) Increment(ctx context.Context, groups []string, wait ...time.Duration) bool
- func (l *Limiter) RemoveLimit(name string)
- func (l *Limiter) SetLimit(name string, limit uint)
- type SetLimitCallback
Constants ¶
const ( ErrNotIncremented = "decrement attempted on a limit group that had not been incremented" ErrAtLimit = "increment attempted on a limit group already at its limit" )
limiter has some typical errors
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Error ¶
type Error struct { Group string // the limit's Name Op string // name of the method Err string // one of our Err constants }
Error records an error and the operation, request and protector that caused it.
type Limiter ¶
type Limiter struct {
// contains filtered or unexported fields
}
Limiter struct is used to limit usage of groups.
func (*Limiter) Decrement ¶
Decrement decrements the count of every supplied group.
To save memory, if a group reaches a count of 0, it is forgotten.
If a group isn't known about (because it was never previously Increment()ed, or was previously Decrement()ed to 0 and forgotten about), it is silently ignored.
func (*Limiter) GetLimit ¶ added in v0.20.0
GetLimit tells you the limit currently set for the given group. If the group doesn't exist, returns -1.
func (*Limiter) GetLimits ¶ added in v0.23.4
GetLimits tells you the current limit of all currently set groups.
func (*Limiter) GetLowestLimit ¶
GetLowestLimit tells you the lowest limit currently set amongst the given groups. If none have a limit set, returns -1.
func (*Limiter) GetRemainingCapacity ¶ added in v0.20.0
GetRemainingCapacity tells you how many times you could Increment() the given groups. If none have a limit set, returns -1.
func (*Limiter) Increment ¶
Increment sees if it would be possible to increment the count of every supplied group, without making any of them go over their limit.
If this is the first time we're seeing a group name, or a Decrement() call has made us forget about that group, the callback provided to New() will be called with the name, and the returned value will be used to create a new group with that limit and initial count of 0 (which will become 1 if this returns true). Groups with a limit of 0 will not be able to be Increment()ed.
If possible, the group counts are actually incremented and this returns true. If not possible, no group counts are altered and this returns false.
If an optional wait duration is supplied, will wait for up to the given wait period for an increment of every group to be possible.
func (*Limiter) RemoveLimit ¶
RemoveLimit removes the given group from memory. If your callback also begins returning -1 for this group, the group effectively becomes unlimited.
type SetLimitCallback ¶
SetLimitCallback is provided to New(). Your function should take the name of a group and return the current limit for that group. If the group doesn't exist or has no limit, return -1. The idea is that you retrieve the limit for a group from some on-disk database, so you don't have to have all group limits in memory. (Limiter itself will clear out unused groups from its own memory.)