servicegroup.go 2.2 KB

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