Three related issues fixed together:
1. Readiness context was never cancelled during shutdown
server.Run() had a type assertion for a Cancel() method that no standard
context.Context implements, so readiness stayed "ready" through the entire
shutdown window. Added CancelableContext to pkg/server — a thin wrapper that
exposes Cancel() — and switched cmd/server/main.go to use it. Test servers
and CLI continue passing context.Background() unchanged.
2. "Server exited" log was never emitted
The test script expected it; main.go had no log after server.Run() returned.
Added log.Trace().Msg("Server exited") after the Run() call.
3. Double-SIGTERM caused non-JSON "signal: terminated" in server.log
test-graceful-shutdown.sh sent SIGTERM, then called $SERVER_CMD stop which
sent a second SIGTERM. After signal.NotifyContext is cancelled, the second
signal hits the default handler and Go prints "signal: terminated" to stderr,
breaking the all-JSON-lines assertion. Fixed by waiting for the PID to exit
ourselves instead of re-invoking the stop script.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
// Package main provides the dance-lessons-coach server entry point
|
|
//
|
|
// @title dance-lessons-coach API
|
|
// @version 1.4.0
|
|
// @description API for dance-lessons-coach service providing greeting functionality
|
|
// @termsOfService http://swagger.io/terms/
|
|
|
|
// @contact.name API Support
|
|
// @contact.url http://www.arcodange.fr/support
|
|
// @contact.email support@arcodange.fr
|
|
|
|
// @license.name MIT
|
|
// @license.url https://opensource.org/licenses/MIT
|
|
|
|
// @host localhost:8080
|
|
// @BasePath /api
|
|
// @schemes http https
|
|
//
|
|
// @securityDefinitions.apikey BearerAuth
|
|
// @in header
|
|
// @name Authorization
|
|
// @description JWT authentication using Bearer token. Format: Bearer <token>
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"dance-lessons-coach/pkg/config"
|
|
"dance-lessons-coach/pkg/server"
|
|
"dance-lessons-coach/pkg/version"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
func main() {
|
|
// Check for version flag first (before config loading)
|
|
if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-version") {
|
|
fmt.Println(version.Full())
|
|
os.Exit(0)
|
|
}
|
|
|
|
// Load configuration (this will also setup logging)
|
|
cfg, err := config.LoadConfig()
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Failed to load configuration")
|
|
}
|
|
|
|
// Create readiness context to control readiness state.
|
|
// CancelableContext exposes Cancel() so that Server.Run() can cancel
|
|
// readiness at the start of graceful shutdown (before the propagation sleep).
|
|
readyCtx, readyCancel := server.NewCancelableContext(context.Background())
|
|
defer readyCancel()
|
|
|
|
// Create and run server
|
|
server := server.NewServer(cfg, readyCtx)
|
|
if err := server.Run(); err != nil {
|
|
log.Fatal().Err(err).Msg("Server failed")
|
|
}
|
|
log.Trace().Msg("Server exited")
|
|
}
|