feat: ensure anime row exists before saving progress
This commit is contained in:
@@ -89,6 +89,8 @@ type EpisodeData struct {
|
|||||||
|
|
||||||
type PlaybackRepository interface {
|
type PlaybackRepository interface {
|
||||||
InTx(ctx context.Context, fn func(ctx context.Context, repo PlaybackRepository) error) error
|
InTx(ctx context.Context, fn func(ctx context.Context, repo PlaybackRepository) error) error
|
||||||
|
UpsertAnime(ctx context.Context, params db.UpsertAnimeParams) (db.Anime, error)
|
||||||
|
GetAnime(ctx context.Context, id int64) (db.Anime, error)
|
||||||
GetWatchListEntry(ctx context.Context, params db.GetWatchListEntryParams) (db.WatchListEntry, error)
|
GetWatchListEntry(ctx context.Context, params db.GetWatchListEntryParams) (db.WatchListEntry, error)
|
||||||
GetContinueWatchingEntry(ctx context.Context, params db.GetContinueWatchingEntryParams) (db.ContinueWatchingEntry, error)
|
GetContinueWatchingEntry(ctx context.Context, params db.GetContinueWatchingEntryParams) (db.ContinueWatchingEntry, error)
|
||||||
SaveWatchProgress(ctx context.Context, params db.SaveWatchProgressParams) error
|
SaveWatchProgress(ctx context.Context, params db.SaveWatchProgressParams) error
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@@ -108,13 +109,22 @@ func (s *playbackService) CompleteAnime(ctx context.Context, userID string, anim
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *playbackService) SaveProgress(ctx context.Context, userID string, animeID int64, episode int, timeSeconds float64) error {
|
func (s *playbackService) SaveProgress(ctx context.Context, userID string, animeID int64, episode int, timeSeconds float64) error {
|
||||||
_, err := s.repo.UpsertContinueWatchingEntry(ctx, db.UpsertContinueWatchingEntryParams{
|
err := s.repo.InTx(ctx, func(txCtx context.Context, repo domain.PlaybackRepository) error {
|
||||||
ID: uuid.New().String(),
|
if _, err := repo.GetAnime(txCtx, animeID); err != nil {
|
||||||
UserID: userID,
|
if _, err := repo.UpsertAnime(txCtx, minimalAnimeParams(animeID)); err != nil {
|
||||||
AnimeID: animeID,
|
return err
|
||||||
CurrentEpisode: sql.NullInt64{Int64: int64(episode), Valid: true},
|
}
|
||||||
CurrentTimeSeconds: timeSeconds,
|
}
|
||||||
DurationSeconds: sql.NullFloat64{Valid: false},
|
|
||||||
|
_, err := repo.UpsertContinueWatchingEntry(txCtx, db.UpsertContinueWatchingEntryParams{
|
||||||
|
ID: uuid.New().String(),
|
||||||
|
UserID: userID,
|
||||||
|
AnimeID: animeID,
|
||||||
|
CurrentEpisode: sql.NullInt64{Int64: int64(episode), Valid: true},
|
||||||
|
CurrentTimeSeconds: timeSeconds,
|
||||||
|
DurationSeconds: sql.NullFloat64{Valid: false},
|
||||||
|
})
|
||||||
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -148,3 +158,36 @@ func (s *playbackService) SaveProgress(ctx context.Context, userID string, anime
|
|||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *playbackService) ensureAnimeRow(ctx context.Context, anime domain.Anime) {
|
||||||
|
if _, err := s.repo.GetAnime(ctx, int64(anime.MalID)); err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, _ = s.repo.UpsertAnime(ctx, animeParams(anime))
|
||||||
|
}
|
||||||
|
|
||||||
|
func animeParams(anime domain.Anime) db.UpsertAnimeParams {
|
||||||
|
durationSeconds := anime.DurationSeconds()
|
||||||
|
duration := sql.NullFloat64{Valid: durationSeconds > 0}
|
||||||
|
if duration.Valid {
|
||||||
|
duration.Float64 = durationSeconds
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.UpsertAnimeParams{
|
||||||
|
ID: int64(anime.MalID),
|
||||||
|
TitleOriginal: anime.Title,
|
||||||
|
TitleEnglish: sql.NullString{String: anime.TitleEnglish, Valid: anime.TitleEnglish != ""},
|
||||||
|
TitleJapanese: sql.NullString{String: anime.TitleJapanese, Valid: anime.TitleJapanese != ""},
|
||||||
|
ImageUrl: anime.ImageURL(),
|
||||||
|
Airing: sql.NullBool{Bool: anime.Airing, Valid: true},
|
||||||
|
DurationSeconds: duration,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func minimalAnimeParams(animeID int64) db.UpsertAnimeParams {
|
||||||
|
return db.UpsertAnimeParams{
|
||||||
|
ID: animeID,
|
||||||
|
TitleOriginal: fmt.Sprintf("Anime %d", animeID),
|
||||||
|
Airing: sql.NullBool{Valid: false},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ func (r *playbackRepository) InTx(ctx context.Context, fn func(ctx context.Conte
|
|||||||
}, fn)
|
}, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *playbackRepository) UpsertAnime(ctx context.Context, params db.UpsertAnimeParams) (db.Anime, error) {
|
||||||
|
return r.queries.UpsertAnime(ctx, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *playbackRepository) GetAnime(ctx context.Context, id int64) (db.Anime, error) {
|
||||||
|
return r.queries.GetAnime(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *playbackRepository) GetWatchListEntry(ctx context.Context, params db.GetWatchListEntryParams) (db.WatchListEntry, error) {
|
func (r *playbackRepository) GetWatchListEntry(ctx context.Context, params db.GetWatchListEntryParams) (db.WatchListEntry, error) {
|
||||||
return r.queries.GetWatchListEntry(ctx, params)
|
return r.queries.GetWatchListEntry(ctx, params)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
|
|||||||
}
|
}
|
||||||
|
|
||||||
animeData := domain.Anime{Anime: anime}
|
animeData := domain.Anime{Anime: anime}
|
||||||
|
s.ensureAnimeRow(ctx, animeData)
|
||||||
searchTitles := buildSearchTitles(animeData, titleCandidates)
|
searchTitles := buildSearchTitles(animeData, titleCandidates)
|
||||||
canonicalEpisodes, err := s.episodes.GetCanonicalEpisodes(ctx, animeData, false)
|
canonicalEpisodes, err := s.episodes.GetCanonicalEpisodes(ctx, animeData, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user