package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "codespace/internal/api" "codespace/internal/process" "codespace/internal/service" "codespace/internal/workspace" "codespace/pkg/config" "codespace/pkg/logger" ) func main() { cfg, err := config.Load("configs/config.yaml") if err != nil { log.Fatalf("failed to load config: %v", err) } lg := logger.New() workspaces := workspace.NewLocalManager(cfg.Workspace.Root) processes := process.NewManager(cfg.Process.OpenCodeCommand) workspaceSvc := service.NewWorkspaceService(workspaces, processes) fileSvc := service.NewFileService(workspaces) processSvc := service.NewProcessService(workspaces, processes) router := api.NewRouter(workspaceSvc, fileSvc, processSvc) server := &http.Server{ Addr: cfg.Server.Addr, Handler: router, ReadTimeout: cfg.Server.ReadTimeout, WriteTimeout: cfg.Server.WriteTimeout, IdleTimeout: cfg.Server.IdleTimeout, MaxHeaderBytes: cfg.Server.MaxHeaderBytes, } lg.Printf("listening on %s, workspace root: %s", cfg.Server.Addr, cfg.Workspace.Root) go func() { if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { lg.Fatalf("server error: %v", err) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit lg.Printf("shutting down...") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := server.Shutdown(ctx); err != nil { lg.Fatalf("forced shutdown: %v", err) } }