package main import ( "context" "flag" "fmt" "log" "net/http" "os" "os/signal" "sync/atomic" "syscall" ) func main() { address := flag.String("address", ":8080", "listen address") configPath := flag.String("configuration", "", "path to configuration file") bufferSize := flag.Int("buffer-size", 1000, "event replay buffer size") backendType := flag.String("backend", "memory", "pub/sub backend: memory or redis") redisURL := flag.String("redis-url", "redis://localhost:6379", "Redis connection URL (when backend=redis)") flag.Parse() var cfgPtr atomic.Pointer[Configuration] if *configPath != "" { cfg, err := LoadConfiguration(*configPath) if err != nil { log.Fatalf("loading configuration: %v", err) } cfgPtr.Store(cfg) log.Printf("loaded configuration from %s", *configPath) stop, err := WatchConfiguration(*configPath, func(cfg *Configuration) { cfgPtr.Store(cfg) log.Printf("reloaded configuration from %s", *configPath) }) if err != nil { log.Fatalf("watching configuration: %v", err) } defer stop() } var backend Backend switch *backendType { case "memory": backend = NewMemoryBackend(*bufferSize) case "redis": var err error backend, err = NewRedisBackend(*redisURL, *bufferSize) if err != nil { log.Fatalf("connecting to redis: %v", err) } default: log.Fatalf("unknown backend: %s", *backendType) } defer backend.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() broker := NewBroker(backend) broker.Start(ctx) handler := NewServer(broker, &cfgPtr) server := &http.Server{ Addr: *address, Handler: handler, } go func() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) for sig := range sigs { switch sig { case syscall.SIGHUP: if *configPath == "" { continue } cfg, err := LoadConfiguration(*configPath) if err != nil { log.Printf("reloading configuration: %v", err) continue } cfgPtr.Store(cfg) log.Printf("reloaded configuration from %s", *configPath) case syscall.SIGINT, syscall.SIGTERM: log.Printf("shutting down") cancel() server.Shutdown(context.Background()) return } } }() fmt.Fprintf(os.Stderr, "wicket listening on %s\n", *address) if err := server.ListenAndServe(); err != http.ErrServerClosed { log.Fatalf("server error: %v", err) } }