aboutsummaryrefslogtreecommitdiff
path: root/rutina.go
diff options
context:
space:
mode:
Diffstat (limited to 'rutina.go')
-rwxr-xr-xrutina.go93
1 files changed, 73 insertions, 20 deletions
diff --git a/rutina.go b/rutina.go
index 8a8cccc..0bdc7e8 100755
--- a/rutina.go
+++ b/rutina.go
@@ -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