limiter

package
v0.32.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 6, 2023 License: GPL-3.0 Imports: 4 Imported by: 0

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

View Source
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.

func (Error) Error

func (e Error) Error() string

type Limiter

type Limiter struct {
	// contains filtered or unexported fields
}

Limiter struct is used to limit usage of groups.

func New

func New(cb SetLimitCallback) *Limiter

New creates a new Limiter.

func (*Limiter) Decrement

func (l *Limiter) Decrement(groups []string)

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

func (l *Limiter) GetLimit(ctx context.Context, name string) int

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

func (l *Limiter) GetLimits() map[string]int

GetLimits tells you the current limit of all currently set groups.

func (*Limiter) GetLowestLimit

func (l *Limiter) GetLowestLimit(ctx context.Context, groups []string) int

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

func (l *Limiter) GetRemainingCapacity(ctx context.Context, groups []string) int

GetRemainingCapacity tells you how many times you could Increment() the given groups. If none have a limit set, returns -1.

func (*Limiter) Increment

func (l *Limiter) Increment(ctx context.Context, groups []string, wait ...time.Duration) bool

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

func (l *Limiter) RemoveLimit(name string)

RemoveLimit removes the given group from memory. If your callback also begins returning -1 for this group, the group effectively becomes unlimited.

func (*Limiter) SetLimit

func (l *Limiter) SetLimit(name string, limit uint)

SetLimit creates or updates a group with the given limit.

type SetLimitCallback

type SetLimitCallback func(context.Context, string) int

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.)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL