mirror of
https://github.com/akyaiy/GoSally-mvp.git
synced 2026-01-03 08:32:24 +00:00
178 lines
5.5 KiB
Go
178 lines
5.5 KiB
Go
package hooks
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"log/slog"
|
|
"net"
|
|
"net/http"
|
|
"regexp"
|
|
"time"
|
|
|
|
"github.com/akyaiy/GoSally-mvp/internal/colors"
|
|
"github.com/akyaiy/GoSally-mvp/internal/core/corestate"
|
|
"github.com/akyaiy/GoSally-mvp/internal/core/run_manager"
|
|
"github.com/akyaiy/GoSally-mvp/internal/core/update"
|
|
"github.com/akyaiy/GoSally-mvp/internal/core/utils"
|
|
"github.com/akyaiy/GoSally-mvp/internal/engine/app"
|
|
"github.com/akyaiy/GoSally-mvp/internal/engine/config"
|
|
"github.com/akyaiy/GoSally-mvp/internal/engine/logs"
|
|
"github.com/akyaiy/GoSally-mvp/internal/server/gateway"
|
|
"github.com/akyaiy/GoSally-mvp/internal/server/session"
|
|
"github.com/akyaiy/GoSally-mvp/internal/server/sv1"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/cors"
|
|
"github.com/spf13/cobra"
|
|
"golang.org/x/net/netutil"
|
|
)
|
|
|
|
var NodeApp = app.New()
|
|
var AllowedCmdPattern = `^[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*$`
|
|
|
|
func Run(cmd *cobra.Command, args []string) {
|
|
NodeApp.InitialHooks(
|
|
InitGlobalLoggerHook, InitCorestateHook, InitConfigLoadHook,
|
|
InitUUIDHook, InitRuntimeHook, InitRunlockHook,
|
|
InitConfigReplHook, InitConfigPrintHook, InitSLogHook,
|
|
)
|
|
|
|
NodeApp.Run(RunHook)
|
|
}
|
|
|
|
func RunHook(ctx context.Context, cs *corestate.CoreState, x *app.AppX) error {
|
|
ctxMain, cancelMain := context.WithCancel(ctx)
|
|
runLockFile := run_manager.File("run.lock")
|
|
_, err := runLockFile.Open()
|
|
if err != nil {
|
|
x.Log.Fatalf("cannot open run.lock: %s", err)
|
|
}
|
|
|
|
_, err = runLockFile.Watch(ctxMain, func() {
|
|
x.Log.Printf("run.lock was touched")
|
|
_ = run_manager.Clean()
|
|
cancelMain()
|
|
})
|
|
if err != nil {
|
|
x.Log.Printf("watch error: %s", err)
|
|
}
|
|
|
|
serverv1 := sv1.InitV1Server(&sv1.HandlerV1InitStruct{
|
|
X: x,
|
|
CS: cs,
|
|
AllowedCmd: regexp.MustCompile(AllowedCmdPattern),
|
|
Ver: "v1",
|
|
})
|
|
|
|
session_manager := session.New(*x.Config.Conf.HTTPServer.SessionTTL)
|
|
|
|
s := gateway.InitGateway(&gateway.GatewayServerInit{
|
|
SM: session_manager,
|
|
CS: cs,
|
|
X: x,
|
|
}, serverv1)
|
|
|
|
r := chi.NewRouter()
|
|
r.Use(cors.Handler(cors.Options{
|
|
AllowedOrigins: []string{"*"},
|
|
AllowedMethods: []string{"POST"},
|
|
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token", "X-Session-UUID"},
|
|
AllowCredentials: true,
|
|
MaxAge: 300,
|
|
}))
|
|
r.HandleFunc(config.ComDirRoute, s.Handle)
|
|
r.Route("/favicon.ico", func(r chi.Router) {
|
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNoContent)
|
|
})
|
|
})
|
|
|
|
srv := &http.Server{
|
|
Addr: *x.Config.Conf.HTTPServer.Address,
|
|
Handler: r,
|
|
ErrorLog: log.New(&logs.SlogWriter{
|
|
Logger: x.SLog,
|
|
Level: slog.LevelError,
|
|
}, "", 0),
|
|
}
|
|
|
|
NodeApp.Fallback(func(ctx context.Context, cs *corestate.CoreState, x *app.AppX) {
|
|
if err := srv.Shutdown(ctxMain); err != nil {
|
|
x.Log.Printf("%s: Failed to stop the server gracefully: %s", colors.PrintError(), err.Error())
|
|
} else {
|
|
x.Log.Printf("Server stopped gracefully")
|
|
}
|
|
|
|
x.Log.Println("Cleaning up...")
|
|
|
|
if err := run_manager.Clean(); err != nil {
|
|
x.Log.Printf("%s: Cleanup error: %s", colors.PrintError(), err.Error())
|
|
}
|
|
x.Log.Println("bye!")
|
|
})
|
|
|
|
go func() {
|
|
defer utils.CatchPanicWithCancel(cancelMain)
|
|
if *x.Config.Conf.TLS.TlsEnabled {
|
|
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port))
|
|
if err != nil {
|
|
x.Log.Printf("%s: Failed to start TLS listener: %s", colors.PrintError(), err.Error())
|
|
cancelMain()
|
|
return
|
|
}
|
|
x.Log.Printf("Serving on %s port %s with TLS... (https://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute)
|
|
limitedListener := netutil.LimitListener(listener, 100)
|
|
if err := srv.ServeTLS(limitedListener, *x.Config.Conf.TLS.CertFile, *x.Config.Conf.TLS.KeyFile); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
x.Log.Printf("%s: Failed to start HTTPS server: %s", colors.PrintError(), err.Error())
|
|
cancelMain()
|
|
}
|
|
} else {
|
|
x.Log.Printf("Serving on %s port %s... (http://%s%s)", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port, fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port), config.ComDirRoute)
|
|
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%s", *x.Config.Conf.HTTPServer.Address, *x.Config.Conf.HTTPServer.Port))
|
|
if err != nil {
|
|
x.Log.Printf("%s: Failed to start listener: %s", colors.PrintError(), err.Error())
|
|
cancelMain()
|
|
return
|
|
}
|
|
limitedListener := netutil.LimitListener(listener, 100)
|
|
if err := srv.Serve(limitedListener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
x.Log.Printf("%s: Failed to start HTTP server: %s", colors.PrintError(), err.Error())
|
|
cancelMain()
|
|
}
|
|
}
|
|
}()
|
|
|
|
session_manager.StartCleanup(5 * time.Second)
|
|
|
|
if *x.Config.Conf.Updates.UpdatesEnabled {
|
|
go func() {
|
|
defer utils.CatchPanicWithCancel(cancelMain)
|
|
updated := update.NewUpdater(&update.UpdaterInit{
|
|
X: x,
|
|
Ctx: ctxMain,
|
|
Cancel: cancelMain,
|
|
})
|
|
updated.Shutdownfunc(cancelMain)
|
|
for {
|
|
isNewUpdate, err := updated.CkeckUpdates()
|
|
if err != nil {
|
|
x.Log.Printf("Failed to check for updates: %s", err.Error())
|
|
}
|
|
if isNewUpdate {
|
|
if err := updated.Update(); err != nil {
|
|
x.Log.Printf("Failed to update: %s", err.Error())
|
|
} else {
|
|
x.Log.Printf("Update completed successfully")
|
|
}
|
|
}
|
|
time.Sleep(*x.Config.Conf.Updates.CheckInterval)
|
|
}
|
|
}()
|
|
}
|
|
|
|
<-ctxMain.Done()
|
|
NodeApp.CallFallback(ctx)
|
|
return nil
|
|
}
|