limiter

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Feb 25, 2022 License: MIT Imports: 1 Imported by: 7

README

limiter
GoDoc

Limiter is a Golang library for limiting work coming from any number of goroutines. This is useful when you need limit the maximum number of concurrent calls to a specific operation.

This library has two types:

  • Limiter: Limits the number concurrent operations.
  • Queue: Queues limiter operations. Push/pop inputs/outputs.

Install

Requires Go 1.18+

go get github.com/tidwall/limiter

Examples

Limiter

package main

import (
	"io/ioutil"
	"net/http"

	"github.com/tidwall/limiter"
)

func main() {

	// Create a limiter for a maximum of 10 concurrent operations
	l := limiter.New(10)

	http.HandleFunc("/work", func(w http.ResponseWriter, r *http.Request) {
		input, err := ioutil.ReadAll(r.Body)
		if err != nil {
			http.Error(w, "Internal error", http.StatusInternalServerError)
		}
		defer r.Body.Close()

		var result []byte
		func() {
			l.Begin()
			defer l.End()
			// Do some intensive work here. It's guaranteed that only a
			// maximum of ten of these operations will run at the same time.
			result = []byte("rad!")
		}()

		w.Write(result.([]byte))
	})

	http.ListenAndServe(":8080", nil)
}

Queue

package main

import (
	"github.com/tidwall/limiter"
)

func main() {
	// Create a queue for a maximum of 10 concurrent operations. 
	q := limiter.NewQueue(10,
		func(in int) (out int) {
			// Do some intensive work here. It's guaranteed that only a maximum
			// of ten of these operations will run at the same time. 
			// Here we'll just multiple the input by 100 and return that value
			// as the output.
			return in * 100
		},
	)
	
	// Push 100 inputs onto the queue.
	for i := 0; i < 100; i++ {
		q.Push(i)
		// Once an input is pushed onto the queue, you can freely try to pop 
		// the output. The Pop method will return outputs in the same order
		// as their repsective inputs were pushed. It's possible that the 
		// next output is not ready because the background operation that is 
		// processing the input has yet to complete.
		for {
			out, ok := q.Pop()
			if !ok {
				// The next input has not completed or the queue is empty.
				break
			}
			println(out)
		}
	}

	// Finally you can use PopWait to wait on the next output. 
	for {
		out, ok := q.PopWait()
		if !ok {
			// The queue is empty
			break
		}
		println(out)
	}
	// output:
	// 0
	// 100
	// 200
	// ....
	// 9700
	// 9800
	// 9900
}

Contact

Josh Baker @tidwall

License

Limiter source code is available under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Group added in v0.2.0

type Group[I, O any] struct {
	// contains filtered or unexported fields
}

Group for running background operations.

func NewGroup added in v0.2.0

func NewGroup[I, O any](limit int, op func(in I) (out O, err error)) *Group[I, O]

NewGroup returns a Group for running background operations.

func (*Group[I, O]) Drain added in v0.4.0

func (g *Group[I, O]) Drain()

Drain all pending outputs. This acts as a barrier to ensure that there are no more group operations running in the background.

func (*Group[I, O]) Recv added in v0.4.0

func (g *Group[I, O]) Recv(wait bool, results func(out O) error) error

Recv receives pending outputs. Setting "wait" to true will make this function wait for all inputs to complete being processed before returning. The "results" callback will fire for all outputs in the same order as their respective inputs. If the group operation or callback returned an error then the iterator will stop and that error will be returned to the call of this function.

func (*Group[I, O]) Send added in v0.4.0

func (g *Group[I, O]) Send(in I)

Send an input to the group for background processing.

type Limiter

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

Limiter is for limiting the number of concurrent operations.

func New

func New(limit int) *Limiter

New returns a new Limiter. The limit param is the maximum number of concurrent operations.

func (*Limiter) Begin

func (l *Limiter) Begin()

Begin an operation.

func (*Limiter) End

func (l *Limiter) End()

End the operation.

type Queue added in v0.3.0

type Queue[I, O any] struct {
	// contains filtered or unexported fields
}

Queue is a limiter queue operations that executes each operation in background goroutines, where each operation has a single input and output. The inputs are pushed onto the queue using Push, and the output can be retrieved using Pop.

func NewQueue added in v0.3.0

func NewQueue[I, O any](limit int, op func(in I) (out O)) *Queue[I, O]

NewQueue returns a limiter queue.

func (*Queue[I, O]) Pop added in v0.3.0

func (q *Queue[I, O]) Pop() (out O, ok bool)

Pop output off the queue. The outputs will be returned in order of their respective inputs. Returns false if the queue is empty of if the next input operation has not yet finished processing.

func (*Queue[I, O]) PopWait added in v0.3.0

func (q *Queue[I, O]) PopWait() (out O, ok bool)

PopWait works like Pop but it wait for the next input operation to finish processing before returning its respective output. Returns false if the queue is empty.

func (*Queue[I, O]) Push added in v0.3.0

func (q *Queue[I, O]) Push(in I)

Push an input onto the queue for background processing.

Jump to

Keyboard shortcuts

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