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  }