package main import ( "expvar" "flag" "fmt" "os" "runtime" "strings" "sync" "time" _ "github.com/lib/pq" "greenlight.alexedwards.net/internal/data" "greenlight.alexedwards.net/internal/jsonlog" "greenlight.alexedwards.net/internal/vcs" ) var ( version = vcs.Version() ) type config struct { port int env string db struct { dsn string maxOpenConns int maxIdleConns int maxIdleTime string } limiter struct { rps float64 burst int enabled bool } smtp struct { host string port int username string password string sender string } cors struct { trustedOrigins []string } } type application struct { config config logger *jsonlog.Logger models data.Models wg sync.WaitGroup } func main() { var cfg config flag.IntVar(&cfg.port, "port", 4000, "API server port") flag.StringVar(&cfg.env, "env", "development", "Environment (development|staging|production)") flag.StringVar(&cfg.db.dsn, "db-dsn", "", "PostgresSQL DSN") flag.IntVar(&cfg.db.maxOpenConns, "db-max-open-conns", 25, "PostgreSQL max open connections") flag.IntVar(&cfg.db.maxIdleConns, "db-max-idle-conns", 25, "PostgreSQL max idle connections") flag.StringVar(&cfg.db.maxIdleTime, "db-max-idle-time", "15m", "PostgreSQL max idle time") flag.Float64Var(&cfg.limiter.rps, "limiter-rps", 2, "Rate limiter maximum requests per second") flag.IntVar(&cfg.limiter.burst, "limiter-burst", 4, "Rate limiter maximum burst") flag.BoolVar(&cfg.limiter.enabled, "limiter-enabled", true, "Enable rate limiter") flag.StringVar(&cfg.smtp.host, "smtp-host", "smtp.mailtrap.io", "SMTP server host") flag.IntVar(&cfg.smtp.port, "smtp-port", 25, "SMTP server port") flag.StringVar(&cfg.smtp.username, "smtp-username", "ebe83d2e524f7d", "SMTP server username") flag.StringVar(&cfg.smtp.password, "smtp-password", "2a46c462463a5f", "SMTP server password") flag.StringVar(&cfg.smtp.sender, "smtp-sender", "Greenlight ", "SMTP sender email address") flag.Func("cors-trusted-origins", "Trusted CORS origins (space separated)", func(val string) error { cfg.cors.trustedOrigins = strings.Fields(val) return nil }) displayVersion := flag.Bool("version", false, "Display version and exit") flag.Parse() if *displayVersion { fmt.Printf("Version: \t%s\n", version) os.Exit(0) } logger := jsonlog.New(os.Stdout, jsonlog.LevelInfo) logger.PrintInfo("database connection pool established", nil) expvar.NewString("version").Set(version) expvar.Publish("goroutines", expvar.Func(func() any { return runtime.NumGoroutine() })) expvar.Publish("timestamp", expvar.Func(func() any { return time.Now().Unix() })) app := &application{ config: cfg, logger: logger, } err := app.serve() if err != nil { logger.PrintFatal(err, nil) } }