From 12e259270d5fbe7b118ed5c9b41bc8ed0bd3bba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Tue, 1 Jul 2025 21:41:48 +0200 Subject: [PATCH] more caching and auth middleware --- local/controller/api.go | 15 +++++++++------ local/controller/config.go | 11 +++++++---- local/model/cache.go | 23 ++++++++++++++++------- local/service/api.go | 19 +++++++++++++++++++ local/service/server.go | 12 ++++++++++-- 5 files changed, 61 insertions(+), 19 deletions(-) diff --git a/local/controller/api.go b/local/controller/api.go index 7fba8c5..b412fbe 100644 --- a/local/controller/api.go +++ b/local/controller/api.go @@ -1,6 +1,7 @@ package controller import ( + "acc-server-manager/local/middleware" "acc-server-manager/local/service" "acc-server-manager/local/utl/common" "acc-server-manager/local/utl/error_handler" @@ -22,17 +23,19 @@ type ApiController struct { // *Fiber.RouterGroup: Fiber Router Group // Returns: // *ApiController: Controller for "api" interactions -func NewApiController(as *service.ApiService, routeGroups *common.RouteGroups) *ApiController { +func NewApiController(as *service.ApiService, routeGroups *common.RouteGroups, auth *middleware.AuthMiddleware) *ApiController { ac := &ApiController{ service: as, errorHandler: error_handler.NewControllerErrorHandler(), } - routeGroups.Api.Get("/", ac.getFirst) - routeGroups.Api.Get("/:service", ac.getStatus) - routeGroups.Api.Post("/start", ac.startServer) - routeGroups.Api.Post("/stop", ac.stopServer) - routeGroups.Api.Post("/restart", ac.restartServer) + apiGroup := routeGroups.Api + apiGroup.Use(auth.Authenticate) + apiGroup.Get("/", ac.getFirst) + apiGroup.Get("/:service", ac.getStatus) + apiGroup.Post("/start", ac.startServer) + apiGroup.Post("/stop", ac.stopServer) + apiGroup.Post("/restart", ac.restartServer) return ac } diff --git a/local/controller/config.go b/local/controller/config.go index 98b1953..b0f20d3 100644 --- a/local/controller/config.go +++ b/local/controller/config.go @@ -1,6 +1,7 @@ package controller import ( + "acc-server-manager/local/middleware" "acc-server-manager/local/service" "acc-server-manager/local/utl/common" "acc-server-manager/local/utl/error_handler" @@ -24,16 +25,18 @@ type ConfigController struct { // *Fiber.RouterGroup: Fiber Router Group // Returns: // *ConfigController: Controller for "Config" interactions -func NewConfigController(as *service.ConfigService, routeGroups *common.RouteGroups, as2 *service.ApiService) *ConfigController { +func NewConfigController(as *service.ConfigService, routeGroups *common.RouteGroups, as2 *service.ApiService, auth *middleware.AuthMiddleware) *ConfigController { ac := &ConfigController{ service: as, apiService: as2, errorHandler: error_handler.NewControllerErrorHandler(), } - routeGroups.Config.Put("/:file", ac.UpdateConfig) - routeGroups.Config.Get("/:file", ac.GetConfig) - routeGroups.Config.Get("/", ac.GetConfigs) + configGroup := routeGroups.Config + configGroup.Use(auth.Authenticate) + configGroup.Put("/:file", ac.UpdateConfig) + configGroup.Get("/:file", ac.GetConfig) + configGroup.Get("/", ac.GetConfigs) return ac } diff --git a/local/model/cache.go b/local/model/cache.go index 035c3fd..5b1a1eb 100644 --- a/local/model/cache.go +++ b/local/model/cache.go @@ -14,9 +14,9 @@ type StatusCache struct { // CacheConfig holds configuration for cache behavior type CacheConfig struct { - ExpirationTime time.Duration // How long before a cache entry expires - ThrottleTime time.Duration // Minimum time between status checks - DefaultStatus ServiceStatus // Default status to return when throttled + ExpirationTime time.Duration // How long before a cache entry expires + ThrottleTime time.Duration // Minimum time between status checks + DefaultStatus ServiceStatus // Default status to return when throttled } // ServerStatusCache manages cached server statuses @@ -73,6 +73,15 @@ func (c *ServerStatusCache) UpdateStatus(serviceName string, status ServiceStatu c.lastChecked[serviceName] = time.Now() } +// InvalidateStatus removes a specific service from the cache +func (c *ServerStatusCache) InvalidateStatus(serviceName string) { + c.Lock() + defer c.Unlock() + + delete(c.cache, serviceName) + delete(c.lastChecked, serviceName) +} + // Clear removes all entries from the cache func (c *ServerStatusCache) Clear() { c.Lock() @@ -100,7 +109,7 @@ func NewLookupCache() *LookupCache { func (c *LookupCache) Get(key string) (interface{}, bool) { c.RLock() defer c.RUnlock() - + value, exists := c.data[key] if exists { logging.Debug("Cache HIT for key: %s", key) @@ -114,7 +123,7 @@ func (c *LookupCache) Get(key string) (interface{}, bool) { func (c *LookupCache) Set(key string, value interface{}) { c.Lock() defer c.Unlock() - + c.data[key] = value logging.Debug("Cache SET for key: %s", key) } @@ -123,7 +132,7 @@ func (c *LookupCache) Set(key string, value interface{}) { func (c *LookupCache) Clear() { c.Lock() defer c.Unlock() - + c.data = make(map[string]interface{}) logging.Debug("Cache CLEARED") } @@ -285,4 +294,4 @@ func (c *ServerConfigCache) Clear() { c.event = make(map[string]*ConfigEntry[EventConfig]) c.eventRules = make(map[string]*ConfigEntry[EventRules]) c.settings = make(map[string]*ConfigEntry[ServerSettings]) -} \ No newline at end of file +} diff --git a/local/service/api.go b/local/service/api.go index 0d6c75f..ea75870 100644 --- a/local/service/api.go +++ b/local/service/api.go @@ -123,6 +123,25 @@ func (as *ApiService) StatusServer(serviceName string) (string, error) { return as.windowsService.Status(context.Background(), serviceName) } +// GetCachedStatus gets the cached status for a service name without requiring fiber context +func (as *ApiService) GetCachedStatus(serviceName string) (string, error) { + // Try to get status from cache + if status, shouldCheck := as.statusCache.GetStatus(serviceName); !shouldCheck { + return status.String(), nil + } + + // If cache miss or expired, check actual status + statusStr, err := as.StatusServer(serviceName) + if err != nil { + return "", err + } + + // Parse and update cache with new status + status := model.ParseServiceStatus(statusStr) + as.statusCache.UpdateStatus(serviceName, status) + return status.String(), nil +} + func (as *ApiService) StartServer(serviceName string) (string, error) { status, err := as.windowsService.Start(context.Background(), serviceName) if err != nil { diff --git a/local/service/server.go b/local/service/server.go index b3384ff..d76222b 100644 --- a/local/service/server.go +++ b/local/service/server.go @@ -210,6 +210,9 @@ func (s *ServerService) handleStateChange(server *model.Server, state *model.Ser // Update session duration when session changes s.updateSessionDuration(server, state.Session) + // Invalidate status cache when server state changes + s.apiService.statusCache.InvalidateStatus(server.ServiceName) + // Cancel existing timer if any if debouncer, exists := s.debouncers.Load(server.ID); exists { pending := debouncer.(*pendingState) @@ -278,7 +281,7 @@ func (s *ServerService) GetAll(ctx *fiber.Ctx, filter *model.ServerFilter) (*[]m for i := range *servers { server := &(*servers)[i] - status, err := s.apiService.StatusServer(server.ServiceName) + status, err := s.apiService.GetCachedStatus(server.ServiceName) if err != nil { logging.Error("Failed to get status for server %s: %v", server.ServiceName, err) } @@ -309,7 +312,7 @@ func (as *ServerService) GetById(ctx *fiber.Ctx, serverID uuid.UUID) (*model.Ser if err != nil { return nil, err } - status, err := as.apiService.StatusServer(server.ServiceName) + status, err := as.apiService.GetCachedStatus(server.ServiceName) if err != nil { logging.Error(err.Error()) } @@ -427,6 +430,9 @@ func (s *ServerService) DeleteServer(ctx *fiber.Ctx, serverID uuid.UUID) error { s.debouncers.Delete(server.ID) s.sessionIDs.Delete(server.ID) + // Invalidate status cache for deleted server + s.apiService.statusCache.InvalidateStatus(server.ServiceName) + return nil } @@ -467,6 +473,8 @@ func (s *ServerService) UpdateServer(ctx *fiber.Ctx, server *model.Server) error if err := s.configureFirewall(server); err != nil { return fmt.Errorf("failed to update firewall rules: %v", err) } + // Invalidate cache for old service name + s.apiService.statusCache.InvalidateStatus(existingServer.ServiceName) } // Update database record