feat: string-unpack api
This commit is contained in:
24
cmd/api/config.go
Normal file
24
cmd/api/config.go
Normal file
@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"time"
|
||||
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
DSN string `envconfig:"DSN" default:"postgresql://postgres:postgres@postgres:5432/postgres?sslmode=disable"`
|
||||
ReconnectTimeout time.Duration `envconfig:"RECONNECT_TIMEOUT" default:"2s"`
|
||||
}
|
||||
|
||||
func (c *Config) Parse() error {
|
||||
flag.StringVar(&c.DSN, "DSN", "", "postgresql DSN")
|
||||
flag.Parse()
|
||||
|
||||
if err := envconfig.Process("", c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
113
cmd/api/main.go
Normal file
113
cmd/api/main.go
Normal file
@ -0,0 +1,113 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
|
||||
stringunpack "git.grachevko.ru/grachevko/h/string-unpack"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
collector "github.com/prometheus/client_golang/prometheus/collectors/version"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger, _ := zap.NewProduction()
|
||||
defer func(logger *zap.Logger) {
|
||||
_ = logger.Sync()
|
||||
}(logger) // flushes buffer, if any
|
||||
|
||||
cfg := Config{}
|
||||
if err := cfg.Parse(); err != nil {
|
||||
logger.Fatal("config parse", zap.Error(err))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
ctx, stop := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
var metricServer *http.Server
|
||||
{ // Metrics
|
||||
prometheus.MustRegister(collector.NewCollector("unpack"))
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
metricServer = &http.Server{
|
||||
Handler: mux,
|
||||
Addr: ":8089",
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := metricServer.ListenAndServe(); err != nil {
|
||||
logger.Error("metric server failed", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
} // Metrics
|
||||
|
||||
pgconn:
|
||||
conn, err := pgx.Connect(ctx, cfg.DSN)
|
||||
if err != nil {
|
||||
logger.Error("pgx", zap.Error(err))
|
||||
|
||||
logger.Info("Wait before reconnect", zap.Duration("after", cfg.ReconnectTimeout))
|
||||
<-time.After(cfg.ReconnectTimeout)
|
||||
logger.Info("Retrying connection")
|
||||
goto pgconn
|
||||
}
|
||||
defer func(conn *pgx.Conn, ctx context.Context) {
|
||||
if err = conn.Close(ctx); err != nil {
|
||||
logger.Error("pgx close", zap.Error(err))
|
||||
}
|
||||
}(conn, ctx)
|
||||
|
||||
var httpServer *http.Server
|
||||
{ // Http
|
||||
r := gin.Default()
|
||||
|
||||
stringunpack.Setup(ctx, logger, r.Group("unpack"), conn)
|
||||
|
||||
httpServer = &http.Server{
|
||||
Addr: ":8080",
|
||||
Handler: r,
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logger.Error("http server failed", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
} // Http
|
||||
|
||||
// Listen for the interrupt signal.
|
||||
<-ctx.Done()
|
||||
|
||||
{ // Graceful shutdown
|
||||
// Restore default behavior on the interrupt signal and notify user of shutdown.
|
||||
stop()
|
||||
logger.Info("shutting down gracefully, press Ctrl+C again to force")
|
||||
|
||||
// The context is used to inform the server it has 5 seconds to finish
|
||||
// the request it is currently handling
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
g.Go(func() error { return metricServer.Shutdown(ctx) })
|
||||
g.Go(func() error { return httpServer.Shutdown(ctx) })
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
logger.Error("graceful shutdown failed", zap.Error(err))
|
||||
}
|
||||
} // Graceful shutdown
|
||||
|
||||
logger.Info("Server exiting")
|
||||
}
|
Reference in New Issue
Block a user