package main import ( "context" "errors" "fmt" "log/slog" "net/http" "os" "os/signal" "strconv" "syscall" "time" "data-terminal-cloud/internal/mockprovider" ) func main() { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() logger := slog.New(slog.NewJSONHandler(os.Stdout, nil)).With("service", "mock-provider") if err := run(ctx, logger); err != nil { logger.Error("mock provider stopped", "error", err) os.Exit(1) } } func run(ctx context.Context, logger *slog.Logger) error { duplicates, err := strconv.Atoi(env("MOCK_PROVIDER_DUPLICATE_CALLBACKS", "2")) if err != nil { return fmt.Errorf("invalid duplicate callback count: %w", err) } delay, err := time.ParseDuration(env("MOCK_PROVIDER_START_DELAY", "100ms")) if err != nil { return fmt.Errorf("invalid start delay: %w", err) } provider, err := mockprovider.New(mockprovider.Options{ APIKey: env("MOCK_PROVIDER_API_KEY", "local-mock-provider-key"), CallbackURL: env("MOCK_PROVIDER_CALLBACK_URL", "http://localhost:58081/callbacks/v1/vertc/voice-chat"), CallbackSecret: env("PROVIDER_CALLBACK_SECRET", "local-provider-callback-secret-32-bytes-minimum"), StartDelay: delay, DuplicateCallbacks: duplicates, }, logger) if err != nil { return fmt.Errorf("create mock provider: %w", err) } server := &http.Server{ Addr: env("HTTP_ADDR", "0.0.0.0:59200"), Handler: provider.Handler(), ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, IdleTimeout: 30 * time.Second, } serverError := make(chan error, 1) go func() { logger.Info("mock provider listening", "address", server.Addr) serverError <- server.ListenAndServe() }() select { case <-ctx.Done(): shutdownContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := server.Shutdown(shutdownContext); err != nil { return fmt.Errorf("shutdown mock provider: %w", err) } case err := <-serverError: if err != nil && !errors.Is(err, http.ErrServerClosed) { return err } } return nil } func env(key, fallback string) string { if value := os.Getenv(key); value != "" { return value } return fallback }