interface server

This commit is contained in:
Pascal Fischer
2025-06-06 16:39:32 +02:00
parent f930078950
commit ffc1905017
5 changed files with 73 additions and 48 deletions
+5 -32
View File
@@ -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)
})
}
+9 -9
View File
@@ -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
}
+11
View File
@@ -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)
})
}
+20 -2
View File
@@ -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)
})
}
+28 -5
View File
@@ -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)
}