in pkg/boot/module.go [65:124]
func (m *ModuleStarter) Run(ctx context.Context, startUpSuccessCallback func(*module.Manager)) error {
// resolve module dependencies
if err := m.ResolveDependency(); err != nil {
return err
}
if len(m.orderedModules) == 0 {
return fmt.Errorf("no module is active")
}
shutdownChannel := make(chan error)
m.moduleManager = module.NewManager(m.orderedModules, func(err error) {
shutdownChannel <- err
})
// startup modules
defer m.shutdownModules(ctx)
for _, module := range m.orderedModules {
moduleName := module.Name()
// start module
log.Debugf("starting module %s", moduleName)
if err := module.Start(ctx, m.moduleManager); err != nil {
return fmt.Errorf("start module %s failure: %v", moduleName, err)
}
log.Infof("module %s start successful", moduleName)
// append to started modules
m.startedModules = append(m.startedModules, module)
}
// notify all modules setup success
for _, mod := range m.startedModules {
mod.NotifyStartSuccess()
}
if startUpSuccessCallback != nil {
startUpSuccessCallback(m.moduleManager)
}
// register terminal
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
var wg sync.WaitGroup
wg.Add(1)
go func() {
select {
case <-signals:
log.Infof("detect shutdown signal")
break
case <-ctx.Done():
log.Infof("detect background context have been down, error by: %v", ctx.Err())
break
case err := <-shutdownChannel:
log.Warnf("detect module shutdown notify: %v", err)
}
wg.Done()
}()
wg.Wait()
return nil
}