Hunch
<UNMAINTAINED> Hunch provides functions like: All, First, Retry, Waterfall etc., that makes asynchronous flow control more intuitive.
Install / Use
/learn @AaronJan/HunchREADME
Hunch
Hunch provides functions like: All, First, Retry, Waterfall etc., that makes asynchronous flow control more intuitive.
About Hunch
Go have several concurrency patterns, here're some articles:
- https://blog.golang.org/pipelines
- https://blog.golang.org/context
- https://blog.golang.org/go-concurrency-patterns-timing-out-and
- https://blog.golang.org/advanced-go-concurrency-patterns
But nowadays, using the context package is the most powerful pattern.
So base on context, Hunch provides functions that can help you deal with complex asynchronous logics with ease.
Usage
Installation
go get
$ go get -u -v github.com/aaronjan/hunch
go mod (Recommended)
import "github.com/aaronjan/hunch"
$ go mod tidy
Types
type Executable func(context.Context) (interface{}, error)
type ExecutableInSequence func(context.Context, interface{}) (interface{}, error)
API
All
func All(parentCtx context.Context, execs ...Executable) ([]interface{}, error)
All returns all the outputs from all Executables, order guaranteed.
Examples
ctx := context.Background()
r, err := hunch.All(
ctx,
func(ctx context.Context) (interface{}, error) {
time.Sleep(300 * time.Millisecond)
return 1, nil
},
func(ctx context.Context) (interface{}, error) {
time.Sleep(200 * time.Millisecond)
return 2, nil
},
func(ctx context.Context) (interface{}, error) {
time.Sleep(100 * time.Millisecond)
return 3, nil
},
)
fmt.Println(r, err)
// Output:
// [1 2 3] <nil>
Take
func Take(parentCtx context.Context, num int, execs ...Executable) ([]interface{}, error)
Take returns the first num values outputted by the Executables.
Examples
ctx := context.Background()
r, err := hunch.Take(
ctx,
// Only need the first 2 values.
2,
func(ctx context.Context) (interface{}, error) {
time.Sleep(300 * time.Millisecond)
return 1, nil
},
func(ctx context.Context) (interface{}, error) {
time.Sleep(200 * time.Millisecond)
return 2, nil
},
func(ctx context.Context) (interface{}, error) {
time.Sleep(100 * time.Millisecond)
return 3, nil
},
)
fmt.Println(r, err)
// Output:
// [3 2] <nil>
Last
func Last(parentCtx context.Context, num int, execs ...Executable) ([]interface{}, error)
Last returns the last num values outputted by the Executables.
Examples
ctx := context.Background()
r, err := hunch.Last(
ctx,
// Only need the last 2 values.
2,
func(ctx context.Context) (interface{}, error) {
time.Sleep(300 * time.Millisecond)
return 1, nil
},
func(ctx context.Context) (interface{}, error) {
time.Sleep(200 * time.Millisecond)
return 2, nil
},
func(ctx context.Context) (interface{}, error) {
time.Sleep(100 * time.Millisecond)
return 3, nil
},
)
fmt.Println(r, err)
// Output:
// [2 1] <nil>
Waterfall
func Waterfall(parentCtx context.Context, execs ...ExecutableInSequence) (interface{}, error)
Waterfall runs ExecutableInSequences one by one, passing previous result to next Executable as input. When an error occurred, it stop the process then returns the error. When the parent Context canceled, it returns the Err() of it immediately.
Examples
ctx := context.Background()
r, err := hunch.Waterfall(
ctx,
func(ctx context.Context, n interface{}) (interface{}, error) {
return 1, nil
},
func(ctx context.Context, n interface{}) (interface{}, error) {
return n.(int) + 1, nil
},
func(ctx context.Context, n interface{}) (interface{}, error) {
return n.(int) + 1, nil
},
)
fmt.Println(r, err)
// Output:
// 3 <nil>
Retry
func Retry(parentCtx context.Context, retries int, fn Executable) (interface{}, error)
Retry attempts to get a value from an Executable instead of an Error. It will keeps re-running the Executable when failed no more than retries times. Also, when the parent Context canceled, it returns the Err() of it immediately.
Examples
count := 0
getStuffFromAPI := func() (int, error) {
if count == 5 {
return 1, nil
}
count++
return 0, fmt.Errorf("timeout")
}
ctx := context.Background()
r, err := hunch.Retry(
ctx,
10,
func(ctx context.Context) (interface{}, error) {
rs, err := getStuffFromAPI()
return rs, err
},
)
fmt.Println(r, err, count)
// Output:
// 1 <nil> 5
Credits
Heavily inspired by Async and ReactiveX.
Licence
Related Skills
node-connect
337.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
337.3kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
83.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
337.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
