package model import ( "context" "errors" "time" mysqldriver "github.com/go-sql-driver/mysql" "gorm.io/gorm" "spark-server/internal/module/favorite/entity" "spark-server/internal/pkg/errs" ) // Repo is MySQL persistence for favorites. type Repo struct { gdb *gorm.DB } func NewRepo(gdb *gorm.DB) *Repo { return &Repo{gdb: gdb} } func (m *Repo) session(ctx context.Context) (*gorm.DB, error) { if m == nil || m.gdb == nil { return nil, errs.ErrAvailable } return m.gdb.WithContext(ctx), nil } func mapDBErr(err error) error { if err == nil { return nil } if errors.Is(err, gorm.ErrRecordNotFound) { return errs.ErrNotFound } var me *mysqldriver.MySQLError if errors.As(err, &me) && me.Number == 1062 { return errs.ErrDuplicate } return errs.ErrInner.WithError("favorite-mysql", err) } func (m *Repo) Get(ctx context.Context, id int64) (*entity.Favorite, error) { db, err := m.session(ctx) if err != nil { return nil, err } var row Favorite if err := db.Where("id = ?", id).Take(&row).Error; err != nil { return nil, mapDBErr(err) } return row.Entity(), nil } func (m *Repo) GetByUserMsg(ctx context.Context, userID, msgID int64) (*entity.Favorite, error) { db, err := m.session(ctx) if err != nil { return nil, err } var row Favorite if err := db.Where("user_id = ? AND msg_id = ?", userID, msgID).Take(&row).Error; err != nil { return nil, mapDBErr(err) } return row.Entity(), nil } func (m *Repo) Create(ctx context.Context, fav *entity.Favorite) error { if fav == nil || fav.ID <= 0 || fav.UserID <= 0 { return errs.ErrInvalidArgument } db, err := m.session(ctx) if err != nil { return err } row := fromEntity(fav) if row.CreatedAt.IsZero() { row.CreatedAt = time.Now() } return mapDBErr(db.Create(row).Error) } func (m *Repo) ListByUser(ctx context.Context, userID int64, limit int) ([]*entity.Favorite, error) { db, err := m.session(ctx) if err != nil { return nil, err } limit = entity.ClampLimit(limit) var rows []Favorite if err := db.Where("user_id = ?", userID).Order("id DESC").Limit(limit).Find(&rows).Error; err != nil { return nil, mapDBErr(err) } out := make([]*entity.Favorite, 0, len(rows)) for i := range rows { out = append(out, rows[i].Entity()) } return out, nil } func (m *Repo) ListAllByUser(ctx context.Context, userID int64) ([]*entity.Favorite, error) { db, err := m.session(ctx) if err != nil { return nil, err } var rows []Favorite if err := db.Where("user_id = ?", userID).Order("id DESC").Limit(10000).Find(&rows).Error; err != nil { return nil, mapDBErr(err) } out := make([]*entity.Favorite, 0, len(rows)) for i := range rows { out = append(out, rows[i].Entity()) } return out, nil } func (m *Repo) Delete(ctx context.Context, userID, id int64) error { db, err := m.session(ctx) if err != nil { return err } res := db.Where("id = ? AND user_id = ?", id, userID).Delete(&Favorite{}) if res.Error != nil { return mapDBErr(res.Error) } if res.RowsAffected == 0 { return errs.ErrNotFound } return nil }