From ffc1905017aeb868116ced95ecd608fdf674c2a3 Mon Sep 17 00:00:00 2001 From: Pascal Fischer Date: Fri, 6 Jun 2025 16:39:32 +0200 Subject: [PATCH] interface server --- internal/server/boot.go | 37 +++++----------------------------- internal/server/container.go | 18 ++++++++--------- internal/server/controllers.go | 11 ++++++++++ internal/server/modules.go | 22 ++++++++++++++++++-- internal/server/server.go | 33 +++++++++++++++++++++++++----- 5 files changed, 73 insertions(+), 48 deletions(-) create mode 100644 internal/server/controllers.go diff --git a/internal/server/boot.go b/internal/server/boot.go index 2c958d5..5435376 100644 --- a/internal/server/boot.go +++ b/internal/server/boot.go @@ -8,17 +8,14 @@ import ( "github.com/gorilla/mux" - "management/internal/controllers/network_map" - "management/internal/modules/peers" "management/internal/shared/activity" "management/internal/shared/activity/sqlite" "management/internal/shared/api/rest" "management/internal/shared/db" "management/internal/shared/metrics" - "management/internal/shared/permissions" ) -func (s *Server) Store() *db.Store { +func (s *server) Store() *db.Store { return Create(s, func() *db.Store { ctx := context.Background() dbConn, err := db.NewDatabaseConn(ctx) @@ -30,7 +27,7 @@ func (s *Server) Store() *db.Store { }) } -func (s *Server) HttpServer() *http.Server { +func (s *server) HttpServer() *http.Server { return Create(s, func() *http.Server { router := s.Router() @@ -41,7 +38,7 @@ func (s *Server) HttpServer() *http.Server { }) } -func (s *Server) Metrics() *metrics.AppMetrics { +func (s *server) Metrics() *metrics.AppMetrics { return Create(s, func() *metrics.AppMetrics { appMetrics, err := metrics.NewAppMetrics() if err != nil { @@ -51,13 +48,13 @@ func (s *Server) Metrics() *metrics.AppMetrics { }) } -func (s *Server) Router() *mux.Router { +func (s *server) Router() *mux.Router { return Create(s, func() *mux.Router { return rest.NewRouter() }) } -func (s *Server) EventStore() activity.Store { +func (s *server) EventStore() activity.Store { return Create(s, func() activity.Store { ctx := context.Background() store, err := sqlite.NewSQLiteStore(ctx, "dataDir", "encryptionKey") @@ -67,27 +64,3 @@ func (s *Server) EventStore() activity.Store { return store }) } - -func (s *Server) NetworkMapController() *network_map.Controller { - return Create(s, func() *network_map.Controller { - store := s.Store() - metrics := s.Metrics() - return network_map.NewController(store, metrics) - }) -} - -func (s *Server) PermissionsManager() permissions.Manager { - return Create(s, func() permissions.Manager { - return permissions.NewManager() - }) -} - -func (s *Server) PeersManager() *peers.Manager { - return Create(s, func() *peers.Manager { - store := s.Store() - router := s.Router() - permissionsManager := s.PermissionsManager() - - return peers.NewManager(store, router, permissionsManager) - }) -} diff --git a/internal/server/container.go b/internal/server/container.go index 6e74894..43c0dc8 100644 --- a/internal/server/container.go +++ b/internal/server/container.go @@ -3,7 +3,7 @@ package server import "fmt" // Create a dependency and add it to the server's container. A string key identifier will be based on its type definition. -func Create[T any](s *Server, createFunc func() T) T { +func Create[T any](s Server, createFunc func() T) T { result, _ := maybeCreate(s, createFunc) return result @@ -11,7 +11,7 @@ func Create[T any](s *Server, createFunc func() T) T { // CreateNamed is the same as Create but will suffix the dependency string key identifier with a custom name. // Useful if you want to have multiple named instances of the same object type. -func CreateNamed[T any](s *Server, name string, createFunc func() T) T { +func CreateNamed[T any](s Server, name string, createFunc func() T) T { result, _ := maybeCreateNamed(s, name, createFunc) return result @@ -19,37 +19,37 @@ func CreateNamed[T any](s *Server, name string, createFunc func() T) T { // Inject lets you override a specific service from outside the server itself. // This is useful for tests -func Inject[T any](c *Server, thing T) { +func Inject[T any](c Server, thing T) { _, _ = maybeCreate(c, func() T { return thing }) } // InjectNamed is like Inject() but with a custom name. -func InjectNamed[T any](c *Server, name string, thing T) { +func InjectNamed[T any](c Server, name string, thing T) { _, _ = maybeCreateKeyed(c, name, func() T { return thing }) } -func maybeCreate[T any](s *Server, createFunc func() T) (result T, isNew bool) { +func maybeCreate[T any](s Server, createFunc func() T) (result T, isNew bool) { key := fmt.Sprintf("%T", (*T)(nil))[1:] return maybeCreateKeyed(s, key, createFunc) } -func maybeCreateNamed[T any](s *Server, name string, createFunc func() T) (result T, isNew bool) { +func maybeCreateNamed[T any](s Server, name string, createFunc func() T) (result T, isNew bool) { key := fmt.Sprintf("%T:%s", (*T)(nil), name)[1:] return maybeCreateKeyed(s, key, createFunc) } -func maybeCreateKeyed[T any](s *Server, key string, createFunc func() T) (result T, isNew bool) { - if t, ok := s.container[key]; ok { +func maybeCreateKeyed[T any](s Server, key string, createFunc func() T) (result T, isNew bool) { + if t, ok := s.GetContainer(key); ok { return t.(T), false } t := createFunc() - s.container[key] = t + s.SetContainer(key, t) return t, true } diff --git a/internal/server/controllers.go b/internal/server/controllers.go new file mode 100644 index 0000000..e3f9df1 --- /dev/null +++ b/internal/server/controllers.go @@ -0,0 +1,11 @@ +package server + +import "management/internal/controllers/network_map" + +func (s *server) NetworkMapController() *network_map.Controller { + return Create(s, func() *network_map.Controller { + store := s.Store() + metrics := s.Metrics() + return network_map.NewController(store, metrics) + }) +} diff --git a/internal/server/modules.go b/internal/server/modules.go index 6b6a214..5696871 100644 --- a/internal/server/modules.go +++ b/internal/server/modules.go @@ -5,16 +5,34 @@ import ( "management/internal/modules/networks/manager" "management/internal/modules/networks/resources" resourcesManager "management/internal/modules/networks/resources/manager" + "management/internal/modules/peers" + "management/internal/shared/permissions" ) -func (s *Server) NetworksManager() networks.Manager { +func (s *server) NetworksManager() networks.Manager { return Create(s, func() networks.Manager { return manager.NewManager(s.Store(), s.Router(), s.PermissionsManager()) }) } -func (s *Server) ResourcesManager() resources.Manager { +func (s *server) ResourcesManager() resources.Manager { return Create(s, func() resources.Manager { return resourcesManager.NewManager(s.Store(), s.Router(), s.NetworksManager()) }) } + +func (s *server) PermissionsManager() permissions.Manager { + return Create(s, func() permissions.Manager { + return permissions.NewManager() + }) +} + +func (s *server) PeersManager() *peers.Manager { + return Create(s, func() *peers.Manager { + store := s.Store() + router := s.Router() + permissionsManager := s.PermissionsManager() + + return peers.NewManager(store, router, permissionsManager) + }) +} diff --git a/internal/server/server.go b/internal/server/server.go index 205c1b4..d13c421 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -7,9 +7,16 @@ import ( "management/pkg/logging" ) +type Server interface { + Start() error + Stop() error + GetContainer(key string) (any, bool) + SetContainer(key string, container any) +} + // Server holds the HTTP server instance. // Add any additional fields you need, such as database connections, config, etc. -type Server struct { +type server struct { // container of dependencies, each dependency is identified by a unique string. container map[string]any } @@ -17,15 +24,15 @@ type Server struct { var log = logging.LoggerForThisPackage() // NewServer initializes and configures a new Server instance -func NewServer() *Server { - return &Server{ +func NewServer() Server { + return &server{ // @todo shared config container: make(map[string]any), } } // Start begins listening for HTTP requests on the configured address -func (s *Server) Start() error { +func (s *server) Start() error { // @todo instead of specifically starting httpserver // have a supervised start/stop of dependencies instead. // e.g. http, grpc, metrics, crons, etc @@ -33,9 +40,25 @@ func (s *Server) Start() error { } // Stop attempts a graceful shutdown, waiting up to 5 seconds for active connections to finish -func (s *Server) Stop() error { +func (s *server) Stop() error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() return s.HttpServer().Shutdown(ctx) } + +// GetContainer retrieves a dependency from the server's container by its key +func (s *server) GetContainer(key string) (any, bool) { + container, exists := s.container[key] + return container, exists +} + +// SetContainer stores a dependency in the server's container with the specified key +func (s *server) SetContainer(key string, container any) { + if _, exists := s.container[key]; exists { + log.Errorf("container with key %s already exists", key) + return + } + s.container[key] = container + log.Infof("container with key %s set successfully", key) +}