flow

package module
v1.11.1 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2025 License: MIT Imports: 6 Imported by: 1

README

Flow

A collection of async/flow control functions

Usage

Eventually

Get the result of a function call later on:

res := flow.Eventually(context.Background(), func(ctx context.Context) (int, error) {
    return 5, nil
})

...

<-res.Done()
if res.Err() != nil {
    panic(res.Err())
}

fmt.Println(res.Out()) // prints 5
Groups

If you need to wait for multiple results to resolve:


fast := flow.Eventually(context.Background(), func(ctx context.Context) (int, error) {
    return 5, nil
})
slow := flow.Eventually(context.Background(), func(ctx context.Context) (string, error) {
    time.Sleep(time.Second * 5)
    return "bongo", nil
})

group := &flow.ResultGroup{}
group.Add(fast)
group.Add(slow)

// The wait function blocks until all results have resolved
group.Wait()

fmt.Println(fast.Out()) // prints 5
fmt.Println(slow.Out()) // prints bongo
Retry

To retry a function a 3 times:

i := 0
f := flow.Retry(func(ctx context.Context) (int, error) {
    defer func() { i++ }()
    if i < 2 {
        return 0, errors.New("demo error")
    }
    return 5, nil
}, 3)

// The above will call the function three times, and will return 5, nil on the third call
out, err := f(context.Background()) // err is nil
fmt.Println(out) // prints 5

To retyr a function 3 times with a millisecond delay between each try:

i := 0
f := flow.RetryDelay(func(ctx context.Context) (int, error) {
    defer func() { i++ }()
    if i < 2 {
        return 0, errors.New("demo error")
    }
    return 5, nil
}, 3, time.Millisecond)

out, err := f(context.Background()) // err is nil
fmt.Println(out) // prints 5
Throttle

To throttle a function call so that it runs once per second:

i := 1
f := flow.Throttle(func(ctx context.Context) (int, error) {
    defer func() { i++ }()
    return i, nil
}, time.Second)

for range 3 {
    fmt.Println(f(context.Background()))
}

Which will print:

1 <nil>
0 throttled
0 throttled

To throttle a function call so that it runs once per second, and returns the first value without a throttled error:

i := 1
f := flow.SilentThrottle(func(ctx context.Context) (int, error) {
    defer func() { i++ }()
    return i, nil
}, time.Millisecond)

for i := range 3 {
    if i == 2 {
        time.Sleep(time.Millisecond * 2)
    }
    fmt.Println(f(context.Background()))
    i++
}

Which will print:

1 <nil>
1 <nil>
2 <nil>

Documentation

Overview

Package flow

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrGroupAlreadyWaiting = errors.New("resultgroup is already waiting")
)
View Source
var (
	ErrThrottled = errors.New("throttled")
)

Functions

func Hedge added in v1.11.0

func Hedge[T any](ctx context.Context, f Effector[T], count int) (T, error)

Types

type Channel added in v1.10.0

type Channel[T, U any] struct {
	// contains filtered or unexported fields
}

func NewChannel added in v1.10.0

func NewChannel[T, U any](ctx context.Context, bufferSize int, cb Work[T, U]) *Channel[T, U]

func (*Channel[T, U]) Push added in v1.10.0

func (c *Channel[T, U]) Push(item T) *Response[U]

type Effector

type Effector[T any] func(context.Context) (T, error)

func Retry added in v1.1.0

func Retry[T any](f Effector[T], times int) Effector[T]

Retries calling the effector x times if it fails

func RetryDelay added in v1.2.0

func RetryDelay[T any](f Effector[T], times int, delay time.Duration) Effector[T]

Does the same a Retry, but adds a delay after each attempt

func SilentThrottle added in v1.4.0

func SilentThrottle[T any](f Effector[T], every time.Duration) Effector[T]

func Throttle

func Throttle[T any](f Effector[T], every time.Duration) Effector[T]

Return an Effector that, when called, will only fire once every duration

type EffectorIn added in v1.7.0

type EffectorIn[T any] func(context.Context, T) error

func SilentThrottleIn added in v1.7.1

func SilentThrottleIn[T any](f EffectorIn[T], every time.Duration) EffectorIn[T]

func ThrottleIn added in v1.7.0

func ThrottleIn[T any](f EffectorIn[T], every time.Duration) EffectorIn[T]

type ExpiringStore added in v1.8.0

type ExpiringStore[T any] struct {
	// contains filtered or unexported fields
}

func NewExpiringStore added in v1.8.0

func NewExpiringStore[T any]() *ExpiringStore[T]

func (*ExpiringStore[T]) Close added in v1.8.0

func (e *ExpiringStore[T]) Close()

Close the store, this will block until all items in the store have been expired before it returns, so be careful over the max expiry time you use when adding items to the store

func (*ExpiringStore[T]) Closed added in v1.8.0

func (e *ExpiringStore[T]) Closed() <-chan struct{}

func (*ExpiringStore[T]) Delete added in v1.8.0

func (e *ExpiringStore[T]) Delete(id string)

func (*ExpiringStore[T]) Get added in v1.8.0

func (e *ExpiringStore[T]) Get(id string) (T, bool)

func (*ExpiringStore[T]) Put added in v1.8.0

func (e *ExpiringStore[T]) Put(id string, val T, exp time.Duration, callbacks ...ExpiryCallback[T])

type ExpiryCallback added in v1.8.3

type ExpiryCallback[T any] func(key string, val T)

type HedgeClient added in v1.11.0

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

func NewHedgeClient added in v1.11.0

func NewHedgeClient(c *http.Client, count int) *HedgeClient

func (*HedgeClient) Do added in v1.11.0

func (h *HedgeClient) Do(r *http.Request) (*http.Response, error)

type OncePer added in v1.9.0

type OncePer[T comparable] struct {
	// contains filtered or unexported fields
}

func NewOncePer added in v1.9.0

func NewOncePer[T comparable]() *OncePer[T]

func (*OncePer[T]) Do added in v1.9.0

func (o *OncePer[T]) Do(key T, f func())

func (*OncePer[T]) Reset added in v1.9.1

func (o *OncePer[T]) Reset(key T)

type Response added in v1.10.0

type Response[T any] struct {
	// contains filtered or unexported fields
}

func (*Response[T]) Err added in v1.10.0

func (r *Response[T]) Err() error

func (*Response[T]) Output added in v1.10.0

func (r *Response[T]) Output() T

type Result added in v1.3.0

type Result[T any] struct {
	// contains filtered or unexported fields
}

func Eventually added in v1.3.0

func Eventually[T any](ctx context.Context, f Effector[T]) *Result[T]

func (*Result[T]) Done added in v1.5.0

func (r *Result[T]) Done() <-chan struct{}

func (*Result[T]) Err added in v1.3.0

func (r *Result[T]) Err() error

func (*Result[T]) Out added in v1.3.0

func (r *Result[T]) Out() T

type ResultGroup added in v1.5.0

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

func (*ResultGroup) Add added in v1.5.0

func (r *ResultGroup) Add(res resultItem) error

Add an item to the result group This will return an error if Wait has already been called. When Wait has finished, you can add more results to resolve.

func (*ResultGroup) Wait added in v1.5.0

func (r *ResultGroup) Wait()

Wait blocks until every result has resolved

type Store added in v1.6.1

type Store[T any] struct {
	// contains filtered or unexported fields
}

func NewStore added in v1.6.1

func NewStore[T any]() *Store[T]

func (*Store[T]) Delete added in v1.6.1

func (p *Store[T]) Delete(id string)

func (*Store[T]) Get added in v1.6.1

func (p *Store[T]) Get(id string) (T, bool)

func (*Store[T]) Len added in v1.6.2

func (p *Store[T]) Len() int

func (*Store[T]) Put added in v1.6.1

func (p *Store[T]) Put(id string, val T)

type Work added in v1.10.0

type Work[T, U any] func(T) (U, error)

Jump to

Keyboard shortcuts

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