Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var Command = &cli.Command{ Name: "serve", Usage: "Start the API server", Flags: []cli.Flag{ &cli.StringFlag{ Name: "addr", Usage: "Server listen address", Value: ":8080", Sources: cli.EnvVars(saas.EnvAddr), }, &cli.StringFlag{ Name: "database-url", Usage: "PostgreSQL connection string", Value: "postgres://postgres:postgres@localhost:5432/gmaps_pro?sslmode=disable", Sources: cli.EnvVars(saas.EnvDatabaseURL), }, &cli.IntFlag{ Name: "db-max-conns", Usage: "Maximum database connections", Value: 10, Sources: cli.EnvVars(saas.EnvDBMaxConns), }, &cli.IntFlag{ Name: "db-min-conns", Usage: "Minimum database connections", Value: 2, Sources: cli.EnvVars(saas.EnvDBMinConns), }, &cli.DurationFlag{ Name: "db-max-conn-lifetime", Usage: "Maximum connection lifetime", Value: time.Hour, Sources: cli.EnvVars(saas.EnvDBMaxConnLifetime), }, &cli.DurationFlag{ Name: "db-max-conn-idle-time", Usage: "Maximum connection idle time", Value: 30 * time.Minute, Sources: cli.EnvVars(saas.EnvDBMaxConnIdleTime), }, &cli.StringFlag{ Name: "encryption-key", Usage: "Hex-encoded 32-byte encryption key for sensitive data. Generate with: openssl rand -hex 32", Sources: cli.EnvVars(saas.EnvEncryptionKey), Required: true, }, }, Action: func(ctx context.Context, cmd *cli.Command) error { addr := cmd.String("addr") dsn := cmd.String("database-url") dbPool, err := postgres.Connect(ctx, dsn, postgres.WithMaxConns(int32(cmd.Int("db-max-conns"))), postgres.WithMinConns(int32(cmd.Int("db-min-conns"))), postgres.WithMaxConnLifetime(cmd.Duration("db-max-conn-lifetime")), postgres.WithMaxConnIdleTime(cmd.Duration("db-max-conn-idle-time")), ) if err != nil { return err } defer dbPool.Close() encKeyHex := cmd.String("encryption-key") if encKeyHex == "0398d4cad290e145cb8242bb74e045264564d384d33ada80ff7702e460e6956c" { return fmt.Errorf("ENCRYPTION_KEY must not be the default value. Generate one with: openssl rand -hex 32") } encryptionKey, err := cryptoext.ParseEncryptionKey(encKeyHex) if err != nil { return fmt.Errorf("invalid ENCRYPTION_KEY (must be 64 hex chars / 32 bytes): %w. Generate one with: openssl rand -hex 32", err) } env.LogUnsetEnvs(saas.EnvDatabaseURL, saas.EnvEncryptionKey) adminStore := adminpostgres.NewWithPool(dbPool, encryptionKey) apiStore := apipostgres.New(dbPool) dsnConfig := &admin.AppConfig{ Key: "database_url", Value: dsn, } if err = adminStore.SetConfig(ctx, dsnConfig, true); err != nil { return err } rqueueClient, err := rqueue.NewClient(dbPool, encryptionKey) if err != nil { return err } if err = rqueueClient.Start(ctx); err != nil { return err } riverUIHandler, err := rqueue.CreateRiverUIHandler(ctx, rqueueClient) if err != nil { return err } if err = riverUIHandler.Start(ctx); err != nil { return err } rateLimiter := ratelimitpostgres.New(dbPool) adminState, err := admin.NewAppState(adminStore, rateLimiter, encryptionKey) if err != nil { return err } adminState.RQueueClient = rqueueClient apiState := api.NewAppState(rqueueClient, apiStore) mainRouter := chi.NewRouter() mainRouter.Use(middleware.Recoverer) admin.Routes(mainRouter, adminState, riverUIHandler) mainRouter.Group(func(r chi.Router) { api.Routes(r, apiState) }) mainRouter.Get("/swagger/*", httpSwagger.Handler( httpSwagger.URL("/swagger/doc.json"), )) srv, err := httpext.New(mainRouter, httpext.WithAddr(addr)) if err != nil { return err } log.Info("starting server", "addr", addr) return srv.Run(ctx) }, }
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.