github.com/songzhibin97/gkit@v1.2.13/egroup/liftcycle.go (about) 1 package egroup 2 3 import ( 4 "context" 5 "os" 6 "os/signal" 7 "syscall" 8 9 "github.com/songzhibin97/gkit/goroutine" 10 "github.com/songzhibin97/gkit/options" 11 ) 12 13 // LifeAdminer 生命周期管理接口 14 type LifeAdminer interface { 15 Start(ctx context.Context) error 16 Shutdown(ctx context.Context) error 17 } 18 19 // Member 成员 20 type Member struct { 21 Start func(ctx context.Context) error 22 Shutdown func(ctx context.Context) error 23 } 24 25 // LifeAdmin 生命周期管理 26 type LifeAdmin struct { 27 opts *config 28 members []Member 29 shutdown func() 30 } 31 32 // Add 添加成员表(通过内部 Member 对象添加) 33 func (l *LifeAdmin) Add(member Member) { 34 l.members = append(l.members, member) 35 } 36 37 // AddMember 添加程序表(通过外部接口 LifeAdminer 添加) 38 func (l *LifeAdmin) AddMember(la LifeAdminer) { 39 l.members = append(l.members, Member{ 40 Start: la.Start, 41 Shutdown: la.Shutdown, 42 }) 43 } 44 45 // Start 启动 46 func (l *LifeAdmin) Start() error { 47 ctx := context.Background() 48 ctx, l.shutdown = context.WithCancel(ctx) 49 g := WithContext(ctx) 50 for _, m := range l.members { 51 func(m Member) { 52 // 如果有shutdown进行注册 53 if m.Shutdown != nil { 54 g.Go(func() error { 55 // 等待异常或信号关闭触发 56 <-g.ctx.Done() 57 return goroutine.Delegate(g.ctx, l.opts.stopTimeout, m.Shutdown) 58 }) 59 } 60 if m.Start != nil { 61 g.Go(func() error { 62 return goroutine.Delegate(g.ctx, l.opts.startTimeout, m.Start) 63 }) 64 } 65 }(m) 66 } 67 // 判断是否需要监听信号 68 if len(l.opts.signals) == 0 || l.opts.handler == nil { 69 return g.Wait() 70 } 71 c := make(chan os.Signal, len(l.opts.signals)) 72 // 监听信号 73 signal.Notify(c, l.opts.signals...) 74 g.Go(func() error { 75 for { 76 select { 77 case <-g.ctx.Done(): 78 return g.ctx.Err() 79 case sig := <-c: 80 l.opts.handler(l, sig) 81 } 82 } 83 }) 84 return g.Wait() 85 } 86 87 // Shutdown 停止服务 88 func (l *LifeAdmin) Shutdown() { 89 if l.shutdown != nil { 90 l.shutdown() 91 } 92 } 93 94 // NewLifeAdmin 实例化方法 95 func NewLifeAdmin(opts ...options.Option) *LifeAdmin { 96 // 默认参数 97 o := &config{ 98 startTimeout: startTimeout, 99 stopTimeout: stopTimeout, 100 signals: []os.Signal{syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT}, 101 handler: func(a *LifeAdmin, signal os.Signal) { 102 switch signal { 103 case syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT: 104 a.Shutdown() 105 default: 106 } 107 }, 108 } 109 // 选项模式填充参数 110 for _, opt := range opts { 111 opt(o) 112 } 113 return &LifeAdmin{opts: o} 114 }