github.com/lingyao2333/mo-zero@v1.4.1/core/service/servicegroup.go (about) 1 package service 2 3 import ( 4 "log" 5 6 "github.com/lingyao2333/mo-zero/core/proc" 7 "github.com/lingyao2333/mo-zero/core/syncx" 8 "github.com/lingyao2333/mo-zero/core/threading" 9 ) 10 11 type ( 12 // Starter is the interface wraps the Start method. 13 Starter interface { 14 Start() 15 } 16 17 // Stopper is the interface wraps the Stop method. 18 Stopper interface { 19 Stop() 20 } 21 22 // Service is the interface that groups Start and Stop methods. 23 Service interface { 24 Starter 25 Stopper 26 } 27 28 // A ServiceGroup is a group of services. 29 // Attention: the starting order of the added services is not guaranteed. 30 ServiceGroup struct { 31 services []Service 32 stopOnce func() 33 } 34 ) 35 36 // NewServiceGroup returns a ServiceGroup. 37 func NewServiceGroup() *ServiceGroup { 38 sg := new(ServiceGroup) 39 sg.stopOnce = syncx.Once(sg.doStop) 40 return sg 41 } 42 43 // Add adds service into sg. 44 func (sg *ServiceGroup) Add(service Service) { 45 // push front, stop with reverse order. 46 sg.services = append([]Service{service}, sg.services...) 47 } 48 49 // Start starts the ServiceGroup. 50 // There should not be any logic code after calling this method, because this method is a blocking one. 51 // Also, quitting this method will close the logx output. 52 func (sg *ServiceGroup) Start() { 53 proc.AddShutdownListener(func() { 54 log.Println("Shutting down...") 55 sg.stopOnce() 56 }) 57 58 sg.doStart() 59 } 60 61 // Stop stops the ServiceGroup. 62 func (sg *ServiceGroup) Stop() { 63 sg.stopOnce() 64 } 65 66 func (sg *ServiceGroup) doStart() { 67 routineGroup := threading.NewRoutineGroup() 68 69 for i := range sg.services { 70 service := sg.services[i] 71 routineGroup.RunSafe(func() { 72 service.Start() 73 }) 74 } 75 76 routineGroup.Wait() 77 } 78 79 func (sg *ServiceGroup) doStop() { 80 for _, service := range sg.services { 81 service.Stop() 82 } 83 } 84 85 // WithStart wraps a start func as a Service. 86 func WithStart(start func()) Service { 87 return startOnlyService{ 88 start: start, 89 } 90 } 91 92 // WithStarter wraps a Starter as a Service. 93 func WithStarter(start Starter) Service { 94 return starterOnlyService{ 95 Starter: start, 96 } 97 } 98 99 type ( 100 stopper struct{} 101 102 startOnlyService struct { 103 start func() 104 stopper 105 } 106 107 starterOnlyService struct { 108 Starter 109 stopper 110 } 111 ) 112 113 func (s stopper) Stop() { 114 } 115 116 func (s startOnlyService) Start() { 117 s.start() 118 }