60 lines
1.8 KiB
Go
60 lines
1.8 KiB
Go
package repositories
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"thamanyah/discovery/internal/models"
|
|
|
|
"github.com/lib/pq"
|
|
)
|
|
|
|
type VideoRepository struct {
|
|
SQLDB *sql.DB
|
|
}
|
|
|
|
var VideoRepo VideoRepository
|
|
|
|
// SaveVideo records an announced video, replacing what the catalogue already
|
|
// held for that id.
|
|
//
|
|
// The upsert is what makes the consumer safe to retry: the catalogue topic
|
|
// delivers at-least-once, so the same announcement can arrive twice, and a
|
|
// plain INSERT would fail the second time on the primary key. Re-announcing a
|
|
// video is also how it is corrected — a later announcement wins, which is why
|
|
// every column is overwritten rather than merged.
|
|
func (svc VideoRepository) SaveVideo(ctx context.Context, v models.Video) error {
|
|
_, err := svc.SQLDB.ExecContext(ctx, `
|
|
INSERT INTO videos (id, title, playback_url, categories)
|
|
VALUES ($1, $2, $3, $4)
|
|
ON CONFLICT (id) DO UPDATE
|
|
SET title = EXCLUDED.title,
|
|
playback_url = EXCLUDED.playback_url,
|
|
categories = EXCLUDED.categories,
|
|
updated_at = now()
|
|
`, v.ID, v.Title, v.PlaybackURL, pq.Array(v.Categories))
|
|
return err
|
|
}
|
|
|
|
// GetVideoByID reads the catalogue's copy of one video. It returns
|
|
// ErrVideoNotFound when the catalogue has not heard about it — which, for a
|
|
// video cms has only just made ready, is a matter of timing rather than a
|
|
// mistake.
|
|
func (svc VideoRepository) GetVideoByID(ctx context.Context, id string) (models.Video, error) {
|
|
var v models.Video
|
|
|
|
err := svc.SQLDB.QueryRowContext(ctx, `
|
|
SELECT id, title, playback_url, categories, created_at, updated_at
|
|
FROM videos
|
|
WHERE id = $1
|
|
`, id).Scan(&v.ID, &v.Title, &v.PlaybackURL, pq.Array(&v.Categories), &v.CreatedAt, &v.UpdatedAt)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return models.Video{}, ErrVideoNotFound
|
|
}
|
|
if err != nil {
|
|
return models.Video{}, err
|
|
}
|
|
|
|
return v, nil
|
|
}
|