main.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package main
  2. import (
  3. "context"
  4. "flag"
  5. "log"
  6. "log/slog"
  7. "net/http"
  8. "os"
  9. "os/signal"
  10. "slices"
  11. "syscall"
  12. "time"
  13. "github.com/ncarlier/webhookd/pkg/api"
  14. "github.com/ncarlier/webhookd/pkg/config"
  15. configflag "github.com/ncarlier/webhookd/pkg/config/flag"
  16. "github.com/ncarlier/webhookd/pkg/logger"
  17. "github.com/ncarlier/webhookd/pkg/notification"
  18. _ "github.com/ncarlier/webhookd/pkg/notification/all"
  19. "github.com/ncarlier/webhookd/pkg/server"
  20. "github.com/ncarlier/webhookd/pkg/version"
  21. "github.com/ncarlier/webhookd/pkg/worker"
  22. )
  23. const envPrefix = "WHD"
  24. func main() {
  25. conf := &config.Config{}
  26. configflag.Bind(conf, envPrefix)
  27. flag.Parse()
  28. if *version.ShowVersion {
  29. version.Print()
  30. os.Exit(0)
  31. }
  32. if conf.Hook.LogDir == "" {
  33. conf.Hook.LogDir = os.TempDir()
  34. }
  35. if err := conf.Validate(); err != nil {
  36. log.Fatal("invalid configuration:", err)
  37. }
  38. logger.Configure(conf.Log.Format, conf.Log.Level)
  39. logger.HookOutputEnabled = slices.Contains(conf.Log.Modules, "hook")
  40. logger.RequestOutputEnabled = slices.Contains(conf.Log.Modules, "http")
  41. conf.ManageDeprecatedFlags(envPrefix)
  42. slog.Debug("starting webhookd server...")
  43. srv := server.NewServer(conf)
  44. // Configure notification
  45. if err := notification.Init(conf.Notification.URI); err != nil {
  46. slog.Error("unable to create notification channel", "err", err)
  47. }
  48. // Start the dispatcher.
  49. slog.Debug("starting the dispatcher...", "workers", conf.Hook.Workers)
  50. worker.StartDispatcher(conf.Hook.Workers)
  51. done := make(chan bool)
  52. quit := make(chan os.Signal, 1)
  53. signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
  54. go func() {
  55. <-quit
  56. slog.Debug("server is shutting down...")
  57. api.Shutdown()
  58. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  59. defer cancel()
  60. if err := srv.Shutdown(ctx); err != nil {
  61. slog.Error("could not gracefully shutdown the server", "err", err)
  62. }
  63. close(done)
  64. }()
  65. api.Start()
  66. slog.Info("server started", "addr", conf.ListenAddr)
  67. if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
  68. slog.Error("unable to start the server", "addr", conf.ListenAddr, "err", err)
  69. os.Exit(1)
  70. }
  71. <-done
  72. slog.Debug("server stopped")
  73. }