add tacking

This commit is contained in:
Fran Jurmanović
2025-05-24 00:44:26 +02:00
parent 31a2b73cf9
commit edf5a2c8c4
11 changed files with 210 additions and 12 deletions

View File

@@ -4,25 +4,32 @@ import (
"acc-server-manager/local/model"
"acc-server-manager/local/repository"
"acc-server-manager/local/utl/common"
"context"
"errors"
"strings"
"github.com/gofiber/fiber/v2"
)
type ApiService struct {
repository *repository.ApiRepository
serverRepository *repository.ServerRepository
serverService *ServerService
}
func NewApiService(repository *repository.ApiRepository,
serverRepository *repository.ServerRepository) *ApiService {
serverRepository *repository.ServerRepository,) *ApiService {
return &ApiService{
repository: repository,
serverRepository: serverRepository,
}
}
func (as ApiService) SetServerService(serverService *ServerService) {
as.serverService = serverService
}
// GetFirst
// Gets first row from API table.
//
@@ -73,15 +80,28 @@ func (as ApiService) StatusServer(serviceName string) (string, error) {
}
func (as ApiService) StartServer(serviceName string) (string, error) {
return ManageService(serviceName, "start")
status, err := ManageService(serviceName, "start")
server := as.serverRepository.GetFirstByServiceName(context.Background(), serviceName)
as.serverService.StartAccServerRuntime(server)
return status, err
}
func (as ApiService) StopServer(serviceName string) (string, error) {
return ManageService(serviceName, "stop")
status, err := ManageService(serviceName, "stop")
server := as.serverRepository.GetFirstByServiceName(context.Background(), serviceName)
as.serverService.instances.Delete(server.ID)
return status, err
}
func (as ApiService) RestartServer(serviceName string) (string, error) {
return ManageService(serviceName, "restart")
status, err := ManageService(serviceName, "restart")
server := as.serverRepository.GetFirstByServiceName(context.Background(), serviceName)
as.serverService.StartAccServerRuntime(server)
return status, err
}
func ManageService(serviceName string, action string) (string, error) {

View File

@@ -63,6 +63,7 @@ func mustDecode[T any](fileName, path string) (T, error) {
type ConfigService struct {
repository *repository.ConfigRepository
serverRepository *repository.ServerRepository
serverService *ServerService
}
func NewConfigService(repository *repository.ConfigRepository, serverRepository *repository.ServerRepository) *ConfigService {
@@ -72,6 +73,10 @@ func NewConfigService(repository *repository.ConfigRepository, serverRepository
}
}
func (as ConfigService) SetServerService(serverService *ServerService) {
as.serverService = serverService
}
// UpdateConfig
// Updates physical config file and caches it in database.
//
@@ -131,6 +136,8 @@ func (as ConfigService) UpdateConfig(ctx *fiber.Ctx, body *map[string]interface{
return nil, err
}
as.serverService.StartAccServerRuntime(server)
// Log change
return as.repository.UpdateConfig(context, &model.Config{
ServerID: uint(serverID),

View File

@@ -3,7 +3,15 @@ package service
import (
"acc-server-manager/local/model"
"acc-server-manager/local/repository"
"acc-server-manager/local/utl/tracking"
"context"
"log"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
"time"
"github.com/gofiber/fiber/v2"
)
@@ -11,13 +19,90 @@ import (
type ServerService struct {
repository *repository.ServerRepository
apiService *ApiService
instances sync.Map
configService *ConfigService
}
func NewServerService(repository *repository.ServerRepository, apiService *ApiService) *ServerService {
return &ServerService{
func NewServerService(repository *repository.ServerRepository, apiService *ApiService, configService *ConfigService) *ServerService {
service := &ServerService{
repository: repository,
apiService: apiService,
configService: configService,
}
servers := repository.GetAll(context.Background())
for _, server := range *servers {
status, err := service.apiService.StatusServer(server.ServiceName)
if err != nil {
log.Print(err.Error())
}
if (status == string(model.StatusRunning)) {
service.StartAccServerRuntime(&server)
}
}
return service
}
var leaderboardUpdateRegex = regexp.MustCompile(`Updated leaderboard for (\d+) clients`)
var sessionChangeRegex = regexp.MustCompile(`Session changed: (\w+) -> (\w+)`)
func handleLogLine(instance *model.AccServerInstance) func(string) {
return func (line string) {
state := (*instance).State
now := time.Now()
if strings.Contains(line, "client(s) online") {
parts := strings.Fields(line)
if len(parts) >= 2 {
countStr := parts[1]
if count, err := strconv.Atoi(countStr); err == nil {
state.Lock()
state.PlayerCount = count
state.Unlock()
}
}
}
if strings.Contains(line, "Session changed") {
match := sessionChangeRegex.FindStringSubmatch(line)
if len(match) == 3 {
newSession := match[2]
state.Lock()
state.Session = newSession
state.SessionStart = now
state.Unlock()
}
}
if strings.Contains(line, "Updated leaderboard for") {
match := leaderboardUpdateRegex.FindStringSubmatch(line)
if len(match) == 2 {
if count, err := strconv.Atoi(match[1]); err == nil {
state.Lock()
state.PlayerCount = count
state.Unlock()
}
}
}
}
}
func (s *ServerService) StartAccServerRuntime(server *model.Server) {
s.instances.Delete(server.ID)
instance := &model.AccServerInstance{
Model: server,
State: &model.ServerState{PlayerCount: 0},
}
config, _ := DecodeFileName(ConfigurationJson)(server.ConfigPath)
cfg := config.(model.Configuration)
event, _ := DecodeFileName(EventJson)(server.ConfigPath)
evt := event.(model.EventConfig)
instance.State.MaxConnections = cfg.MaxConnections.ToInt()
instance.State.Track = evt.Track
go tracking.TailLogFile(filepath.Join(server.ConfigPath, "\\server\\log\\server.log"), handleLogLine(instance))
s.instances.Store(server.ID, instance)
}
// GetAll
@@ -36,6 +121,15 @@ func (as ServerService) GetAll(ctx *fiber.Ctx) *[]model.Server {
log.Print(err.Error())
}
(*servers)[i].Status = model.ServiceStatus(status)
instance, ok := as.instances.Load(server.ID)
if !ok {
log.Print("Unable to retrieve instance for server of ID: ", server.ID)
} else {
serverInstance := instance.(*model.AccServerInstance)
if (serverInstance.State != nil) {
(*servers)[i].State = *serverInstance.State
}
}
}
return servers
@@ -55,7 +149,15 @@ func (as ServerService) GetById(ctx *fiber.Ctx, serverID int) *model.Server {
log.Print(err.Error())
}
server.Status = model.ServiceStatus(status)
instance, ok := as.instances.Load(server.ID)
if !ok {
log.Print("Unable to retrieve instance for server of ID: ", server.ID)
} else {
serverInstance := instance.(*model.AccServerInstance)
if (serverInstance.State != nil) {
server.State = *serverInstance.State
}
}
return server
}
}

View File

@@ -2,6 +2,7 @@ package service
import (
"acc-server-manager/local/repository"
"log"
"go.uber.org/dig"
)
@@ -18,4 +19,12 @@ func InitializeServices(c *dig.Container) {
c.Provide(NewApiService)
c.Provide(NewConfigService)
c.Provide(NewLookupService)
err := c.Invoke(func(server *ServerService, api *ApiService, config *ConfigService) {
api.SetServerService(server)
config.SetServerService(server)
})
if err != nil {
log.Panic("unable to initialize server service in api service")
}
}