congestion

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Dec 10, 2020 License: BSD-3-Clause Imports: 7 Imported by: 0

README

Congestion

Build Status GoDoc

A congestion control limiter with priorities. Useful if you are working with a service that implements dynamic rate limits with a way of signaling when you're over the rate limit, e.g. HTTP 429.

It works by limiting the number of outstanding concurrent requests. It gradually increments concurrency, until it hits a limit, at which point, it decreases concurrency by 25%.

Installation

$ go get github.com/joshbohde/congestion

Usage

import (
	"context"
	"log"

	"github.com/joshbohde/congestion"
)

func Example() {
	const (
		HighPriority = 100
	)

	// A limiter can be used to manage concurrent access to a rate limited resource
	limiter := congestion.New(congestion.Config{
		Capacity: 10,
		MaxLimit: 10,
	})

	// backoff manages a single retryable request with priority
	backoff := congestion.Backoff{
		Step:     100 * time.Millisecond,
		Limiter:  &limiter,
		Priority: HighPriority,
	}
	defer backoff.Close()

	// Try the request until either it succeeds, or the context is canceled
	for backoff.Try(context.Background()) {

		// Make some sort of request to the rate limited resource
		err := doRequest()

		// If this error signals we are overloading the server, we'll retry
		if err != nil {
			continue
		}

		// Otherwise return
		return
	}
}

Documentation

Overview

Example
package main

import (
	"context"
	"time"

	"github.com/joshbohde/congestion"
)

func doRequest() error {
	return nil
}

func main() {
	const (
		HighPriority = 100
	)

	// A limiter can be used to manage concurrent access to a rate limited resource
	limiter := congestion.New(congestion.Config{
		Capacity: 10,
		MaxLimit: 10,
	})

	// backoff manages a single retryable request with priority
	backoff := congestion.Backoff{
		Step:     100 * time.Millisecond,
		Limiter:  &limiter,
		Priority: HighPriority,
	}
	defer backoff.Close()

	// Try the request until either it succeeds, or the context is canceled
	for backoff.Try(context.Background()) {

		// Make some sort of request to the rate limited resource
		err := doRequest()

		// If this error signals we are overloading the server, we'll retry
		if err != nil {
			continue
		}

		// Otherwise return
		return
	}

}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var Dropped = errors.New("dropped")

Dropped is the error that will be returned if this token is dropped

Functions

This section is empty.

Types

type Backoff

type Backoff struct {
	Step     time.Duration
	Limiter  *Limiter
	Priority int
	Error    error
	// contains filtered or unexported fields
}

Backoff implements exponential backoff retries on top of a Limiter

func (*Backoff) Close

func (r *Backoff) Close()

Close will close resources associated with the Backoff

func (*Backoff) Try

func (r *Backoff) Try(ctx context.Context) bool

Try will block this attempt until it's no longer limited, or the context is cancelled

type Config

type Config struct {
	Capacity int
	MaxLimit int
}

type Limiter

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

func New

func New(cfg Config) Limiter

func (*Limiter) Acquire

func (l *Limiter) Acquire(ctx context.Context, priority int) error

Acquire a Lock with FIFO ordering, respecting the context. Returns an error it fails to acquire.

func (*Limiter) Backoff

func (l *Limiter) Backoff()

Signal that we need to backoff, and decrease our limit.

func (*Limiter) Release

func (l *Limiter) Release()

Release a previously acquired lock.

Jump to

Keyboard shortcuts

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