Update link repository

Add timeout to contexts.
Add method for retrieving all links.
This commit is contained in:
Andrey Chervyakov 2021-03-13 17:15:47 +06:00
parent 99be0824cd
commit 2eea43d973

View file

@ -7,11 +7,13 @@ import (
"github.com/jackc/pgx/v4" "github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool" "github.com/jackc/pgx/v4/pgxpool"
"net/url" "net/url"
"time"
) )
type Repository interface { type Repository interface {
Save(link *Link) error Save(link *Link) error
FindById(id string) (*Link, error) FindById(id string) (*Link, error)
FindAll(limit int, offset int) ([]Link, error)
DeleteById(id string) error DeleteById(id string) error
} }
@ -20,7 +22,9 @@ type PgRepository struct {
} }
func (r *PgRepository) Save(link *Link) error { func (r *PgRepository) Save(link *Link) error {
ctx := context.Background() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
tx, err := r.pool.Begin(ctx) tx, err := r.pool.Begin(ctx)
if err != nil { if err != nil {
return err return err
@ -45,7 +49,9 @@ func (r *PgRepository) Save(link *Link) error {
} }
func (r *PgRepository) FindById(id string) (*Link, error) { func (r *PgRepository) FindById(id string) (*Link, error) {
ctx := context.Background() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
tx, err := r.pool.Begin(ctx) tx, err := r.pool.Begin(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
@ -74,8 +80,63 @@ func (r *PgRepository) FindById(id string) (*Link, error) {
return entity, nil return entity, nil
} }
func (r *PgRepository) FindAll(limit int, offset int) ([]Link, error) {
if limit < 0 {
return nil, errors.New("limit can't be negative")
}
if offset < 0 {
return nil, errors.New("offset can't be negative")
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
tx, err := r.pool.Begin(ctx)
if err != nil {
return nil, err
}
sql := `
SELECT id, name, redirect_url, creation_time
FROM links
LIMIT $1
OFFSET $2
`
rows, err := tx.Query(ctx, sql, limit, offset)
if err != nil {
_ = tx.Rollback(ctx)
return nil, err
}
defer rows.Close()
links := make([]Link, 0)
for rows.Next() {
link, err := mapRowToEntity(rows)
if err != nil {
_ = tx.Rollback(ctx)
return nil, err
}
links = append(links, *link)
}
if err = rows.Err(); err != nil {
_ = tx.Rollback(ctx)
return nil, err
}
if err = tx.Commit(ctx); err != nil {
return nil, err
}
return links, nil
}
func (r *PgRepository) DeleteById(id string) error { func (r *PgRepository) DeleteById(id string) error {
ctx := context.Background() ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
tx, err := r.pool.Begin(ctx) tx, err := r.pool.Begin(ctx)
if err != nil { if err != nil {
return err return err
@ -98,14 +159,23 @@ func (r *PgRepository) DeleteById(id string) error {
return nil return nil
} }
func mapRowToEntity(r pgx.Row) (*Link, error) { func mapRowToEntity(r interface{}) (*Link, error) {
var entity Link var entity Link
var urlStr string var urlStr string
var t pgtype.Timestamp var t pgtype.Timestamp
if err := r.Scan(&entity.Id, &entity.Name, &urlStr, &t); err != nil { switch v := r.(type) {
case pgx.Row:
if err := v.Scan(&entity.Id, &entity.Name, &urlStr, &t); err != nil {
return nil, err return nil, err
} }
case pgx.Rows:
if err := v.Scan(&entity.Id, &entity.Name, &urlStr, &t); err != nil {
return nil, err
}
default:
return nil, errors.New("unsupported type")
}
u, err := url.Parse(urlStr) u, err := url.Parse(urlStr)
if err != nil { if err != nil {