package wsserve import ( "context" "fmt" "log/slog" "os" "os/signal" "strconv" "strings" "syscall" "github.com/spf13/cobra" "git.avsdev.uk/Go/job-search/internal/cli" "git.avsdev.uk/Go/job-search/internal/websocket" "git.avsdev.uk/Go/job-search/internal/websocket/tcpserver" ) func NewCommand(opts *cli.Options) *cobra.Command { cmd := &cobra.Command{ Use: "wsserve", Short: "Run JobSearch TCP Websocket server", PersistentPreRun: func(cmd *cobra.Command, args []string) { slog.Debug("command persistent pre-run", "command", "wsserve") }, PersistentPostRun: func(cmd *cobra.Command, args []string) { slog.Debug("command persistent post-run", "command", "wsserve") }, RunE: func(cmd *cobra.Command, args []string) error { slog.Debug("command run", "command", "wsserve") addrOverride, _ := cmd.Flags().GetString("listen") hostOverride, _ := cmd.Flags().GetString("host") portOverride, _ := cmd.Flags().GetInt("port") if addrOverride != "" { listenParts := strings.Split(addrOverride, ":") if len(listenParts) != 2 { return fmt.Errorf( "--listen should be in the format of 127.0.0.1:9393", ) } i, err := strconv.Atoi(listenParts[1]) if err != nil { return fmt.Errorf("Failed to parse --listen port: %w", err) } hostOverride = listenParts[0] portOverride = i } conf, err := opts.RunSetup(cmd, true, true) if err != nil { return fmt.Errorf("no configuration loaded (%w)", err) } if portOverride != 0 { conf.Server.Port = portOverride } if hostOverride != "" { conf.Server.Host = hostOverride } // ctx is cancelled on the first SIGINT (Ctrl+C) or SIGTERM. ctx, stop := signal.NotifyContext( context.Background(), os.Interrupt, syscall.SIGTERM, ) defer stop() // After the first signal, restore default signal handling so a second // Ctrl+C force-kills the process if graceful shutdown hangs. go func() { <-ctx.Done() stop() }() hub := websocket.NewHub(conf.Server.WebSocket) svr := tcpserver.New(&conf.Server, hub) return svr.Run(ctx) }, } cmd.Flags().String("listen", "", "listen address (default from config, 127.0.0.1:9393)") cmd.Flags().String("host", "", "listen address (default from config, 127.0.0.1)") cmd.Flags().Int("port", 0, "listen address (default from config, 9393)") cmd.Flags().Bool("foreground", false, "run in the foreground") cmd.MarkFlagsMutuallyExclusive("listen", "host") cmd.MarkFlagsMutuallyExclusive("listen", "port") return cmd }