package socket import ( "context" "errors" "log/slog" protoSocket "git.toki-labs.com/toki/proto-socket/go" "nhooyr.io/websocket" "git.toki-labs.com/toki/alt/services/api/internal/config" apiContracts "git.toki-labs.com/toki/alt/services/api/internal/contracts" "git.toki-labs.com/toki/alt/services/api/internal/workerclient" ) const ( serverName = "alt-api" serverVersion = "dev" defaultAltProtocolVersion = "alt.v1" ) type Server struct { wsServer *protoSocket.WsServer worker workerclient.WorkerClient } func NewServer(cfg config.Config) *Server { return NewServerWithWorker(cfg, workerclient.New(cfg.WorkerSocketURL)) } func NewServerWithWorker(cfg config.Config, worker workerclient.WorkerClient) *Server { options := protoSocket.WsServerOptions{} if len(cfg.WSOriginPatterns) > 0 { options.AcceptOptions = &websocket.AcceptOptions{ OriginPatterns: cfg.WSOriginPatterns, } } wsServer := protoSocket.NewWsServerWithOptions(cfg.Host, cfg.Port, cfg.SocketPath, options, func(conn *websocket.Conn) *protoSocket.WsClient { return protoSocket.NewWsClient(conn, cfg.HeartbeatIntervalSec, cfg.HeartbeatWaitSec, apiContracts.ParserMap()) }) wsServer.OnClientConnected = registerSessionHandlers(worker) return &Server{ wsServer: wsServer, worker: worker, } } func (s *Server) Start(ctx context.Context) error { go func() { if err := s.worker.Connect(ctx); err != nil { slog.Warn("eager worker connection failed on startup", "error", err) } }() return s.wsServer.Start(ctx) } func (s *Server) Stop() error { var errs []error if err := s.wsServer.Stop(); err != nil { errs = append(errs, err) } if err := s.worker.Close(); err != nil { errs = append(errs, err) } if len(errs) > 0 { return errors.Join(errs...) } return nil }