package repo import ( "context" "errors" "time" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) var ErrNotFound = errors.New("not found") type Episode struct { EpNum int `json:"ep_num"` EpTitle string `json:"ep_title"` SeasonName string `json:"season_name"` StartTime string `json:"start_time"` PlaybackLength string `json:"playback_length"` DateCreated time.Time `json:"date_created"` } type EpisodeRepository interface { GetCurrent(ctx context.Context) (Episode, error) SetCurrent(ctx context.Context, id int64, startHHMMSS string) error } type pgxEpisodeRepo struct { pool *pgxpool.Pool } func NewEpisodeRepo(pool *pgxpool.Pool) EpisodeRepository { return &pgxEpisodeRepo{pool: pool} } func (r *pgxEpisodeRepo) GetCurrent(ctx context.Context) (Episode, error) { const q = ` SELECT ep_num, ep_title, season_name, to_char(start_time, 'HH24:MI:SS') AS start_time, to_char(playback_length, 'HH24:MI:SS') AS playback_length, date_created FROM current WHERE current_ep = true ORDER BY id DESC LIMIT 1; ` var e Episode err := r.pool.QueryRow(ctx, q).Scan( &e.EpNum, &e.EpTitle, &e.SeasonName, &e.StartTime, &e.PlaybackLength, &e.DateCreated, ) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return Episode{}, ErrNotFound } return Episode{}, err } return e, nil } func (r *pgxEpisodeRepo) SetCurrent(ctx context.Context, id int64, startHHMMSS string) error { tx, err := r.pool.Begin(ctx) if err != nil { return err } defer func() { _ = tx.Rollback(ctx) }() // 1) clear any current episode flag if _, err := tx.Exec(ctx, `UPDATE current SET current_ep = false WHERE current_ep = true`); err != nil { return err } // 2) set start_time and current_ep for the id ct, err := tx.Exec(ctx, `UPDATE current SET start_time = $1::time, current_ep = true WHERE id = $2`, startHHMMSS, id) if err != nil { return err } if ct.RowsAffected() == 0 { return ErrNotFound } return tx.Commit(ctx) }