You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
64 lines
1.4 KiB
64 lines
1.4 KiB
package tdsync |
|
|
|
import ( |
|
"context" |
|
"sync" |
|
) |
|
|
|
// Supervisor is simple task group primitive to control multiple |
|
// long-live tasks. |
|
// Unlike Groups, Supervisor does not cancel when one task is failed. |
|
// Unlike WaitGroup and errgroup.Group this is not allowed to use zero value. |
|
type Supervisor struct { |
|
wg sync.WaitGroup |
|
|
|
ctx context.Context |
|
cancel context.CancelFunc |
|
|
|
onError func(err error) |
|
} |
|
|
|
// NewSupervisor creates new Supervisor. |
|
func NewSupervisor(parent context.Context) *Supervisor { |
|
ctx, cancel := context.WithCancel(parent) |
|
|
|
return &Supervisor{ |
|
ctx: ctx, |
|
cancel: cancel, |
|
} |
|
} |
|
|
|
// WithErrorHandler sets tasks error handler |
|
// Must be called before any Go calls. |
|
func (s *Supervisor) WithErrorHandler(h func(err error)) *Supervisor { |
|
s.onError = h |
|
return s |
|
} |
|
|
|
// Go calls the given function in a new goroutine. |
|
func (s *Supervisor) Go(task func(ctx context.Context) error) { |
|
s.wg.Add(1) |
|
go func() { |
|
defer s.wg.Done() |
|
|
|
if err := task(s.ctx); err != nil { |
|
if s.onError != nil { |
|
s.onError(err) |
|
} |
|
} |
|
}() |
|
} |
|
|
|
// Cancel cancels all goroutines in group. |
|
// |
|
// Note: context cancellation error can be returned by Wait(). |
|
func (s *Supervisor) Cancel() { |
|
s.cancel() |
|
} |
|
|
|
// Wait blocks until all function calls from the Go method have returned, then |
|
// returns the first non-nil error (if any) from them. |
|
func (s *Supervisor) Wait() error { |
|
s.wg.Wait() |
|
return nil |
|
}
|
|
|