make use of AppX and CoreState in program modules

This commit is contained in:
2025-07-29 17:54:57 +03:00
parent 92c89996f5
commit 74f166e6cf
9 changed files with 74 additions and 83 deletions

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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,
}