package table import ( "fmt" "github.com/jmoiron/sqlx" "git.kplus.net.ua/yevhen/resource-scraper/types/model" ) // srrdbUpsert keys on the "release" primary key: a repeated search refreshes the // existing row instead of inserting a copy. synced_at is stamped with the same // run timestamp as created_at, so the two differ only on a release that was // already stored by an earlier run. const srrdbUpsert = ` INSERT INTO srrdb_releases ("release", date, has_nfo, has_srs, is_foreign, imdb_id, size, group_name, category, status, created_at) VALUES (:release, :date, :has_nfo, :has_srs, :is_foreign, :imdb_id, :size, :group_name, :category, :status, :created_at) ON CONFLICT("release") DO UPDATE SET date = excluded.date, has_nfo = excluded.has_nfo, has_srs = excluded.has_srs, is_foreign = excluded.is_foreign, imdb_id = excluded.imdb_id, size = excluded.size, group_name = excluded.group_name, category = excluded.category, status = COALESCE(excluded.status, status), synced_at = excluded.created_at` const srrdbUpsertDay = ` INSERT INTO srrdb_log ("day", "category", "found", "stored", "ignored", "run_at") VALUES (:day, :category, :found, :stored, :ignored, :run_at) ON CONFLICT("day", "category") DO UPDATE SET found = excluded.found, stored = excluded.stored, ignored = excluded.ignored, run_at = excluded.run_at` // UpsertAllSrrdb writes a whole set in one transaction: either every release // lands or none does, so a failure halfway through cannot leave a day half // harvested. func UpsertAllSrrdb(db *sqlx.DB, rows []model.SrrdbRelease) error { return UpsertAllSrrdbWithDay(db, rows, nil) } func UpsertAllSrrdbWithDay(db *sqlx.DB, rows []model.SrrdbRelease, day *model.SrrdbLog) error { if len(rows) == 0 && day == nil { return nil } tx, err := db.Beginx() if err != nil { return fmt.Errorf("begin srrdb transaction: %w", err) } for _, row := range rows { if _, err := tx.NamedExec(srrdbUpsert, &row); err != nil { // Rollback failure is not reported: the insert error is the one that // matters to the caller, and the transaction is gone either way. _ = tx.Rollback() return fmt.Errorf("upsert srrdb release %q: %w", row.Release, err) } } if day != nil { if _, err := tx.NamedExec(srrdbUpsertDay, day); err != nil { _ = tx.Rollback() return fmt.Errorf("upsert srrdb day %q/%q: %w", day.Day, day.Category, err) } } if err := tx.Commit(); err != nil { return fmt.Errorf("commit srrdb transaction: %w", err) } return nil }