Skip to content

Commit

Permalink
add transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
denpeshkov committed Feb 1, 2024
1 parent be5ce21 commit edec93c
Showing 1 changed file with 52 additions and 5 deletions.
57 changes: 52 additions & 5 deletions internal/postgres/movie.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ func (s *MovieService) GetMovie(ctx context.Context, id int64) (*greenlight.Movi
ctx, cancel := context.WithTimeout(ctx, s.db.opts.queryTimeout)
defer cancel()

tx, err := s.db.db.BeginTx(ctx, nil)
if err != nil {
return nil, fmt.Errorf("%s: %w", op, err)
}
defer tx.Rollback()

query := `SELECT id, title, release_date, runtime, genres, version FROM movies WHERE id = $1`
args := []any{id}
var m greenlight.Movie
if err := s.db.db.QueryRowContext(ctx, query, args...).Scan(&m.ID, &m.Title, &m.ReleaseDate, &m.Runtime, pq.Array(&m.Genres), &m.Version); err != nil {
if err := tx.QueryRowContext(ctx, query, args...).Scan(&m.ID, &m.Title, &m.ReleaseDate, &m.Runtime, pq.Array(&m.Genres), &m.Version); err != nil {
switch {
case errors.Is(err, sql.ErrNoRows):
return nil, greenlight.NewNotFoundError("Movie with id=%d is not found.", id)
Expand All @@ -44,6 +50,9 @@ func (s *MovieService) GetMovie(ctx context.Context, id int64) (*greenlight.Movi
}
}

if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("%s: %w", op, err)
}
return &m, nil
}

Expand All @@ -53,6 +62,12 @@ func (s *MovieService) GetMovies(ctx context.Context, filter greenlight.MovieFil
ctx, cancel := context.WithTimeout(ctx, s.db.opts.queryTimeout)
defer cancel()

tx, err := s.db.db.BeginTx(ctx, nil)
if err != nil {
return nil, fmt.Errorf("%s: %w", op, err)
}
defer tx.Rollback()

sortCol, sortDir := filter.Sort, "ASC"
if v, ok := strings.CutPrefix(sortCol, "-"); ok {
sortCol = v
Expand All @@ -65,7 +80,7 @@ func (s *MovieService) GetMovies(ctx context.Context, filter greenlight.MovieFil
WHERE (LOWER(title) = LOWER($1) OR $1 = '') AND (genres @> $2 OR $2 = '{}')
ORDER BY %s %s, id ASC
LIMIT $3 OFFSET $4`, sortCol, sortDir)
rs, err := s.db.db.QueryContext(ctx, query, filter.Title, pq.Array(filter.Genres), filter.PageSize, (filter.Page-1)*filter.PageSize)
rs, err := tx.QueryContext(ctx, query, filter.Title, pq.Array(filter.Genres), filter.PageSize, (filter.Page-1)*filter.PageSize)
if err != nil {
return nil, fmt.Errorf("%s: %w", op, err)
}
Expand All @@ -83,6 +98,9 @@ func (s *MovieService) GetMovies(ctx context.Context, filter greenlight.MovieFil
return nil, fmt.Errorf("%s: %w", op, err)
}

if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("%s: %w", op, err)
}
return movies, nil
}

Expand All @@ -92,16 +110,26 @@ func (s *MovieService) UpdateMovie(ctx context.Context, m *greenlight.Movie) err
ctx, cancel := context.WithTimeout(ctx, s.db.opts.queryTimeout)
defer cancel()

tx, err := s.db.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("%s: %w", op, err)
}
defer tx.Rollback()

query := `UPDATE movies SET (title, release_date, runtime, genres, version) = ($1, $2, $3, $4, version+1) WHERE id = $5 AND version = $6 RETURNING version`
args := []any{m.Title, m.ReleaseDate, m.Runtime, pq.Array(m.Genres), m.ID, m.Version}
if err := s.db.db.QueryRowContext(ctx, query, args...).Scan(&m.Version); err != nil {
if err := tx.QueryRowContext(ctx, query, args...).Scan(&m.Version); err != nil {
switch {
case errors.Is(err, sql.ErrNoRows):
return greenlight.NewConflictError("Conflicting change for the movie with id=%d", m.ID)
default:
return fmt.Errorf("%s: movie with id=%d: %w", op, m.ID, err)
}
}

if err := tx.Commit(); err != nil {
return fmt.Errorf("%s: %w", op, err)
}
return nil
}

Expand All @@ -111,9 +139,15 @@ func (s *MovieService) DeleteMovie(ctx context.Context, id int64) error {
ctx, cancel := context.WithTimeout(ctx, s.db.opts.queryTimeout)
defer cancel()

tx, err := s.db.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("%s: %w", op, err)
}
defer tx.Rollback()

query := `DELETE FROM movies where id = $1`
args := []any{id}
rs, err := s.db.db.ExecContext(ctx, query, args...)
rs, err := tx.ExecContext(ctx, query, args...)
if err != nil {
return fmt.Errorf("%s: movie with id=%d: %w", op, id, err)
}
Expand All @@ -126,6 +160,9 @@ func (s *MovieService) DeleteMovie(ctx context.Context, id int64) error {
return greenlight.NewNotFoundError("Movie with id=%d is not found.", id)
}

if err := tx.Commit(); err != nil {
return fmt.Errorf("%s: %w", op, err)
}
return nil
}

Expand All @@ -135,9 +172,19 @@ func (s *MovieService) CreateMovie(ctx context.Context, m *greenlight.Movie) err
ctx, cancel := context.WithTimeout(ctx, s.db.opts.queryTimeout)
defer cancel()

tx, err := s.db.db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("%s: %w", op, err)
}
defer tx.Rollback()

query := `INSERT INTO movies (title, release_date, runtime, genres) VALUES ($1, $2, $3, $4) RETURNING id, version`
args := []any{m.Title, m.ReleaseDate, m.Runtime, pq.Array(m.Genres)}
if err := s.db.db.QueryRowContext(ctx, query, args...).Scan(&m.ID, &m.Version); err != nil {
if err := tx.QueryRowContext(ctx, query, args...).Scan(&m.ID, &m.Version); err != nil {
return fmt.Errorf("%s: %w", op, err)
}

if err := tx.Commit(); err != nil {
return fmt.Errorf("%s: %w", op, err)
}
return nil
Expand Down

0 comments on commit edec93c

Please sign in to comment.