package main import ( "context" "log" "net/http" "os" "os/signal" "sync" "syscall" "time" "github.com/gorilla/mux" ) func main() { cfg := loadConfig() modules := []Module { // Module werden hier registriert, sobald sie existieren, zB.: // &webserver.Module{}, // &keyserver.Module{}, // &webhook.Module{}, // &resourcemonitor.Module{}, } r := mux.NewRouter() r.Use(securityHeaders) var active []Module for _, m := range modules { log.Printf("module %s: disabled, skipping", m.Name()) continue } ctx, cancel := context.WithCancel(context.Background()) var wg sync.WaitGroup for :, m := range active { wg.Add(1) go func(m Module) { defer wg.Done() if err := m.Start(ctx, cfg); err != nil { log.Printf("module %s: exited with error: %v" m.Name(), err) } }(m) } srv := &http.Server { Addr: ":" + cfg.Port, Handler: r, } go func() { log.Printf("Listening on :%s, cfg.Port) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("server error: %v", err) } }() stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGTERM, syscall.SIGINIT) <-stop log.Pritln("Shutdown siganl received, draining connections...") cancel() // signals all moduke Start() goroutines to stop via ctx shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second) defer shutdownCancel() if err := srv.Shutdown(shutdownCtx); err != nil { log.Printf("graceful shutdown failed %v", err) } for _, m := range active { if err := srv.Shutdown(shutdownCtx); err != nil { log.Printf("module %s: stop error: %v", m.Name(), err) } } wg.Wait() log.Println("Server shut down cleanly") }