Apply review fixes: validation, idempotency, SOA dedup, startup cleanup
- Migration v2: INSERT → INSERT OR IGNORE for idempotency - Config: validate server.tls_cert and server.tls_key are non-empty - gRPC: add input validation matching REST handlers - gRPC: add logger to zone/record services, log timestamp parse errors - REST+gRPC: extract SOA defaults into shared db.ApplySOADefaults() - DNS: simplify SOA query condition (remove dead code from precedence bug) - Startup: consolidate shutdown into shutdownAll(), clean up gRPC listener on error path, shut down sibling servers when one fails Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,26 @@ func runServer(configPath string) error {
|
||||
}
|
||||
}
|
||||
|
||||
// shutdownAll tears down all servers. Safe to call even if some
|
||||
// servers were never started. grpcSrv.Serve takes ownership of
|
||||
// grpcLis, so we only close grpcLis if we never reached Serve.
|
||||
grpcServeStarted := false
|
||||
shutdownAll := func() {
|
||||
dnsServer.Shutdown()
|
||||
if grpcSrv != nil {
|
||||
grpcSrv.GracefulStop()
|
||||
} else if grpcLis != nil && !grpcServeStarted {
|
||||
_ = grpcLis.Close()
|
||||
}
|
||||
shutdownTimeout := 30 * time.Second
|
||||
if cfg.Server.ShutdownTimeout.Duration > 0 {
|
||||
shutdownTimeout = cfg.Server.ShutdownTimeout.Duration
|
||||
}
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
|
||||
defer cancel()
|
||||
_ = httpServer.Shutdown(shutdownCtx)
|
||||
}
|
||||
|
||||
// Graceful shutdown on SIGINT/SIGTERM.
|
||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
defer stop()
|
||||
@@ -151,6 +171,7 @@ func runServer(configPath string) error {
|
||||
|
||||
// Start gRPC server.
|
||||
if grpcSrv != nil {
|
||||
grpcServeStarted = true
|
||||
go func() {
|
||||
logger.Info("gRPC server listening", "addr", grpcLis.Addr())
|
||||
errCh <- grpcSrv.Serve(grpcLis)
|
||||
@@ -169,22 +190,11 @@ func runServer(configPath string) error {
|
||||
|
||||
select {
|
||||
case err := <-errCh:
|
||||
shutdownAll()
|
||||
return fmt.Errorf("server error: %w", err)
|
||||
case <-ctx.Done():
|
||||
logger.Info("shutting down")
|
||||
dnsServer.Shutdown()
|
||||
if grpcSrv != nil {
|
||||
grpcSrv.GracefulStop()
|
||||
}
|
||||
shutdownTimeout := 30 * time.Second
|
||||
if cfg.Server.ShutdownTimeout.Duration > 0 {
|
||||
shutdownTimeout = cfg.Server.ShutdownTimeout.Duration
|
||||
}
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
|
||||
defer cancel()
|
||||
if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
||||
return fmt.Errorf("shutdown: %w", err)
|
||||
}
|
||||
shutdownAll()
|
||||
logger.Info("mcns stopped")
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user