Parent directory

main.go

1484 bytes
 1package main
 2
 3import (
 4	"context"
 5	"fmt"
 6	"log/slog"
 7	"net/http"
 8	"os"
 9	"os/signal"
10	"syscall"
11	"time"
12
13	"git.theedgeofrage.com/TheEdgeOfRage/kaiwari/internal/bootstrap"
14	"git.theedgeofrage.com/TheEdgeOfRage/kaiwari/internal/config"
15	"git.theedgeofrage.com/TheEdgeOfRage/kaiwari/internal/server"
16)
17
18const shutdownTimeout = 10 * time.Second
19
20func main() {
21	slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, nil)))
22	cfg := config.ParseServerConfig()
23	if cfg.Token == "" {
24		fatalf("token is required: set --token or JP_SERVER_TOKEN")
25	}
26
27	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
28	defer stop()
29
30	svc, err := bootstrap.New(ctx, &cfg.Config)
31	if err != nil {
32		fatalf("%v", err)
33	}
34	defer svc.Close()
35
36	srv := server.New(svc, cfg.Token)
37	httpSrv := &http.Server{Addr: cfg.Listen, Handler: srv.Handler()}
38	errCh := make(chan error, 1)
39	go func() {
40		if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
41			errCh <- err
42		}
43	}()
44
45	fmt.Printf("kaiwari-server: listening on %s\n", cfg.Listen)
46	select {
47	case err := <-errCh:
48		svc.Close()
49		fatalf("%v", err)
50	case <-ctx.Done():
51		shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
52		defer cancel()
53		if err := httpSrv.Shutdown(shutdownCtx); err != nil {
54			svc.Close()
55			fatalf("shutdown: %v", err)
56		}
57	}
58}
59
60func fatalf(format string, args ...any) {
61	fmt.Fprintf(os.Stderr, "kaiwari-server: "+format+"\n", args...)
62	os.Exit(1)
63}