package main import ( "context" "errors" "flag" "log" "net/http" "os" "os/signal" "syscall" "time" "code.northwest.io/axon/relay/storage" "code.northwest.io/axon/relay/subscription" ) func main() { cfgPath := flag.String("config", "config.yaml", "path to config.yaml") flag.Parse() cfg, err := LoadConfig(*cfgPath) if err != nil { log.Fatalf("relay: load config: %v", err) } allowlist, err := cfg.AllowlistBytes() if err != nil { log.Fatalf("relay: allowlist: %v", err) } store, err := storage.New(cfg.DB) if err != nil { log.Fatalf("relay: open storage: %v", err) } defer store.Close() global := subscription.NewGlobalManager() // Periodically purge closed subscriptions. stopPurger := make(chan struct{}) global.StartPurger(5*time.Minute, stopPurger) defer close(stopPurger) srv := NewServer(cfg, allowlist, store, global) // Graceful shutdown on SIGINT / SIGTERM. sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) errCh := make(chan error, 1) go func() { if err := srv.Start(); err != nil && !errors.Is(err, http.ErrServerClosed) { errCh <- err } }() select { case sig := <-sigCh: log.Printf("relay: received signal %s, shutting down", sig) case err := <-errCh: log.Fatalf("relay: server error: %v", err) } shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { log.Printf("relay: shutdown error: %v", err) } log.Println("relay: stopped") }