refactor: commands
This commit is contained in:
parent
3a903741f5
commit
5b68c58797
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
|
@ -78,11 +79,16 @@ type bundDBConfig struct {
|
|||
writeTimeout time.Duration
|
||||
}
|
||||
|
||||
const dbPingTimeout = 10 * time.Second
|
||||
|
||||
func newBunDB(cfg bundDBConfig) (*bun.DB, error) {
|
||||
db := bun.NewDB(newSQLDB(cfg), pgdialect.New())
|
||||
|
||||
if err := pingDB(db); err != nil {
|
||||
return nil, err
|
||||
ctx, cancel := context.WithTimeout(context.Background(), dbPingTimeout)
|
||||
defer cancel()
|
||||
|
||||
if err := db.PingContext(ctx); err != nil {
|
||||
return nil, fmt.Errorf("couldn't ping db: %w", err)
|
||||
}
|
||||
|
||||
return db, nil
|
||||
|
@ -100,15 +106,11 @@ func newSQLDB(cfg bundDBConfig) *sql.DB {
|
|||
return db
|
||||
}
|
||||
|
||||
const dbPingTimeout = 10 * time.Second
|
||||
|
||||
func pingDB(db *bun.DB) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), dbPingTimeout)
|
||||
defer cancel()
|
||||
|
||||
if err := db.PingContext(ctx); err != nil {
|
||||
return fmt.Errorf("couldn't ping db: %w", err)
|
||||
func closeBunDB(db *bun.DB, logger *slog.Logger) {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", db.Stats().OpenConnections))
|
||||
if dbCloseErr := db.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -342,22 +342,12 @@ func runConsumer(c *cli.Context, name string, registerHandlers registerConsumerH
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", bunDB.Stats().OpenConnections))
|
||||
if dbCloseErr := bunDB.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
}()
|
||||
defer closeBunDB(bunDB, logger)
|
||||
|
||||
healthObserver := healthfile.LiveObserver(health.New(), "/tmp/live")
|
||||
defer func() {
|
||||
logger.Debug("closing health observer...")
|
||||
if closeErr := healthObserver.Close(); closeErr != nil {
|
||||
logger.Warn("couldn't close health observer", slog.Any("error", closeErr))
|
||||
} else {
|
||||
logger.Debug("health observer closed")
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
@ -48,14 +49,7 @@ var cmdDB = &cli.Command{
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", bunDB.Stats().OpenConnections))
|
||||
if dbCloseErr := bunDB.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
}()
|
||||
defer closeBunDB(bunDB, logger)
|
||||
|
||||
migrator := migrations.NewMigrator(bunDB)
|
||||
|
||||
|
@ -63,19 +57,13 @@ var cmdDB = &cli.Command{
|
|||
return fmt.Errorf("couldn't init migrator: %w", err)
|
||||
}
|
||||
|
||||
// we use c.Context instead of shutdownSignalCtx here because we still want to unlock the db
|
||||
// even after one of the shutdown signals has been received
|
||||
defer unlockMigrations(c.Context, migrator, logger)
|
||||
|
||||
if err = migrator.Lock(shutdownSignalCtx); err != nil {
|
||||
return fmt.Errorf("couldn't lock db: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("unlocking db...")
|
||||
// we use c.Context instead of shutdownSignalCtx here because we still want to unlock the db
|
||||
// even after one of the shutdown signals has been received
|
||||
if unlockErr := migrator.Unlock(c.Context); unlockErr != nil {
|
||||
logger.Warn("couldn't unlock db", slog.Any("error", unlockErr))
|
||||
} else {
|
||||
logger.Debug("db unlocked")
|
||||
}
|
||||
}()
|
||||
|
||||
group, err := migrator.Migrate(shutdownSignalCtx)
|
||||
if err != nil {
|
||||
|
@ -110,30 +98,17 @@ var cmdDB = &cli.Command{
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", bunDB.Stats().OpenConnections))
|
||||
if dbCloseErr := bunDB.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
}()
|
||||
defer closeBunDB(bunDB, logger)
|
||||
|
||||
migrator := migrations.NewMigrator(bunDB)
|
||||
|
||||
// we use c.Context instead of shutdownSignalCtx here because we still want to unlock the db
|
||||
// even after one of the shutdown signals has been received
|
||||
defer unlockMigrations(c.Context, migrator, logger)
|
||||
|
||||
if err = migrator.Lock(shutdownSignalCtx); err != nil {
|
||||
return fmt.Errorf("couldn't lock db: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("unlocking db...")
|
||||
// we use c.Context instead of shutdownSignalCtx here because we still want to unlock the db
|
||||
// even after one of the shutdown signals has been received
|
||||
if unlockErr := migrator.Unlock(c.Context); unlockErr != nil {
|
||||
logger.Warn("couldn't unlock db", slog.Any("error", unlockErr))
|
||||
} else {
|
||||
logger.Debug("db unlocked")
|
||||
}
|
||||
}()
|
||||
|
||||
group, err := migrator.Rollback(shutdownSignalCtx)
|
||||
if err != nil {
|
||||
|
@ -212,3 +187,12 @@ var cmdDB = &cli.Command{
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
func unlockMigrations(ctx context.Context, migrator *migrate.Migrator, logger *slog.Logger) {
|
||||
logger.Debug("unlocking db...")
|
||||
if unlockErr := migrator.Unlock(ctx); unlockErr != nil {
|
||||
logger.Warn("couldn't unlock db", slog.Any("error", unlockErr))
|
||||
} else {
|
||||
logger.Debug("db unlocked")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,14 +51,7 @@ var (
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", bunDB.Stats().OpenConnections))
|
||||
if dbCloseErr := bunDB.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
}()
|
||||
defer closeBunDB(bunDB, logger)
|
||||
|
||||
serverPublisher := adapter.NewServerWatermillPublisher(
|
||||
publisher,
|
||||
|
@ -114,14 +107,7 @@ var (
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", bunDB.Stats().OpenConnections))
|
||||
if dbCloseErr := bunDB.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
}()
|
||||
defer closeBunDB(bunDB, logger)
|
||||
|
||||
ennoblementPublisher := adapter.NewEnnoblementWatermillPublisher(
|
||||
publisher,
|
||||
|
@ -183,14 +169,7 @@ var (
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", bunDB.Stats().OpenConnections))
|
||||
if dbCloseErr := bunDB.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
}()
|
||||
defer closeBunDB(bunDB, logger)
|
||||
|
||||
tribeSnapshotPublisher := adapter.NewSnapshotWatermillPublisher(
|
||||
publisher,
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.dwysokinski.me/Kichiyaki/chiclientip"
|
||||
"gitea.dwysokinski.me/twhelp/corev3/internal/adapter"
|
||||
"gitea.dwysokinski.me/twhelp/corev3/internal/app"
|
||||
"gitea.dwysokinski.me/twhelp/corev3/internal/chislog"
|
||||
|
@ -18,6 +18,7 @@ import (
|
|||
"gitea.dwysokinski.me/twhelp/corev3/internal/port"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
"github.com/realclientip/realclientip-go"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
@ -27,6 +28,12 @@ var (
|
|||
EnvVars: []string{"API_PORT"},
|
||||
Value: 9234, //nolint:gomnd
|
||||
}
|
||||
apiServerHandlerTimeoutFlag = &cli.DurationFlag{
|
||||
Name: "api.handlerTimeout",
|
||||
EnvVars: []string{"API_HANDLER_TIMEOUT"},
|
||||
Value: 5 * time.Second, //nolint:gomnd,
|
||||
Usage: "https://pkg.go.dev/net/http#TimeoutHandler",
|
||||
}
|
||||
apiServerReadTimeoutFlag = &cli.DurationFlag{
|
||||
Name: "api.readTimeout",
|
||||
EnvVars: []string{"API_READ_TIMEOUT"},
|
||||
|
@ -68,6 +75,7 @@ var (
|
|||
}
|
||||
apiServerFlags = []cli.Flag{
|
||||
apiServerPortFlag,
|
||||
apiServerHandlerTimeoutFlag,
|
||||
apiServerReadTimeoutFlag,
|
||||
apiServerReadHeaderTimeoutFlag,
|
||||
apiServerWriteTimeoutFlag,
|
||||
|
@ -95,14 +103,7 @@ var cmdServe = &cli.Command{
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
logger.Debug("closing db connections...", slog.Int("db.openConnections", bunDB.Stats().OpenConnections))
|
||||
if dbCloseErr := bunDB.Close(); dbCloseErr != nil {
|
||||
logger.Warn("couldn't close db connections", slog.Any("error", dbCloseErr))
|
||||
} else {
|
||||
logger.Debug("db connections closed")
|
||||
}
|
||||
}()
|
||||
defer closeBunDB(bunDB, logger)
|
||||
|
||||
// adapters
|
||||
versionRepo := adapter.NewVersionBunRepository(bunDB)
|
||||
|
@ -139,20 +140,25 @@ var cmdServe = &cli.Command{
|
|||
return oapiCfgErr
|
||||
}
|
||||
|
||||
r.Use(newAPIMiddlewares(logger)...)
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(middleware.Recoverer)
|
||||
r.Mount(metaBasePath, port.NewMetaHTTPHandler(h))
|
||||
})
|
||||
|
||||
r.Mount(metaBasePath, port.NewMetaHTTPHandler(h))
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(newAPIMiddlewares(c, logger)...)
|
||||
|
||||
r.Mount(apiBasePath, port.NewAPIHTTPHandler(
|
||||
versionSvc,
|
||||
serverSvc,
|
||||
tribeSvc,
|
||||
playerSvc,
|
||||
villageSvc,
|
||||
ennoblementSvc,
|
||||
tribeChangeSvc,
|
||||
port.WithOpenAPIConfig(oapiCfg),
|
||||
))
|
||||
r.Mount(apiBasePath, port.NewAPIHTTPHandler(
|
||||
versionSvc,
|
||||
serverSvc,
|
||||
tribeSvc,
|
||||
playerSvc,
|
||||
villageSvc,
|
||||
ennoblementSvc,
|
||||
tribeChangeSvc,
|
||||
port.WithOpenAPIConfig(oapiCfg),
|
||||
))
|
||||
})
|
||||
|
||||
return nil
|
||||
},
|
||||
|
@ -213,11 +219,21 @@ func newOpenAPIConfigFromFlags(c *cli.Context) (port.OpenAPIConfig, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func newAPIMiddlewares(logger *slog.Logger) chi.Middlewares {
|
||||
func newAPIMiddlewares(c *cli.Context, logger *slog.Logger) chi.Middlewares {
|
||||
return chi.Middlewares{
|
||||
chislog.Logger(logger, chislog.WithFilter(func(r *http.Request) bool {
|
||||
return !strings.HasPrefix(r.URL.Path, metaBasePath)
|
||||
chiclientip.ClientIP(
|
||||
realclientip.NewChainStrategy(
|
||||
realclientip.Must(realclientip.NewRightmostNonPrivateStrategy("X-Forwarded-For")),
|
||||
realclientip.RemoteAddrStrategy{},
|
||||
),
|
||||
),
|
||||
chislog.Logger(logger, chislog.WithIPExtractor(func(r *http.Request) string {
|
||||
clientIP, _ := chiclientip.ClientIPFromContext(r.Context())
|
||||
return clientIP
|
||||
})),
|
||||
middleware.Recoverer,
|
||||
func(next http.Handler) http.Handler {
|
||||
return http.TimeoutHandler(next, c.Duration(apiServerHandlerTimeoutFlag.Name), "Timeout")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -3,6 +3,7 @@ module gitea.dwysokinski.me/twhelp/corev3
|
|||
go 1.22
|
||||
|
||||
require (
|
||||
gitea.dwysokinski.me/Kichiyaki/chiclientip v0.1.0
|
||||
github.com/ThreeDotsLabs/watermill v1.3.5
|
||||
github.com/ThreeDotsLabs/watermill-amqp/v2 v2.1.1
|
||||
github.com/brianvoe/gofakeit/v7 v7.0.2
|
||||
|
@ -16,6 +17,7 @@ require (
|
|||
github.com/google/uuid v1.6.0
|
||||
github.com/oapi-codegen/runtime v1.1.1
|
||||
github.com/ory/dockertest/v3 v3.10.0
|
||||
github.com/realclientip/realclientip-go v1.0.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/uptrace/bun v1.1.17
|
||||
github.com/uptrace/bun/dbfixture v1.1.17
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1,3 +1,5 @@
|
|||
gitea.dwysokinski.me/Kichiyaki/chiclientip v0.1.0 h1:5e5Uh+Am1PBSW1cYsbAuEhrGSZHxP7JfNeNa+FXbQ/4=
|
||||
gitea.dwysokinski.me/Kichiyaki/chiclientip v0.1.0/go.mod h1:zMTruKo30+qM3dG4yhAPOxK/5hUEBhKiDSrV0VRlZnI=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
|
@ -155,6 +157,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rabbitmq/amqp091-go v1.9.0 h1:qrQtyzB4H8BQgEuJwhmVQqVHB9O4+MNDJCCAcpc3Aoo=
|
||||
github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc=
|
||||
github.com/realclientip/realclientip-go v1.0.0 h1:+yPxeC0mEaJzq1BfCt2h4BxlyrvIIBzR6suDc3BEF1U=
|
||||
github.com/realclientip/realclientip-go v1.0.0/go.mod h1:CXnUdVwFRcXFJIRb/dTYqbT7ud48+Pi2pFm80bxDmcI=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
|
|
Loading…
Reference in New Issue
Block a user