diff options
author | Alexander Kiryukhin <a.kiryukhin@mail.ru> | 2019-06-15 10:20:37 +0300 |
---|---|---|
committer | Alexander Kiryukhin <a.kiryukhin@mail.ru> | 2019-06-15 10:20:37 +0300 |
commit | 741cf397a9150a8f76b8f74289b1dde8aaa43d02 (patch) | |
tree | 66a64d97e247b57b37d82493eb307d1bf64c7490 | |
parent | c691d422395cb72283512d8956a255db10b70b44 (diff) |
WIP: Added lifecycle mixin
Removed hooks
-rwxr-xr-x | README.md | 13 | ||||
-rwxr-xr-x | mixins.go | 14 | ||||
-rwxr-xr-x | rutina.go | 54 |
3 files changed, 38 insertions, 43 deletions
@@ -96,9 +96,9 @@ err := <- r.Errors() Disabled by default. Use `r.With(rutina.WithErrChan())` to turn on. -## Events and hooks +## Lifecycle events -Rutina has own simple lifecycle events system. You can subscribe your hooks on any of this events: +Rutina has own simple lifecycle events: * `EventRoutineStart` - Fires when starts new routine * `EventRoutineStop` - Fires when routine stopped with any result @@ -108,15 +108,6 @@ Rutina has own simple lifecycle events system. You can subscribe your hooks on a * `EventAppComplete` - Fires when all routines stopped with no errors * `EventAppFail` - Fires when all routines stopped with error -Example: - -```go -r.RegisterHook(rutina.EventRoutineStart, func(ev rutina.Event, rid int) error { - log.Println("Started routine with ID", rid) - return nil -}) -``` - ## Mixins ### Usage @@ -58,3 +58,17 @@ func WithErrChan() *MixinErrChan { func (o MixinErrChan) apply(r *Rutina) { r.errCh = make(chan error, 1) } + +type LifecycleListener func(event Event, routineID int) + +type LifecycleMixin struct { + Listener LifecycleListener +} + +func (l LifecycleMixin) apply(r *Rutina) { + r.lifecycleListener = l.Listener +} + +func WithLifecycleListener(listener LifecycleListener) *LifecycleMixin { + return &LifecycleMixin{Listener: listener} +} @@ -12,23 +12,23 @@ import ( //Rutina is routine manager type Rutina struct { - ctx context.Context // State of application (started/stopped) - Cancel func() // Cancel func that stops all routines - wg sync.WaitGroup // WaitGroup that wait all routines to complete - onceErr sync.Once // Flag that prevents overwrite first error that shutdowns all routines - onceWait sync.Once // Flag that prevents wait already waited rutina - err error // First error that shutdowns all routines - logger *log.Logger // Optional logger - counter *uint64 // Optional counter that names routines with increment ids for debug purposes at logger - errCh chan error // Optional channel for errors when RestartIfFail and DoNothingIfFail - hooks map[Event][]Hook // Lifecycle hooks + ctx context.Context // State of application (started/stopped) + Cancel func() // Cancel func that stops all routines + wg sync.WaitGroup // WaitGroup that wait all routines to complete + onceErr sync.Once // Flag that prevents overwrite first error that shutdowns all routines + onceWait sync.Once // Flag that prevents wait already waited rutina + err error // First error that shutdowns all routines + logger *log.Logger // Optional logger + counter *uint64 // Optional counter that names routines with increment ids for debug purposes at logger + errCh chan error // Optional channel for errors when RestartIfFail and DoNothingIfFail + lifecycleListener LifecycleListener // Optional listener for events } // New instance with builtin context func New(mixins ...Mixin) *Rutina { ctx, cancel := context.WithCancel(context.Background()) var counter uint64 - r := &Rutina{ctx: ctx, Cancel: cancel, counter: &counter, errCh: nil, hooks: map[Event][]Hook{}} + r := &Rutina{ctx: ctx, Cancel: cancel, counter: &counter, errCh: nil} return r.With(mixins...) } @@ -40,10 +40,6 @@ func (r *Rutina) With(mixins ...Mixin) *Rutina { return r } -func (r *Rutina) RegisterHook(ev Event, hook Hook) { - r.hooks[ev] = append(r.hooks[ev], hook) -} - // Go routine func (r *Rutina) Go(doer func(ctx context.Context) error, opts ...Options) { // Check that context is not canceled yet @@ -77,10 +73,10 @@ func (r *Rutina) Go(doer func(ctx context.Context) error, opts ...Options) { go func() { defer r.wg.Done() id := atomic.AddUint64(r.counter, 1) - r.fire(EventRoutineStart, int(id)) + r.lifecycleEvent(EventRoutineStart, int(id)) if err := doer(r.ctx); err != nil { - r.fire(EventRoutineFail, int(id)) - r.fire(EventRoutineStop, int(id)) + r.lifecycleEvent(EventRoutineFail, int(id)) + r.lifecycleEvent(EventRoutineStop, int(id)) // errors history if r.errCh != nil { r.errCh <- err @@ -98,8 +94,8 @@ func (r *Rutina) Go(doer func(ctx context.Context) error, opts ...Options) { } // endregion } else { - r.fire(EventRoutineComplete, int(id)) - r.fire(EventRoutineStop, int(id)) + r.lifecycleEvent(EventRoutineComplete, int(id)) + r.lifecycleEvent(EventRoutineStop, int(id)) // region routine successfully done switch onDone { case ShutdownIfDone: @@ -140,11 +136,11 @@ func (r *Rutina) ListenOsSignals(signals ...os.Signal) { func (r *Rutina) Wait() error { r.onceWait.Do(func() { r.wg.Wait() - r.fire(EventAppStop, 0) + r.lifecycleEvent(EventAppStop, 0) if r.err == nil { - r.fire(EventAppComplete, 0) + r.lifecycleEvent(EventAppComplete, 0) } else { - r.fire(EventAppFail, 0) + r.lifecycleEvent(EventAppFail, 0) } if r.errCh != nil { close(r.errCh) @@ -153,16 +149,10 @@ func (r *Rutina) Wait() error { return r.err } -func (r *Rutina) fire(ev Event, rid int) { +func (r *Rutina) lifecycleEvent(ev Event, rid int) { r.log("Event = %s Routine ID = %d", ev.String(), rid) - if hooks, ok := r.hooks[ev]; ok == true { - for _, h := range hooks { - if err := h(ev, r, rid); err != nil { - if r.errCh != nil { - r.errCh <- err - } - } - } + if r.lifecycleListener != nil { + r.lifecycleListener(ev, rid) } } |