Skip to content

Commit

Permalink
refactor waitGroup chanel in a simpler solution
Browse files Browse the repository at this point in the history
  • Loading branch information
mrsoftware committed Oct 8, 2024
1 parent c919624 commit 52e7623
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 17 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,34 @@ if err := wg.Wait(); err != nil {
// oh, something bad happened in one of routines above.
}
```
### Turn WaitGroup into a chanel
```go
import (
"github.com/mrsoftware/errors"
)

wg := errors.NewWaitGroup()

wg.Do(func(ctx context.Context) error {
return callingHttpClient()
})

wg.Do(func(ctx context.Context) error {
return callingHttpClient()
})

// this wait until receive something from chanel.
var err error
select {
case err = <-errors.WaitChanel(wg):
}

if err != nil {
// oh, something bad happened in one of the routines above.
}

```


for mode details, check the [documentation](https://godoc.org/github.com/mrsoftware/errors)

Expand Down
27 changes: 10 additions & 17 deletions waitGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ type WaitGroup struct {
ctx context.Context
cancel context.CancelCauseFunc
cancelOnce sync.Once
wait chan struct{}
}

// NewWaitGroup create new WaitGroup.
Expand All @@ -36,7 +35,7 @@ func NewWaitGroup(options ...WaitGroupOption) *WaitGroup {

ctx, cancel := context.WithCancelCause(ops.Ctx)

return &WaitGroup{options: ops, gch: gch, ctx: ctx, cancel: cancel, wait: make(chan struct{})}
return &WaitGroup{options: ops, gch: gch, ctx: ctx, cancel: cancel}
}

// Context of current waitGroup.
Expand All @@ -55,21 +54,6 @@ func (g *WaitGroup) Wait() (err error) {

defer func() { g.Stop(err) }()

select {
case g.wait <- struct{}{}:
default:
}

return g.errors.Err()
}

// WaitChan is like Wait method but return chanel.
func (g *WaitGroup) WaitChan() <-chan struct{} {
return g.wait
}

// Err of tasks.
func (g *WaitGroup) Err() error {
return g.errors.Err()
}

Expand Down Expand Up @@ -175,3 +159,12 @@ func WaitGroupWithContext(ctx context.Context) WaitGroupOption {
g.Ctx = ctx
}
}

// WaitChanel turn WaitGroup Wait method into chanel.
func WaitChanel(wg *WaitGroup) chan error {
wait := make(chan error)

go func() { wait <- wg.Wait() }()

return wait
}
42 changes: 42 additions & 0 deletions waitGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,48 @@ func TestGroup(t *testing.T) {
})
}

func TestWaitChanel(t *testing.T) {
t.Run("expect to turn wait into chanel and work", func(t *testing.T) {
wg := NewWaitGroup()

wg.Do(func(ctx context.Context) error {
return nil
})

wg.Do(func(ctx context.Context) error {
return nil
})

var err error
select {
case err = <-WaitChanel(wg):
}

assert.Nil(t, err)
})

t.Run("expect to turn wait into chanel and get error (one task is failed)", func(t *testing.T) {
wg := NewWaitGroup()

internalErr := errors.New("some error")

wg.Do(func(ctx context.Context) error {
return nil
})

wg.Do(func(ctx context.Context) error {
return internalErr
})

var err error
select {
case err = <-WaitChanel(wg):
}

assert.Equal(t, NewMultiError(internalErr), err)
})
}

// all below test cases are copied from sync/waitgroup_test.go and transformed to group.

func testWaitGroup(t *testing.T, wg1 *WaitGroup, wg2 *WaitGroup) {
Expand Down

0 comments on commit 52e7623

Please sign in to comment.