package serverimp import ( "context" "strings" "time" "github.com/tech/sendico/pkg/api/routers/health" "github.com/tech/sendico/pkg/mlogger" "go.uber.org/zap" ) const defaultShutdownTimeout = 15 * time.Second func Create(logger mlogger.Logger, file string, debug bool) (*Imp, error) { return &Imp{ logger: logger.Named("server"), file: file, debug: debug, }, nil } func (i *Imp) Start() error { i.initStopChannels() defer i.closeDone() i.logger.Info("Starting discovery service", zap.String("config_file", i.file), zap.Bool("debug", i.debug)) cfg, err := i.loadConfig() if err != nil { return err } i.config = cfg messagingDriver := "none" if cfg.Messaging != nil { messagingDriver = string(cfg.Messaging.Driver) } metricsAddress := "" if cfg.Metrics != nil { metricsAddress = strings.TrimSpace(cfg.Metrics.Address) } if metricsAddress == "" { metricsAddress = "disabled" } i.logger.Info("Discovery config loaded", zap.String("messaging_driver", messagingDriver), zap.String("metrics_address", metricsAddress)) i.startMetrics(cfg.Metrics) err = i.startDiscovery(cfg) if err != nil { i.stopDiscovery() i.setMetricsStatus(health.SSTerminating) ctx, cancel := context.WithTimeout(context.Background(), i.shutdownTimeout()) i.shutdownMetrics(ctx) cancel() return err } i.setMetricsStatus(health.SSRunning) i.logger.Info("Discovery service ready", zap.String("messaging_driver", messagingDriver)) <-i.stopCh i.logger.Info("Discovery service stop signal received") return nil } func (i *Imp) Shutdown() { timeout := i.shutdownTimeout() i.logger.Info("Stopping discovery service", zap.Duration("timeout", timeout)) i.stopDiscovery() i.signalStop() if i.doneCh != nil { <-i.doneCh } ctx, cancel := context.WithTimeout(context.Background(), timeout) i.shutdownMetrics(ctx) cancel() i.logger.Info("Discovery service stopped") } func (i *Imp) initStopChannels() { if i.stopCh == nil { i.stopCh = make(chan struct{}) } if i.doneCh == nil { i.doneCh = make(chan struct{}) } } func (i *Imp) signalStop() { i.stopOnce.Do(func() { if i.stopCh != nil { close(i.stopCh) } }) } func (i *Imp) closeDone() { i.doneOnce.Do(func() { if i.doneCh != nil { close(i.doneCh) } }) } func (i *Imp) shutdownTimeout() time.Duration { if i.config != nil && i.config.Runtime != nil { return i.config.Runtime.ShutdownTimeout() } return defaultShutdownTimeout }