Skip to content

Commit 74db4a9

Browse files
authored
feat(action): added Action support (#4)
1 parent c749421 commit 74db4a9

8 files changed

+813
-262
lines changed

.deepsource.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
version = 1
22

3+
test_patterns = ["*_test.go"]
4+
5+
exclude_patterns = ["*_test.go"]
6+
37
[[analyzers]]
48
name = "go"
59

610
[analyzers.meta]
711
import_root = "github.com/yaitoo/async"
812

913
[[transformers]]
10-
name = "gofmt"
14+
name = "gofmt"
15+
16+

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88

9+
## [1.0.4] - 2024-03-18
10+
- added `Action` support (#4)
911

1012
## [1.0.3] - 2024-03-12
1113
- added `WaitN` (#1)

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Async
2-
Async is an asynchronous task package for Go.
2+
Async is an async/await like task package for Go
33

44
![License](https://img.shields.io/badge/license-MIT-green.svg)
55
[![Tests](https://github.com/yaitoo/async/actions/workflows/tests.yml/badge.svg)](https://github.com/yaitoo/async/actions/workflows/tests.yml)
@@ -10,12 +10,12 @@ Async is an asynchronous task package for Go.
1010

1111

1212
## Features
13-
- Wait/WaitAny/WaitN
13+
- Wait/WaitAny/WaitN for `Task` and `Action`
1414
- `context.Context` with `timeout`, `cancel` support
1515
- Works with generic instead of `interface{}`
1616

1717
## Tutorials
18-
see more examples on [tests](./awaiter_test.go) or [go.dev](https://go.dev/play/p/7jgcRltbwts)
18+
see more examples on [tasks](./waiter_test.go), [actions](./awaiter_test.go) or [go.dev](https://go.dev/play/p/7jgcRltbwts)
1919

2020
### Install async
2121
- install latest commit from `main` branch

async.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,25 @@ import (
66
)
77

88
var (
9-
ErrTooLessDone = errors.New("async: too less tasks to completed without error")
9+
ErrTooLessDone = errors.New("async: too less tasks/actions to completed without error")
1010
)
1111

12-
func New[T any](tasks ...func(ctx context.Context) (T, error)) Awaiter[T] {
13-
return &awaiter[T]{
12+
// Task a task with result T
13+
type Task[T any] func(ctx context.Context) (T, error)
14+
15+
// New create a task waiter
16+
func New[T any](tasks ...Task[T]) Waiter[T] {
17+
return &waiter[T]{
1418
tasks: tasks,
1519
}
1620
}
21+
22+
// Action a task without result
23+
type Action func(ctx context.Context) error
24+
25+
// NewA create an action awaiter
26+
func NewA(actions ...Action) Awaiter {
27+
return &awaiter{
28+
actions: actions,
29+
}
30+
}

awaiter.go

+46-64
Original file line numberDiff line numberDiff line change
@@ -4,112 +4,94 @@ import (
44
"context"
55
)
66

7-
type Awaiter[T any] interface {
8-
// Add add a task
9-
Add(task func(context.Context) (T, error))
10-
// Wait wail for all tasks to completed
11-
Wait(context.Context) ([]T, []error, error)
12-
// WaitAny wait for any task to completed without error, can cancel other tasks
13-
WaitAny(context.Context) (T, []error, error)
14-
// WaitN wait for N tasks to completed without error
15-
WaitN(context.Context, int) ([]T, []error, error)
7+
type Awaiter interface {
8+
// Add add an action
9+
Add(action Action)
10+
// Wait wail for all actions to completed
11+
Wait(context.Context) ([]error, error)
12+
// WaitAny wait for any action to completed without error, can cancel other tasks
13+
WaitAny(context.Context) ([]error, error)
14+
// WaitN wait for N actions to completed without error
15+
WaitN(context.Context, int) ([]error, error)
1616
}
1717

18-
type awaiter[T any] struct {
19-
tasks []func(context.Context) (T, error)
18+
type awaiter struct {
19+
actions []Action
2020
}
2121

22-
func (a *awaiter[T]) Add(task func(ctx context.Context) (T, error)) {
23-
a.tasks = append(a.tasks, task)
22+
func (a *awaiter) Add(action Action) {
23+
a.actions = append(a.actions, action)
2424
}
2525

26-
func (a *awaiter[T]) Wait(ctx context.Context) ([]T, []error, error) {
27-
wait := make(chan Result[T])
26+
func (a *awaiter) Wait(ctx context.Context) ([]error, error) {
27+
wait := make(chan error)
2828

29-
for _, task := range a.tasks {
30-
go func(task func(context.Context) (T, error)) {
31-
r, err := task(ctx)
32-
wait <- Result[T]{
33-
Data: r,
34-
Error: err,
35-
}
36-
}(task)
29+
for _, action := range a.actions {
30+
go func(action Action) {
31+
32+
wait <- action(ctx)
33+
}(action)
3734
}
3835

39-
var r Result[T]
4036
var taskErrs []error
41-
var items []T
4237

43-
tt := len(a.tasks)
38+
tt := len(a.actions)
4439
for i := 0; i < tt; i++ {
4540
select {
46-
case r = <-wait:
47-
if r.Error != nil {
48-
taskErrs = append(taskErrs, r.Error)
49-
} else {
50-
items = append(items, r.Data)
41+
case err := <-wait:
42+
if err != nil {
43+
taskErrs = append(taskErrs, err)
5144
}
5245
case <-ctx.Done():
53-
return items, taskErrs, ctx.Err()
46+
return taskErrs, ctx.Err()
5447
}
5548
}
5649

57-
if len(items) == tt {
58-
return items, taskErrs, nil
50+
if len(taskErrs) > 0 {
51+
return taskErrs, ErrTooLessDone
5952
}
6053

61-
return items, taskErrs, ErrTooLessDone
54+
return taskErrs, nil
6255
}
6356

64-
func (a *awaiter[T]) WaitN(ctx context.Context, n int) ([]T, []error, error) {
65-
wait := make(chan Result[T])
57+
func (a *awaiter) WaitN(ctx context.Context, n int) ([]error, error) {
58+
wait := make(chan error)
6659

6760
cancelCtx, cancel := context.WithCancel(ctx)
6861
defer cancel()
6962

70-
for _, task := range a.tasks {
71-
go func(task func(context.Context) (T, error)) {
72-
r, err := task(cancelCtx)
73-
wait <- Result[T]{
74-
Data: r,
75-
Error: err,
76-
}
77-
}(task)
63+
for _, action := range a.actions {
64+
go func(action Action) {
65+
wait <- action(cancelCtx)
66+
67+
}(action)
7868
}
7969

80-
var r Result[T]
8170
var taskErrs []error
82-
var items []T
83-
tt := len(a.tasks)
71+
tt := len(a.actions)
72+
8473
var done int
8574
for i := 0; i < tt; i++ {
8675
select {
87-
case r = <-wait:
88-
if r.Error != nil {
89-
taskErrs = append(taskErrs, r.Error)
76+
case err := <-wait:
77+
if err != nil {
78+
taskErrs = append(taskErrs, err)
9079
} else {
91-
items = append(items, r.Data)
80+
9281
done++
9382
if done == n {
94-
return items, taskErrs, nil
83+
return taskErrs, nil
9584
}
9685
}
9786
case <-ctx.Done():
98-
return items, taskErrs, ctx.Err()
87+
return taskErrs, ctx.Err()
9988
}
10089

10190
}
10291

103-
return items, taskErrs, ErrTooLessDone
92+
return taskErrs, ErrTooLessDone
10493
}
10594

106-
func (a *awaiter[T]) WaitAny(ctx context.Context) (T, []error, error) {
107-
var t T
108-
result, err, taskErrs := a.WaitN(ctx, 1)
109-
110-
if len(result) == 1 {
111-
t = result[0]
112-
}
113-
114-
return t, err, taskErrs
95+
func (a *awaiter) WaitAny(ctx context.Context) ([]error, error) {
96+
return a.WaitN(ctx, 1)
11597
}

0 commit comments

Comments
 (0)