package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" ) func main() { config := LoadConfig() // 可选初始化 MySQL var db *PromptDB if config.MySQLDSN != "" { var err error db, err = NewPromptDB(config.MySQLDSN) if err != nil { log.Fatalf("failed to init mysql: %v", err) } log.Println("mysql prompt recording enabled") } else { log.Println("mysql not configured, prompt recording disabled") } handler := NewHookHandler(config, db) mux := http.NewServeMux() mux.HandleFunc("/hooks", handler.HandleHook) mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte(`{"status":"ok"}`)) }) srv := &http.Server{ Addr: config.Port, Handler: mux, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 60 * time.Second, } // 优雅关闭 go func() { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) <-sigCh log.Println("shutting down...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Printf("server shutdown error: %v", err) } if db != nil { db.Close() } }() log.Printf("cc-hook service starting on %s", config.Port) log.Printf("gotify endpoint: %s", config.GotifyURL) if err := srv.ListenAndServe(); err != http.ErrServerClosed { log.Fatalf("server failed: %v", err) } log.Println("server stopped") }