diff --git a/backend/internal/bootstrap/router_bootstrap.go b/backend/internal/bootstrap/router_bootstrap.go index 35b4dc1b..78397b70 100644 --- a/backend/internal/bootstrap/router_bootstrap.go +++ b/backend/internal/bootstrap/router_bootstrap.go @@ -2,6 +2,7 @@ package bootstrap import ( "log" + "net" "time" "github.com/gin-gonic/gin" @@ -10,6 +11,7 @@ import ( "github.com/pocket-id/pocket-id/backend/internal/job" "github.com/pocket-id/pocket-id/backend/internal/middleware" "github.com/pocket-id/pocket-id/backend/internal/service" + "github.com/pocket-id/pocket-id/backend/internal/utils/systemd" "golang.org/x/time/rate" "gorm.io/gorm" ) @@ -79,8 +81,20 @@ func initRouter(db *gorm.DB, appConfigService *service.AppConfigService) { baseGroup := r.Group("/") controller.NewWellKnownController(baseGroup, jwtService) - // Run the server - if err := r.Run(common.EnvConfig.Host + ":" + common.EnvConfig.Port); err != nil { + // Get the listener + l, err := net.Listen("tcp", common.EnvConfig.Host+":"+common.EnvConfig.Port) + if err != nil { + log.Fatal(err) + } + + // Notify systemd that we are ready + if err := systemd.SdNotifyReady(); err != nil { + log.Println("Unable to notify systemd that the service is ready: ", err) + // continue to serve anyway since it's not that important + } + + // Serve requests + if err := r.RunListener(l); err != nil { log.Fatal(err) } } diff --git a/backend/internal/utils/systemd/sdnotify.go b/backend/internal/utils/systemd/sdnotify.go new file mode 100644 index 00000000..aba034b9 --- /dev/null +++ b/backend/internal/utils/systemd/sdnotify.go @@ -0,0 +1,33 @@ +package systemd + +import ( + "net" + "os" +) + +// SdNotifyReady sends a message to the systemd daemon to notify that service is ready to operate. +// It is common to ignore the error. +func SdNotifyReady() error { + socketAddr := &net.UnixAddr{ + Name: os.Getenv("NOTIFY_SOCKET"), + Net: "unixgram", + } + + if socketAddr.Name == "" { + return nil + } + + conn, err := net.DialUnix(socketAddr.Net, nil, socketAddr) + if err != nil { + return err + } + defer func() { + _ = conn.Close() + }() + + if _, err = conn.Write([]byte("READY=1")); err != nil { + return err + } + + return nil +}