Enhance server update process with graceful shutdown; enable TLS in config and clean up temporary files during update

This commit is contained in:
alex
2025-07-06 09:13:37 +03:00
parent 66f3d12412
commit 90c7b1cd70
3 changed files with 76 additions and 54 deletions

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"log/slog" "log/slog"
"net" "net"
"net/http" "net/http"
@@ -31,35 +32,32 @@ func init() {
currentV, currentB, _ := update.NewUpdater(*log, cfg).GetCurrentVersion() currentV, currentB, _ := update.NewUpdater(*log, cfg).GetCurrentVersion()
log.Info("Initializing server", slog.String("address", cfg.HTTPServer.Address), slog.String("version", string(currentV)+"-"+string(currentB))) log.Info("Initializing GoSally server", slog.String("address", cfg.HTTPServer.Address), slog.String("version", string(currentV)+"-"+string(currentB)))
log.Debug("Server running in debug mode") log.Debug("Server running in debug mode")
} }
func UpdateDaemon(u *update.Updater, cfg config.ConfigConf) { func UpdateDaemon(u *update.Updater, cfg config.ConfigConf, srv *http.Server) {
for { //time.Sleep(5 * time.Second)
isNewUpdate, err := u.CkeckUpdates()
if err != nil {
log.Error("Failed to check for updates", slog.String("error", err.Error()))
}
if isNewUpdate {
log.Info("New update available, starting update process...") log.Info("New update available, starting update process...")
err = u.Update()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
log.Info("Trying to down server gracefully before update")
if err := srv.Shutdown(ctx); err != nil {
log.Error("Failed to shutdown server gracefully", slog.String("error", err.Error()))
}
err := u.Update()
if err != nil { if err != nil {
log.Error("Failed to update", slog.String("error", err.Error())) log.Error("Failed to update", slog.String("error", err.Error()))
} else { } else {
log.Info("Update completed successfully") log.Info("Update completed successfully")
} }
} else {
log.Info("No new updates available")
}
time.Sleep(cfg.CheckInterval)
}
} }
func main() { func main() {
updater := update.NewUpdater(*log, cfg)
go UpdateDaemon(updater, *cfg)
serverv1 := sv1.InitV1Server(&sv1.HandlerV1InitStruct{ serverv1 := sv1.InitV1Server(&sv1.HandlerV1InitStruct{
Log: *log, Log: *log,
Config: cfg, Config: cfg,
@@ -90,10 +88,14 @@ func main() {
}) })
}) })
address := cfg.Address srv := &http.Server{
Addr: cfg.Address,
Handler: r,
}
go func() {
if cfg.TlsEnabled { if cfg.TlsEnabled {
log.Info("HTTPS server started with TLS", slog.String("address", address)) log.Info("HTTPS server started with TLS", slog.String("address", cfg.Address))
listener, err := net.Listen("tcp", address) listener, err := net.Listen("tcp", cfg.Address)
if err != nil { if err != nil {
log.Error("Failed to start TLS listener", slog.String("error", err.Error())) log.Error("Failed to start TLS listener", slog.String("error", err.Error()))
return return
@@ -104,8 +106,8 @@ func main() {
log.Error("Failed to start HTTPS server", slog.String("error", err.Error())) log.Error("Failed to start HTTPS server", slog.String("error", err.Error()))
} }
} else { } else {
log.Info("HTTP server started", slog.String("address", address)) log.Info("HTTP server started", slog.String("address", cfg.Address))
listener, err := net.Listen("tcp", address) listener, err := net.Listen("tcp", cfg.Address)
if err != nil { if err != nil {
log.Error("Failed to start listener", slog.String("error", err.Error())) log.Error("Failed to start listener", slog.String("error", err.Error()))
return return
@@ -116,4 +118,25 @@ func main() {
log.Error("Failed to start HTTP server", slog.String("error", err.Error())) log.Error("Failed to start HTTP server", slog.String("error", err.Error()))
} }
} }
}()
time.Sleep(5*time.Second)
updater := update.NewUpdater(*log, cfg)
go func() {
time.Sleep(6*time.Second)
for {
isNewUpdate, err := updater.CkeckUpdates()
if err != nil {
log.Error("Failed to check for updates", slog.String("error", err.Error()))
}
if isNewUpdate {
UpdateDaemon(updater, *cfg, srv)
} else {
log.Info("No new updates available")
}
time.Sleep(cfg.CheckInterval)
}
}()
select {}
} }

View File

@@ -39,7 +39,7 @@ func init() {
output.Close() output.Close()
runArgs := os.Args runArgs := os.Args
runArgs[0] = runBinaryPath runArgs[0] = runBinaryPath
if err := syscall.Exec(runBinaryPath, runArgs, append(os.Environ(), "GS_RUNTIME_PATH=" + runPath)); err != nil { if err := syscall.Exec(runBinaryPath, runArgs, append(os.Environ(), "GS_RUNTIME_PATH="+runPath)); err != nil {
log.Fatalf("Failed to init node: %s", err) log.Fatalf("Failed to init node: %s", err)
} }
} }

View File

@@ -10,6 +10,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp"
"strconv" "strconv"
"strings" "strings"
@@ -203,7 +204,6 @@ func (u *Updater) Update() error {
if err != nil { if err != nil {
return errors.New("failed to create temp dir " + err.Error()) return errors.New("failed to create temp dir " + err.Error())
} }
//defer os.RemoveAll(downloadPath)
_, currentBranch, err := u.GetCurrentVersion() _, currentBranch, err := u.GetCurrentVersion()
if err != nil { if err != nil {
return errors.New("failed to get current version: " + err.Error()) return errors.New("failed to get current version: " + err.Error())
@@ -288,7 +288,6 @@ func (u *Updater) InstallAndRestart(newBinaryPath string) error {
return err return err
} }
if _, err := io.Copy(output, input); err != nil { if _, err := io.Copy(output, input); err != nil {
return err return err
} }
@@ -298,6 +297,10 @@ func (u *Updater) InstallAndRestart(newBinaryPath string) error {
} }
input.Close() input.Close()
toClean := regexp.MustCompile(`^(/tmp/\d+-gs-up/)`).FindStringSubmatch(newBinaryPath)
if len(toClean) > 1 {
os.RemoveAll(toClean[0])
}
output.Close() output.Close()
// Запускаем новый процесс // Запускаем новый процесс
u.Log.Info("Launching new version...", slog.String("path", targetPath)) u.Log.Info("Launching new version...", slog.String("path", targetPath))
@@ -310,10 +313,6 @@ func (u *Updater) InstallAndRestart(newBinaryPath string) error {
if err = cmd.Start(); err != nil { if err = cmd.Start(); err != nil {
return err return err
} }
// if err := syscall.Exec(targetPath, os.Args, os.Environ()); err != nil {
// u.Log.Error("Failed to run new version automatickly", slog.String("err", err.Error()))
// return err
// }
u.Log.Info("Shutting down") u.Log.Info("Shutting down")
os.Exit(0) os.Exit(0)
return errors.New("failed to shutdown the process") return errors.New("failed to shutdown the process")