diff options
Diffstat (limited to 'rutina.go')
-rwxr-xr-x | rutina.go | 93 |
1 files changed, 73 insertions, 20 deletions
@@ -22,35 +22,54 @@ type Rutina struct { } // New instance with builtin context -func New(opts ...Option) *Rutina { +func New(mixins ...Mixin) *Rutina { ctx, cancel := context.WithCancel(context.Background()) var counter uint64 = 0 r := &Rutina{ctx: ctx, Cancel: cancel, counter: &counter, cancelByError: false} - return r.WithOptions(opts...) + return r.With(mixins...) } -func (r *Rutina) WithOptions(opts ...Option) *Rutina { +func (r *Rutina) With(mixins ...Mixin) *Rutina { nr := *r - for _, o := range opts { - o.apply(&nr) + for _, m := range mixins { + m.apply(&nr) } return &nr } // Go routine -func (r *Rutina) Go(doer func(ctx context.Context) error) { +func (r *Rutina) Go(doer func(ctx context.Context) error, opts ...Options) { + onFail := ShutdownIfFail + for _, o := range opts { + switch o { + case ShutdownIfFail: + onFail = ShutdownIfFail + case RestartIfFail: + onFail = RestartIfFail + case DoNothingIfFail: + onFail = DoNothingIfFail + } + } + onDone := DoNothingIfDone + for _, o := range opts { + switch o { + case ShutdownIfDone: + onDone = ShutdownIfDone + case RestartIfDone: + onDone = RestartIfDone + case DoNothingIfDone: + onDone = DoNothingIfDone + } + } + r.wg.Add(1) go func() { + defer r.wg.Done() + // Check that context is not canceled yet + if r.ctx.Err() != nil { + return + } id := atomic.AddUint64(r.counter, 1) - defer func() { - if r.logger != nil { - r.logger.Printf("stopping #%d", id) - } - r.wg.Done() - if !r.cancelByError { - r.Cancel() - } - }() if r.logger != nil { r.logger.Printf("starting #%d", id) } @@ -58,13 +77,47 @@ func (r *Rutina) Go(doer func(ctx context.Context) error) { if r.logger != nil { r.logger.Printf("error at #%d : %v", id, err) } - r.o.Do(func() { - r.err = err - }) - if r.cancelByError { + switch onFail { + case ShutdownIfFail: + if r.logger != nil { + r.logger.Printf("stopping #%d", id) + } + // Save error only if shutdown all routines + r.o.Do(func() { + r.err = err + }) + r.Cancel() + case RestartIfFail: + // TODO maybe store errors on restart? + if r.logger != nil { + r.logger.Printf("restarting #%d", id) + } + r.Go(doer, opts...) + case DoNothingIfFail: + // TODO maybe store errors on nothing to do? + if r.logger != nil { + r.logger.Printf("stopping #%d", id) + } + } + } else { + switch onDone { + case ShutdownIfDone: + if r.logger != nil { + r.logger.Printf("stopping #%d with shutdown", id) + } r.Cancel() + case RestartIfDone: + if r.logger != nil { + r.logger.Printf("restarting #%d", id) + } + r.Go(doer, opts...) + case DoNothingIfDone: + if r.logger != nil { + r.logger.Printf("stopping #%d", id) + } } } + }() } @@ -84,7 +137,7 @@ func (r *Rutina) ListenOsSignals() { case <-ctx.Done(): } return nil - }) + }, ShutdownIfDone) } // Wait all routines and returns first error or nil if all routines completes without errors |