Skip to content
/ hunch Public
forked from AaronJan/Hunch

Hunch provides functions like: All, First, Retry, Waterfall etc., that makes asynchronous flow control more intuitive.

License

Notifications You must be signed in to change notification settings

uded/hunch

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Housekeeper

GitHub tag (latest SemVer) Build status codecov Go Report Card GitHub GoDoc

Hunch

Hunch provides functions like: All, First, Retry, Waterfall etc., that makes asynchronous flow control more intuitive.

This is a up-to-date repo for the original one available at https://github.com/AaronJan/Hunch I will be more than happy to fix any errors, merge pull-requests or just move it forward.

About Hunch

Go have several concurrency patterns, here are some articles:

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/uded/hunch

go mod (Recommended)

import "github.com/uded/hunch"
$ go mod tidy

Types

type Executable[T interface{} func(context.Context) (T, error)

type ExecutableInSequence[T interface{} func(context.Context, T) (T, error)

API

All

func All[T any](parentCtx context.Context, execs ...Executable[T]) ([]T, error) 

All returns all the outputs from all Executables, order guaranteed.

Examples
ctx := context.Background()
r, err := hunch.All(
    ctx,
    func(ctx context.Context) (int64, error) {
        time.Sleep(300 * time.Millisecond)
        return 1, nil
    },
    func(ctx context.Context) (int64, error) {
        time.Sleep(200 * time.Millisecond)
        return 2, nil
    },
    func(ctx context.Context) (int64, error) {
        time.Sleep(100 * time.Millisecond)
        return 3, nil
    },
)

fmt.Println(r, err)
// Output:
// [1 2 3] <nil>

Take

func Take[T interface{}](parentCtx context.Context, num int, execs ...Executable[T]) ([]T, 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) (int64, error) {
        time.Sleep(300 * time.Millisecond)
        return 1, nil
    },
    func(ctx context.Context) (int64, error) {
        time.Sleep(200 * time.Millisecond)
        return 2, nil
    },
    func(ctx context.Context) (int64, error) {
        time.Sleep(100 * time.Millisecond)
        return 3, nil
    },
)

fmt.Println(r, err)
// Output:
// [3 2] <nil>

Last

func Last[T any](parentCtx context.Context, num int, execs ...Executable[T]) ([]T, 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) (int64, error) {
        time.Sleep(300 * time.Millisecond)
        return 1, nil
    },
    func(ctx context.Context) (int64, error) {
        time.Sleep(200 * time.Millisecond)
        return 2, nil
    },
    func(ctx context.Context) (int64, error) {
        time.Sleep(100 * time.Millisecond)
        return 3, nil
    },
)

fmt.Println(r, err)
// Output:
// [2 1] <nil>

Waterfall

func Waterfall[T any](parentCtx context.Context, execs ...ExecutableInSequence[T]) (T, 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 int) (int, error) {
        return 1, nil
    },
    func(ctx context.Context, n int) (int, error) {
        return n + 1, nil
    },
    func(ctx context.Context, n int) (int, error) {
        return n + 1, nil
    },
)

fmt.Println(r, err)
// Output:
// 3 <nil>

Retry

func Retry[T any](parentCtx context.Context, retries int, fn Executable[T]) (T, 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) (int, error) {
        rs, err := getStuffFromAPI()

        return rs, err
    },
)

fmt.Println(r, err, count)
// Output:
// 1 <nil> 5

Credits

Heavily inspired by Async and ReactiveX.

Licence

Apache 2.0

About

Hunch provides functions like: All, First, Retry, Waterfall etc., that makes asynchronous flow control more intuitive.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 99.0%
  • Makefile 1.0%