HH-442: isolate runtime processes and harden shutdown (#90)
* HH-442: isolate runtime processes and harden shutdown * HH-442: harden worker shutdown races * HH-442: gate dependency shutdown on active handlers --------- Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package lifecycle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// HandlerGroup stops new handlers, cancels their shared lifecycle context,
|
||||
// and waits for handlers already using application dependencies.
|
||||
type HandlerGroup struct {
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
|
||||
mu sync.Mutex
|
||||
done *sync.Cond
|
||||
active int
|
||||
stopped bool
|
||||
}
|
||||
|
||||
func NewHandlerGroup() *HandlerGroup {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
g := &HandlerGroup{ctx: ctx, cancel: cancel}
|
||||
g.done = sync.NewCond(&g.mu)
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *HandlerGroup) Context() context.Context { return g.ctx }
|
||||
|
||||
func (g *HandlerGroup) Begin() bool {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
if g.stopped {
|
||||
return false
|
||||
}
|
||||
g.active++
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *HandlerGroup) Done() {
|
||||
g.mu.Lock()
|
||||
g.active--
|
||||
if g.active == 0 {
|
||||
g.done.Broadcast()
|
||||
}
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
||||
func (g *HandlerGroup) Stop() {
|
||||
g.mu.Lock()
|
||||
if !g.stopped {
|
||||
g.stopped = true
|
||||
g.cancel()
|
||||
}
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
||||
func (g *HandlerGroup) Wait() {
|
||||
g.mu.Lock()
|
||||
for g.active != 0 {
|
||||
g.done.Wait()
|
||||
}
|
||||
g.mu.Unlock()
|
||||
}
|
||||
Reference in New Issue
Block a user