diff --git a/cmd/cgnolink/main.go b/cmd/cgnolink/main.go index 562aa2a..4a72941 100644 --- a/cmd/cgnolink/main.go +++ b/cmd/cgnolink/main.go @@ -14,8 +14,7 @@ func main() { conf := cgnolink.NewConfig() - pool := database.Pool(conf) - database.Migrate(pool) + pool := database.InitPool(conf) server := appserver.NewServer(conf, pool) @@ -23,5 +22,5 @@ func main() { } func configureLogger() { - log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: "2006-01-02 15:04:05"}) } diff --git a/database/database.go b/database/database.go index a6314fb..5796452 100644 --- a/database/database.go +++ b/database/database.go @@ -6,16 +6,34 @@ import ( "fmt" "github.com/jackc/pgx/v4/pgxpool" "github.com/knadh/koanf" + "github.com/rs/zerolog/log" + "time" ) -func Pool(config *koanf.Koanf) *pgxpool.Pool { - connStr, err := getConnectionString(config) - if err != nil { +func InitPool(config *koanf.Koanf) *pgxpool.Pool { + pool := NewPool(config) + + if err := runMigrations(pool); err != nil { + log.Fatal().Err(err).Msg("Couldn't apply migrations") panic(err) } - pool, err := pgxpool.Connect(context.Background(), connStr) + return pool +} + +func NewPool(config *koanf.Koanf) *pgxpool.Pool { + connStr, err := getConnectionString(config) if err != nil { + log.Fatal().Err(err).Msg("Couldn't construct DB connection string") + panic(err) + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + pool, err := pgxpool.Connect(ctx, connStr) + if err != nil { + log.Fatal().Err(err).Msg("Couldn't connect to DB") panic(err) } diff --git a/database/migrate.go b/database/migrate.go index 4223e4a..44f96be 100644 --- a/database/migrate.go +++ b/database/migrate.go @@ -4,24 +4,30 @@ import ( "context" "github.com/jackc/pgx/v4/pgxpool" "github.com/jackc/tern/migrate" + "time" ) -func Migrate(pool *pgxpool.Pool) { - conn, err := pool.Acquire(context.Background()) +func runMigrations(pool *pgxpool.Pool) (err error) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + conn, err := pool.Acquire(ctx) if err != nil { - panic(err) + return } - migrator, err := migrate.NewMigrator(context.Background(), conn.Conn(), "schema_version") + migrator, err := migrate.NewMigrator(ctx, conn.Conn(), "schema_version") if err != nil { - panic(err) + return } if err = migrator.LoadMigrations("./migrations"); err != nil { - panic(err) + return } - if err = migrator.Migrate(context.Background()); err != nil { - panic(err) + if err = migrator.Migrate(ctx); err != nil { + return } + + return } diff --git a/database/util.go b/database/util.go new file mode 100644 index 0000000..9d31c75 --- /dev/null +++ b/database/util.go @@ -0,0 +1,15 @@ +package database + +import ( + "github.com/jackc/pgx/v4/pgxpool" + "github.com/rs/zerolog/log" +) + +func LogPoolState(pool *pgxpool.Pool, message string) { + stat := pool.Stat() + log.Info(). + Int32("acquired_conns", stat.AcquiredConns()). + Int32("idle_conns", stat.IdleConns()). + Int32("total_conns", stat.TotalConns()). + Msg(message) +} diff --git a/link/repository.go b/link/repository.go index b31b9c3..8751b3a 100644 --- a/link/repository.go +++ b/link/repository.go @@ -1,6 +1,7 @@ package link import ( + "cgnolink/database" "context" "errors" "github.com/jackc/pgtype" @@ -15,7 +16,7 @@ const defaultContextTimeout = 10 * time.Second type Repository interface { Save(link *Link) error FindById(id string) (*Link, error) - FindAll(limit int, offset int) (Links, error) + GetAll(limit int, offset int) (Links, error) Update(link *Link) error DeleteById(id string) error } @@ -37,6 +38,7 @@ func (r *PgRepository) Save(link *Link) error { VALUES ($1, $2, $3, $4::timestamp) ` + database.LogPoolState(r.pool, "Saving link") _, err := r.pool.Exec(ctx, sql, link.Id, link.Name, link.RedirectURL.String(), link.CreationTime.Format("2006-01-02 15:04:05")) if err != nil { return err @@ -55,6 +57,7 @@ func (r *PgRepository) FindById(id string) (*Link, error) { WHERE id = $1 ` + database.LogPoolState(r.pool, "Finding link by ID") entity, err := mapRowToEntity(r.pool.QueryRow(ctx, sql, id)) if err != nil { if errors.Is(err, pgx.ErrNoRows) { @@ -67,7 +70,7 @@ func (r *PgRepository) FindById(id string) (*Link, error) { return entity, nil } -func (r *PgRepository) FindAll(limit int, offset int) (Links, error) { +func (r *PgRepository) GetAll(limit int, offset int) (Links, error) { if limit < 0 { return nil, errors.New("limit can't be negative") } @@ -85,6 +88,7 @@ func (r *PgRepository) FindAll(limit int, offset int) (Links, error) { OFFSET $2 ` + database.LogPoolState(r.pool, "Getting all links") rows, err := r.pool.Query(ctx, sql, limit, offset) if err != nil { return nil, err @@ -122,6 +126,7 @@ func (r *PgRepository) Update(link *Link) error { WHERE id = $3 ` + database.LogPoolState(r.pool, "Updating link") _, err := r.pool.Exec(ctx, sql, link.Name, link.RedirectURL.String(), link.Id) if err != nil { return err @@ -138,6 +143,7 @@ func (r *PgRepository) DeleteById(id string) error { DELETE FROM links WHERE id = $1 ` + database.LogPoolState(r.pool, "Deleting link") _, err := r.pool.Exec(ctx, sql, id) if err != nil { return err diff --git a/link/service.go b/link/service.go index 241332c..b35d7d5 100644 --- a/link/service.go +++ b/link/service.go @@ -64,7 +64,7 @@ func (s *PgService) GetById(id string) (*Link, error) { } func (s *PgService) GetAll(limit int, offset int) (Links, error) { - links, err := s.rep.FindAll(limit, offset) + links, err := s.rep.GetAll(limit, offset) if err != nil { return nil, apperrors.UnknownError{Err: err} } diff --git a/server/middleware.go b/server/middleware.go index 04a7824..82c2901 100644 --- a/server/middleware.go +++ b/server/middleware.go @@ -26,7 +26,7 @@ func Logger() echo.MiddlewareFunc { Str("user_agent", req.UserAgent()). Int("status", res.Status). Str("latency", stop.Sub(start).String()). - Send() + Msg("Request") return }