package main import ( "context" "log/slog" "os" "connectrpc.com/connect" "connectrpc.com/validate" sdb "git.kocoder.xyz/vt/service-base/database" "git.kocoder.xyz/vt/service-base/middleware" "git.kocoder.xyz/vt/service-base/rpc" "git.kocoder.xyz/vt/service-base/server" "git.kocoder.xyz/vt/service-base/telemetry" "git.kocoder.xyz/vt/shortener/internal/config" "git.kocoder.xyz/vt/shortener/internal/database" "git.kocoder.xyz/vt/shortener/internal/proto/shorten/v1/shortenv1connect" "git.kocoder.xyz/vt/shortener/internal/service" _ "github.com/lib/pq" ) func main() { // Fallback logger for early startup errors telemetry.SetupFallbackLogger() conf := config.Read() ctx := context.Background() shutdown, err := telemetry.Init(ctx, conf.OTLP_ENDPOINT, "shortener-server") if err != nil { slog.Error("Failed to initialize telemetry", slog.String("err", err.Error())) } defer func() { if err := shutdown(ctx); err != nil { slog.Error("Error shutting down telemetry", slog.String("err", err.Error())) } }() // Connect to DB and wrap with otelsql for database tracing db, err := sdb.OpenPostgres(conf.DB_URL) if err != nil { slog.Error("failed to connect to database", slog.String("err", err.Error())) os.Exit(1) } defer db.Close() dbQueries := database.New(db) srv := service.NewServer(conf, dbQueries) mux := rpc.NewServeMux() path, handler := shortenv1connect.NewShortenServiceHandler( service.NewShortenerService(conf, dbQueries), connect.WithInterceptors(validate.NewInterceptor()), ) mux.RegisterConnect(shortenv1connect.ShortenServiceName, path, handler) mux.Handle("/", srv) mux.MountReflection() c := middleware.NewCORS(conf.ALLOWED_ORIGINS) corsMux := c.Handler(mux) // Start server with OpenTelemetry tracing, HTTP/1.1 & HTTP/2 (h2c) support if err := server.ListenAndServeH2C(conf.LISTEN_ON, corsMux, "shortener-server"); err != nil { slog.Error("Server failed", slog.String("err", err.Error())) } }