package main import ( "context" "log" "net/http" "os" "cmpp-platform/gateway/internal/control" "cmpp-platform/gateway/internal/health" "cmpp-platform/gateway/internal/inbound" "cmpp-platform/gateway/internal/ratelimit" "cmpp-platform/gateway/internal/submitworker" "cmpp-platform/gateway/internal/upstream" ) func main() { addr := os.Getenv("GATEWAY_HEALTH_ADDR") if addr == "" { addr = ":8090" } cmppAddr := os.Getenv("GATEWAY_CMPP_ADDR") if cmppAddr == "" { cmppAddr = ":17890" } apiBaseURL := os.Getenv("API_BASE_URL") upstreamManager := &upstream.Manager{APIBaseURL: apiBaseURL} channelLimiter, err := ratelimit.New(os.Getenv("REDIS_URL")) if err != nil { log.Fatalf("gateway channel rate limiter init failed: %v", err) } presenceStore, err := inbound.NewRedisPresenceStore(os.Getenv("REDIS_URL")) if err != nil { log.Printf("gateway downstream presence store init failed: %v", err) } recoveryStore, err := inbound.NewRedisRecoveryStore(os.Getenv("REDIS_URL")) if err != nil { log.Printf("gateway downstream recovery store init failed: %v", err) } go func() { log.Printf("cmpp gateway inbound server listening on %s", cmppAddr) if err := (inbound.Server{ Addr: cmppAddr, APIBaseURL: apiBaseURL, PresenceStore: presenceStore, RecoveryStore: recoveryStore, GatewayInstanceID: getenv("GATEWAY_INSTANCE_ID", hostname()), }).ListenAndServe(); err != nil { log.Fatalf("gateway inbound server stopped: %v", err) } }() if os.Getenv("GATEWAY_SUBMIT_WORKER_DISABLED") != "true" { worker, err := submitworker.New(os.Getenv("REDIS_URL"), upstreamManager) if err != nil { log.Printf("gateway submit worker init failed: %v", err) } else { worker.Stream = getenv("GATEWAY_SUBMIT_STREAM", "gateway.submit.commands") worker.Group = getenv("GATEWAY_SUBMIT_GROUP", "cmpp-gateway") worker.Consumer = getenv("GATEWAY_SUBMIT_CONSUMER", "gateway-1") worker.APIBaseURL = apiBaseURL go func() { log.Printf("cmpp gateway submit worker consuming stream=%s group=%s consumer=%s", worker.Stream, worker.Group, worker.Consumer) if err := worker.Run(context.Background()); err != nil { log.Printf("gateway submit worker stopped: %v", err) } }() } } mux := http.NewServeMux() mux.Handle("/health", health.Handler()) control.Register(mux, control.Server{ APIBaseURL: apiBaseURL, Upstream: upstreamManager, Limiter: channelLimiter, RecoveryCandidates: func(ctx context.Context) ([]inbound.DownstreamPresence, error) { return inbound.ListRecoveryCandidates(ctx, presenceStore) }, RecoveryStatuses: func(ctx context.Context) ([]inbound.DownstreamRecoveryStatus, error) { if recoveryStore == nil { return nil, nil } return recoveryStore.ListRecoveryStatuses(ctx) }, }) log.Printf("cmpp gateway control server listening on %s", addr) if err := http.ListenAndServe(addr, mux); err != nil { log.Fatalf("gateway control server stopped: %v", err) } } func getenv(key string, fallback string) string { value := os.Getenv(key) if value == "" { return fallback } return value } func hostname() string { name, err := os.Hostname() if err != nil || name == "" { return "gateway-1" } return name }