From 74f166e6cf12a8abb67bf768fde5c3161eb8b02d Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 29 Jul 2025 17:54:57 +0300 Subject: [PATCH] make use of AppX and CoreState in program modules --- cmd/run.go | 20 ++++---- internal/core/update/update.go | 61 ++++++++++-------------- internal/engine/app/app.go | 8 ++-- internal/server/gateway/general_types.go | 8 ++-- internal/server/gateway/init.go | 12 ++--- internal/server/gateway/route.go | 10 ++-- internal/server/sv1/handle.go | 14 ++++-- internal/server/sv1/path.go | 2 +- internal/server/sv1/server.go | 22 ++++----- 9 files changed, 74 insertions(+), 83 deletions(-) diff --git a/cmd/run.go b/cmd/run.go index 623348f..1fd4d57 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -229,15 +229,15 @@ var runCmd = &cobra.Command{ } serverv1 := sv1.InitV1Server(&sv1.HandlerV1InitStruct{ - Log: *x.SLog, - Config: x.Config.Conf, + X: x, + CS: cs, AllowedCmd: regexp.MustCompile(`^[a-zA-Z0-9]+(>[a-zA-Z0-9]+)*$`), Ver: "v1", }) s := gateway.InitGateway(&gateway.GatewayServerInit{ - Log: x.SLog, - Config: x.Config.Conf, + CS: cs, + X: x, }, serverv1) r := chi.NewRouter() @@ -313,15 +313,19 @@ var runCmd = &cobra.Command{ if x.Config.Conf.Updates.UpdatesEnabled { go func() { defer utils.CatchPanicWithCancel(cancelMain) - x.Updated = update.NewUpdater(ctxMain, x.Log, x.Config.Conf, x.Config.Env) - x.Updated.Shutdownfunc(cancelMain) + updated := update.NewUpdater(&update.UpdaterInit{ + X: x, + Ctx: ctxMain, + Cancel: cancelMain, + }) + updated.Shutdownfunc(cancelMain) for { - isNewUpdate, err := x.Updated.CkeckUpdates() + isNewUpdate, err := updated.CkeckUpdates() if err != nil { x.Log.Printf("Failed to check for updates: %s", err.Error()) } if isNewUpdate { - if err := x.Updated.Update(); err != nil { + if err := updated.Update(); err != nil { x.Log.Printf("Failed to update: %s", err.Error()) } else { x.Log.Printf("Update completed successfully") diff --git a/internal/core/update/update.go b/internal/core/update/update.go index 15a1adb..aafbae4 100644 --- a/internal/core/update/update.go +++ b/internal/core/update/update.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "log" "net/http" "os" "path/filepath" @@ -16,6 +15,7 @@ import ( "github.com/akyaiy/GoSally-mvp/internal/core/run_manager" "github.com/akyaiy/GoSally-mvp/internal/core/utils" + "github.com/akyaiy/GoSally-mvp/internal/engine/app" "github.com/akyaiy/GoSally-mvp/internal/engine/config" "golang.org/x/net/context" ) @@ -38,20 +38,23 @@ type UpdaterContract interface { } type Updater struct { - log *log.Logger - config *config.Conf - env *config.Env + x *app.AppX ctx context.Context cancel context.CancelFunc } -func NewUpdater(ctx context.Context, log *log.Logger, cfg *config.Conf, env *config.Env) *Updater { +type UpdaterInit struct { + X *app.AppX + Ctx context.Context + Cancel context.CancelFunc +} + +func NewUpdater(o *UpdaterInit) *Updater { return &Updater{ - log: log, - config: cfg, - env: env, - ctx: ctx, + x: o.X, + ctx: o.Ctx, + cancel: o.Cancel, } } @@ -119,7 +122,7 @@ func isVersionNewer(current, latest Version) bool { func (u *Updater) GetCurrentVersion() (Version, Branch, error) { version, branch, err := splitVersionString(string(config.NodeVersion)) if err != nil { - u.log.Printf("Failed to parse version string: %s", err.Error()) + u.x.Log.Printf("Failed to parse version string: %s", err.Error()) return "", "", err } switch branch { @@ -131,28 +134,28 @@ func (u *Updater) GetCurrentVersion() (Version, Branch, error) { } func (u *Updater) GetLatestVersion(updateBranch Branch) (Version, Branch, error) { - repoURL := u.config.Updates.RepositoryURL + repoURL := u.x.Config.Conf.Updates.RepositoryURL if repoURL == "" { - u.log.Printf("Failed to get latest version: %s", "RepositoryURL is empty in config") + u.x.Log.Printf("Failed to get latest version: %s", "RepositoryURL is empty in config") return "", "", errors.New("repository URL is empty") } if !strings.HasPrefix(repoURL, "http://") && !strings.HasPrefix(repoURL, "https://") { - u.log.Printf("Failed to get latest version: %s: %s", "RepositoryURL does not start with http:// or https:/", repoURL) + u.x.Log.Printf("Failed to get latest version: %s: %s", "RepositoryURL does not start with http:// or https:/", repoURL) return "", "", errors.New("repository URL must start with http:// or https://") } response, err := http.Get(repoURL + "/" + config.ActualFileName) if err != nil { - u.log.Printf("Failed to fetch latest version: %s", err.Error()) + u.x.Log.Printf("Failed to fetch latest version: %s", err.Error()) return "", "", err } defer response.Body.Close() if response.StatusCode != http.StatusOK { - u.log.Printf("Failed to fetch latest version: HTTP status %d", response.StatusCode) + u.x.Log.Printf("Failed to fetch latest version: HTTP status %d", response.StatusCode) return "", "", errors.New("failed to fetch latest version, status code: " + http.StatusText(response.StatusCode)) } data, err := io.ReadAll(response.Body) if err != nil { - u.log.Printf("Failed to read latest version response: %s", err.Error()) + u.x.Log.Printf("Failed to read latest version response: %s", err.Error()) return "", "", err } lines := strings.Split(string(data), "\n") @@ -163,7 +166,7 @@ func (u *Updater) GetLatestVersion(updateBranch Branch) (Version, Branch, error) } version, branch, err := splitVersionString(string(line)) if err != nil { - u.log.Printf("Failed to parse version string: %s", err.Error()) + u.x.Log.Printf("Failed to parse version string: %s", err.Error()) return "", "", err } if branch == updateBranch { @@ -189,7 +192,7 @@ func (u *Updater) CkeckUpdates() (IsNewUpdate, error) { } func (u *Updater) Update() error { - if !u.config.Updates.UpdatesEnabled { + if !u.x.Config.Conf.Updates.UpdatesEnabled { return errors.New("updates are disabled in config, skipping update") } @@ -209,7 +212,7 @@ func (u *Updater) Update() error { } updateArchiveName := fmt.Sprintf("%s.v%s-%s", config.UpdateArchiveName, latestVersion, latestBranch) - updateDest := fmt.Sprintf("%s/%s.%s", u.config.Updates.RepositoryURL, updateArchiveName, "tar.gz") + updateDest := fmt.Sprintf("%s/%s.%s", u.x.Config.Conf.Updates.RepositoryURL, updateArchiveName, "tar.gz") resp, err := http.Get(updateDest) if err != nil { @@ -275,7 +278,7 @@ func (u *Updater) Update() error { func (u *Updater) InstallAndRestart() error { - nodePath := u.env.NodePath + nodePath := u.x.Config.Env.NodePath if nodePath == "" { return errors.New("GS_NODE_PATH environment variable is not set") } @@ -303,12 +306,7 @@ func (u *Updater) InstallAndRestart() error { return fmt.Errorf("failed to chmod: %w", err) } - u.log.Printf("Launching new version: path is %s", targetPath) - // cmd := exec.Command(targetPath, os.Args[1:]...) - // cmd.Env = os.Environ() - // cmd.Stdout = os.Stdout - // cmd.Stderr = os.Stderr - // cmd.Stdin = os.Stdin + u.x.Log.Printf("Launching new version: path is %s", targetPath) args := os.Args args[0] = targetPath env := utils.SetEviron(os.Environ(), "GS_PARENT_PID=-1") @@ -317,17 +315,6 @@ func (u *Updater) InstallAndRestart() error { return err } return syscall.Exec(targetPath, args, env) - //u.cancel() - - // TODO: fix this crap and find a better way to update without errors - // for { - // _, err := run_manager.Get("run.lock") - // if err != nil { - // break - // } - // } - - // return cmd.Start() } func (u *Updater) Shutdownfunc(f context.CancelFunc) { diff --git a/internal/engine/app/app.go b/internal/engine/app/app.go index 9c43a0f..8a864a3 100644 --- a/internal/engine/app/app.go +++ b/internal/engine/app/app.go @@ -10,7 +10,6 @@ import ( "syscall" "github.com/akyaiy/GoSally-mvp/internal/core/corestate" - "github.com/akyaiy/GoSally-mvp/internal/core/update" "github.com/akyaiy/GoSally-mvp/internal/engine/config" ) @@ -34,10 +33,9 @@ type App struct { } type AppX struct { - Config *config.Compositor - Log *log.Logger - SLog *slog.Logger - Updated *update.Updater + Config *config.Compositor + Log *log.Logger + SLog *slog.Logger } func New() AppContract { diff --git a/internal/server/gateway/general_types.go b/internal/server/gateway/general_types.go index 8405bdf..9472e60 100644 --- a/internal/server/gateway/general_types.go +++ b/internal/server/gateway/general_types.go @@ -1,10 +1,10 @@ package gateway import ( - "log/slog" "net/http" - "github.com/akyaiy/GoSally-mvp/internal/engine/config" + "github.com/akyaiy/GoSally-mvp/internal/core/corestate" + "github.com/akyaiy/GoSally-mvp/internal/engine/app" "github.com/akyaiy/GoSally-mvp/internal/server/rpc" ) @@ -22,6 +22,6 @@ type GatewayServer struct { // The key is the version string, and the value is the server implementing GeneralServerApi servers map[serversApiVer]ServerApiContract - log *slog.Logger - cfg *config.Conf + cs *corestate.CoreState + x *app.AppX } diff --git a/internal/server/gateway/init.go b/internal/server/gateway/init.go index 2f92858..e28713e 100644 --- a/internal/server/gateway/init.go +++ b/internal/server/gateway/init.go @@ -2,23 +2,23 @@ package gateway import ( "errors" - "log/slog" - "github.com/akyaiy/GoSally-mvp/internal/engine/config" + "github.com/akyaiy/GoSally-mvp/internal/core/corestate" + "github.com/akyaiy/GoSally-mvp/internal/engine/app" ) // GeneralServerInit structure only for initialization general server. type GatewayServerInit struct { - Log *slog.Logger - Config *config.Conf + CS *corestate.CoreState + X *app.AppX } // InitGeneral initializes a new GeneralServer with the provided configuration and registered servers. func InitGateway(o *GatewayServerInit, servers ...ServerApiContract) *GatewayServer { general := &GatewayServer{ servers: make(map[serversApiVer]ServerApiContract), - cfg: o.Config, - log: o.Log, + cs: o.CS, + x: o.X, } // register the provided servers diff --git a/internal/server/gateway/route.go b/internal/server/gateway/route.go index b27007e..68739d3 100644 --- a/internal/server/gateway/route.go +++ b/internal/server/gateway/route.go @@ -24,7 +24,7 @@ func (gs *GatewayServer) Handle(w http.ResponseWriter, r *http.Request) { "message": rpc.ErrInternalErrorS, }, }) - gs.log.Info("invalid request received", slog.String("issue", rpc.ErrInternalErrorS)) + gs.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrInternalErrorS)) return } @@ -43,7 +43,7 @@ func (gs *GatewayServer) Handle(w http.ResponseWriter, r *http.Request) { "message": rpc.ErrParseErrorS, }, }) - gs.log.Info("invalid request received", slog.String("issue", rpc.ErrParseErrorS)) + gs.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrParseErrorS)) return } resp := gs.Route(r, &single) @@ -78,17 +78,17 @@ func (gs *GatewayServer) Handle(w http.ResponseWriter, r *http.Request) { func (gs *GatewayServer) Route(r *http.Request, req *rpc.RPCRequest) (resp *rpc.RPCResponse) { defer utils.CatchPanicWithFallback(func(rec any) { - gs.log.Error("panic caught in handler", slog.Any("error", rec)) + gs.x.SLog.Error("panic caught in handler", slog.Any("error", rec)) resp = rpc.NewError(rpc.ErrInternalError, "Internal server error (panic)", req.ID) }) if req.JSONRPC != rpc.JSONRPCVersion { - gs.log.Info("invalid request received", slog.String("issue", rpc.ErrInvalidRequestS), slog.String("requested-version", req.JSONRPC)) + gs.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrInvalidRequestS), slog.String("requested-version", req.JSONRPC)) return rpc.NewError(rpc.ErrInvalidRequest, rpc.ErrInvalidRequestS, req.ID) } server, ok := gs.servers[serversApiVer(req.ContextVersion)] if !ok { - gs.log.Info("invalid request received", slog.String("issue", rpc.ErrContextVersionS), slog.String("requested-version", req.ContextVersion)) + gs.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrContextVersionS), slog.String("requested-version", req.ContextVersion)) return rpc.NewError(rpc.ErrContextVersion, rpc.ErrContextVersionS, req.ID) } diff --git a/internal/server/sv1/handle.go b/internal/server/sv1/handle.go index 1540e36..fa004aa 100644 --- a/internal/server/sv1/handle.go +++ b/internal/server/sv1/handle.go @@ -5,6 +5,7 @@ import ( "net/http" "os" "path/filepath" + "strconv" "github.com/akyaiy/GoSally-mvp/internal/core/utils" "github.com/akyaiy/GoSally-mvp/internal/server/rpc" @@ -13,17 +14,17 @@ import ( func (h *HandlerV1) Handle(r *http.Request, req *rpc.RPCRequest) *rpc.RPCResponse { if req.Method == "" { - h.log.Info("invalid request received", slog.String("issue", rpc.ErrMethodNotFoundS), slog.String("requested-method", req.Method)) + h.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrMethodNotFoundS), slog.String("requested-method", req.Method)) return rpc.NewError(rpc.ErrMethodIsMissing, rpc.ErrMethodIsMissingS, req.ID) } method, err := h.resolveMethodPath(req.Method) if err != nil { if err.Error() == rpc.ErrInvalidMethodFormatS { - h.log.Info("invalid request received", slog.String("issue", rpc.ErrInvalidMethodFormatS), slog.String("requested-method", req.Method)) + h.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrInvalidMethodFormatS), slog.String("requested-method", req.Method)) return rpc.NewError(rpc.ErrInvalidMethodFormat, rpc.ErrInvalidMethodFormatS, req.ID) } else if err.Error() == rpc.ErrMethodNotFoundS { - h.log.Info("invalid request received", slog.String("issue", rpc.ErrMethodNotFoundS), slog.String("requested-method", req.Method)) + h.x.SLog.Info("invalid request received", slog.String("issue", rpc.ErrMethodNotFoundS), slog.String("requested-method", req.Method)) return rpc.NewError(rpc.ErrMethodNotFound, rpc.ErrMethodNotFoundS, req.ID) } } @@ -37,7 +38,7 @@ func (h *HandlerV1) HandleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse inTable := L.NewTable() paramsTable := L.NewTable() - if fetchedParams, ok := req.Params.(map[string]interface{}); ok { + if fetchedParams, ok := req.Params.(map[string]any); ok { for k, v := range fetchedParams { L.SetField(paramsTable, k, utils.ConvertGolangTypesToLua(L, v)) } @@ -50,7 +51,7 @@ func (h *HandlerV1) HandleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse L.SetField(outTable, "Result", resultTable) L.SetGlobal("Out", outTable) - prep := filepath.Join(h.cfg.ComDir, "_prepare.lua") + prep := filepath.Join(h.x.Config.Conf.ComDir, "_prepare.lua") if _, err := os.Stat(prep); err == nil { if err := L.DoFile(prep); err != nil { return rpc.NewError(rpc.ErrInternalError, err.Error(), req.ID) @@ -77,6 +78,7 @@ func (h *HandlerV1) HandleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse if msg := errTbl.RawGetString("message"); msg.Type() == lua.LTString { message = msg.String() } + h.x.SLog.Error("the script terminated with an error", slog.String("code", strconv.Itoa(code)), slog.String("message", message)) return rpc.NewError(code, message, req.ID) } return rpc.NewError(rpc.ErrInternalError, "Out.Error is not a table", req.ID) @@ -93,5 +95,7 @@ func (h *HandlerV1) HandleLUA(path string, req *rpc.RPCRequest) *rpc.RPCResponse resultTbl.ForEach(func(key lua.LValue, value lua.LValue) { out[key.String()] = utils.ConvertLuaTypesToGolang(value) }) + + out["responsible-node"] = h.cs.UUID32 return rpc.NewResponse(out, req.ID) } diff --git a/internal/server/sv1/path.go b/internal/server/sv1/path.go index e4dc4b8..73b5d12 100644 --- a/internal/server/sv1/path.go +++ b/internal/server/sv1/path.go @@ -16,7 +16,7 @@ func (h *HandlerV1) resolveMethodPath(method string) (string, error) { parts := strings.Split(method, ">") relPath := filepath.Join(parts...) + ".lua" - fullPath := filepath.Join(h.cfg.ComDir, relPath) + fullPath := filepath.Join(h.x.Config.Conf.ComDir, relPath) if _, err := os.Stat(fullPath); os.IsNotExist(err) { return "", errors.New(rpc.ErrMethodNotFoundS) diff --git a/internal/server/sv1/server.go b/internal/server/sv1/server.go index 76d053b..e533b4e 100644 --- a/internal/server/sv1/server.go +++ b/internal/server/sv1/server.go @@ -3,26 +3,24 @@ package sv1 import ( - "log/slog" "regexp" - "github.com/akyaiy/GoSally-mvp/internal/engine/config" + "github.com/akyaiy/GoSally-mvp/internal/core/corestate" + "github.com/akyaiy/GoSally-mvp/internal/engine/app" ) // HandlerV1InitStruct structure is only for initialization type HandlerV1InitStruct struct { - Ver string - Log slog.Logger - Config *config.Conf - AllowedCmd *regexp.Regexp - ListAllowedCmd *regexp.Regexp + Ver string + CS *corestate.CoreState + X *app.AppX + AllowedCmd *regexp.Regexp } // HandlerV1 implements the ServerV1UtilsContract and serves as the main handler for API requests. type HandlerV1 struct { - log *slog.Logger - - cfg *config.Conf + cs *corestate.CoreState + x *app.AppX // allowedCmd and listAllowedCmd are regular expressions used to validate command names. allowedCmd *regexp.Regexp @@ -35,8 +33,8 @@ type HandlerV1 struct { // because there is no validation of parameters in this function. func InitV1Server(o *HandlerV1InitStruct) *HandlerV1 { return &HandlerV1{ - log: &o.Log, - cfg: o.Config, + cs: o.CS, + x: o.X, allowedCmd: o.AllowedCmd, ver: o.Ver, }