Short and single-letter names in application code become full words (tests keep theirs). Wrapped calls, signatures and composite literals put one item per line, and one-line function bodies are expanded. Exported names and groups of constants get doc comments, and comments refer to the renamed identifiers.
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
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"
|
|
)
|
|
|
|
// NewCommand returns the wsserve command, which runs a plain TCP server for
|
|
// websocket hub clients (see 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)
|
|
server := tcpserver.New(&conf.Server, hub)
|
|
|
|
return server.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
|
|
}
|