package heroagent import ( "fmt" "log" "sync" "git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver" "git.ourworld.tf/herocode/heroagent/pkg/servers/ui" "git.ourworld.tf/herocode/heroagent/pkg/servers/webdavserver" "github.com/gofiber/fiber/v2" ) // ServerFactory manages the lifecycle of all servers type ServerFactory struct { config Config // Server instances redisServer *redisserver.Server webdavServer *webdavserver.Server uiApp *AppInstance jobManager *JobManager // Control channels stopCh chan struct{} wg sync.WaitGroup } // AppInstance wraps the UI app and its listening status type AppInstance struct { App *fiber.App Port string } // New creates a new ServerFactory with the given configuration func New(config Config) *ServerFactory { return &ServerFactory{ config: config, stopCh: make(chan struct{}), } } // Start initializes and starts all enabled servers func (f *ServerFactory) Start() error { log.Println("Starting HeroAgent ServerFactory...") // Start Redis server if enabled if f.config.EnableRedis { if err := f.startRedisServer(); err != nil { return fmt.Errorf("failed to start Redis server: %w", err) } } // Start WebDAV server if enabled if f.config.EnableWebDAV { if err := f.startWebDAVServer(); err != nil { return fmt.Errorf("failed to start WebDAV server: %w", err) } } // Start UI server if enabled if f.config.EnableUI { if err := f.startUIServer(); err != nil { return fmt.Errorf("failed to start UI server: %w", err) } } // Start job manager if enabled if f.config.EnableJobs { if err := f.startJobManager(); err != nil { return fmt.Errorf("failed to start job manager: %w", err) } } log.Println("All servers started successfully") return nil } // Stop gracefully stops all running servers func (f *ServerFactory) Stop() error { log.Println("Stopping all servers...") // Signal all goroutines to stop close(f.stopCh) // Stop WebDAV server if it's running if f.webdavServer != nil { if err := f.webdavServer.Stop(); err != nil { log.Printf("Error stopping WebDAV server: %v", err) } } // Stop job manager if it's running if f.jobManager != nil { if err := f.jobManager.Stop(); err != nil { log.Printf("Error stopping job manager: %v", err) } } // Wait for all goroutines to finish f.wg.Wait() log.Println("All servers stopped") return nil } // startRedisServer initializes and starts the Redis server func (f *ServerFactory) startRedisServer() error { log.Println("Starting Redis server...") // Create Redis server configuration redisConfig := redisserver.ServerConfig{ TCPPort: f.config.Redis.TCPPort, UnixSocketPath: f.config.Redis.UnixSocketPath, } // Create and start Redis server f.redisServer = redisserver.NewServer(redisConfig) log.Printf("Redis server started on port %d and socket %s", redisConfig.TCPPort, redisConfig.UnixSocketPath) return nil } // startWebDAVServer initializes and starts the WebDAV server func (f *ServerFactory) startWebDAVServer() error { log.Println("Starting WebDAV server...") // Create WebDAV server webdavServer, err := webdavserver.NewServer(f.config.WebDAV.Config) if err != nil { return fmt.Errorf("failed to create WebDAV server: %w", err) } f.webdavServer = webdavServer // Start WebDAV server in a goroutine f.wg.Add(1) go func() { defer f.wg.Done() // Start the server if err := webdavServer.Start(); err != nil { log.Printf("WebDAV server error: %v", err) } }() log.Printf("WebDAV server started on port %d", f.config.WebDAV.Config.TCPPort) return nil } // startUIServer initializes and starts the UI server func (f *ServerFactory) startUIServer() error { log.Println("Starting UI server...") // Create UI app uiApp := ui.NewApp(f.config.UI.AppConfig) // Store UI app instance f.uiApp = &AppInstance{ App: uiApp, Port: f.config.UI.Port, } // Start UI server in a goroutine f.wg.Add(1) go func() { defer f.wg.Done() // Start the server addr := ":" + f.config.UI.Port log.Printf("UI server listening on %s", addr) if err := uiApp.Listen(addr); err != nil { log.Printf("UI server error: %v", err) } }() return nil } // GetRedisServer returns the Redis server instance func (f *ServerFactory) GetRedisServer() *redisserver.Server { return f.redisServer } // GetWebDAVServer returns the WebDAV server instance func (f *ServerFactory) GetWebDAVServer() *webdavserver.Server { return f.webdavServer } // GetUIApp returns the UI app instance func (f *ServerFactory) GetUIApp() *AppInstance { return f.uiApp } // startJobManager initializes and starts the job manager func (f *ServerFactory) startJobManager() error { log.Println("Starting job manager...") // Create Redis connection for job manager redisConn := &RedisConnection{ TCPPort: f.config.Redis.TCPPort, UnixSocketPath: f.config.Redis.UnixSocketPath, } // Create job manager jobManager, err := NewJobManager(f.config.Jobs, redisConn) if err != nil { return fmt.Errorf("failed to create job manager: %w", err) } f.jobManager = jobManager // Start job manager if err := jobManager.Start(); err != nil { return fmt.Errorf("failed to start job manager: %w", err) } log.Println("Job manager started") return nil } // GetJobManager returns the job manager instance func (f *ServerFactory) GetJobManager() *JobManager { return f.jobManager }