Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/AaronJan/Hunch
Hunch provides functions like: All, First, Retry, Waterfall etc., that makes asynchronous flow control more intuitive.
https://github.com/AaronJan/Hunch
async asynchronous channel concurrency concurrent context go golang reactivex util
Last synced: 14 days ago
JSON representation
Hunch provides functions like: All, First, Retry, Waterfall etc., that makes asynchronous flow control more intuitive.
- Host: GitHub
- URL: https://github.com/AaronJan/Hunch
- Owner: AaronJan
- License: apache-2.0
- Created: 2019-06-05T13:21:04.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-06-26T13:00:20.000Z (over 2 years ago)
- Last Synced: 2024-04-22T13:32:02.621Z (7 months ago)
- Topics: async, asynchronous, channel, concurrency, concurrent, context, go, golang, reactivex, util
- Language: Go
- Homepage:
- Size: 39.1 KB
- Stars: 97
- Watchers: 2
- Forks: 9
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-go - Hunch - Hunch provides functions like: `All`, `First`, `Retry`, `Waterfall` etc., that makes asynchronous flow control more intuitive. (Goroutines / Search and Analytic Databases)
- awesome-go-extra - Hunch - 06-05T13:21:04Z|2022-06-26T13:00:20Z| (Goroutines / Advanced Console UIs)
README
![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/aaronjan/hunch.svg)
![Build status](https://github.com/aaronjan/hunch/workflows/Go/badge.svg?branch=master)
[![codecov](https://codecov.io/gh/AaronJan/Hunch/branch/master/graph/badge.svg)](https://codecov.io/gh/AaronJan/Hunch)
[![Go Report Card](https://goreportcard.com/badge/github.com/aaronjan/hunch)](https://goreportcard.com/report/github.com/aaronjan/hunch)
![GitHub](https://img.shields.io/github/license/aaronjan/hunch.svg)
[![GoDoc](https://godoc.org/github.com/aaronjan/hunch?status.svg)](https://godoc.org/github.com/aaronjan/hunch)# 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-patternsBut 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`
```shell
$ go get -u -v github.com/aaronjan/hunch
```#### `go mod` (Recommended)
```go
import "github.com/aaronjan/hunch"
``````shell
$ go mod tidy
```### Types
```go
type Executable func(context.Context) (interface{}, error)type ExecutableInSequence func(context.Context, interface{}) (interface{}, error)
```### API
#### All
```go
func All(parentCtx context.Context, execs ...Executable) ([]interface{}, error)
```All returns all the outputs from all Executables, order guaranteed.
##### Examples
```go
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]
```#### Take
```go
func Take(parentCtx context.Context, num int, execs ...Executable) ([]interface{}, error)
```Take returns the first `num` values outputted by the Executables.
##### Examples
```go
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]
```#### Last
```go
func Last(parentCtx context.Context, num int, execs ...Executable) ([]interface{}, error)
```Last returns the last `num` values outputted by the Executables.
##### Examples
```go
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]
```#### Waterfall
```go
func Waterfall(parentCtx context.Context, execs ...ExecutableInSequence) (interface{}, error)
```Waterfall runs `ExecutableInSequence`s 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
```go
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
```#### Retry
```go
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
```go
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 5
```## Credits
Heavily inspired by [Async](https://github.com/caolan/async/) and [ReactiveX](http://reactivex.io/).
## Licence
[Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0)