Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

目录直接相关的 API #234

Merged
merged 28 commits into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
019c648
feat(indices): add router
RanKKI Oct 4, 2022
b210d38
feat(indices): create new index
RanKKI Oct 6, 2022
c215d64
feat(indices): update index's infomation
RanKKI Oct 6, 2022
055e32b
feat(indices): delete index
RanKKI Oct 6, 2022
cfa4cc2
feat(indices): update time of index
RanKKI Oct 6, 2022
5bf8aed
style(db): remove useless options
RanKKI Oct 6, 2022
a04bade
style(indices): use 'description' instead of 'desc'
RanKKI Oct 6, 2022
f05dec9
fix(indices): error handler
RanKKI Oct 6, 2022
3cbd443
feat(indices): CURD subjects in the index
RanKKI Oct 7, 2022
b02c841
style(indices): lint error
RanKKI Oct 7, 2022
757c3bf
test(indices): delete/add non-exists index/indexsubject
RanKKI Oct 7, 2022
c494a80
fix(indices): response key & lint error
RanKKI Oct 8, 2022
dbcd78e
remove: delete index
RanKKI Oct 12, 2022
70eca4c
style: use past tense variable name
RanKKI Oct 12, 2022
24a920e
test(indices): test on new index not the exists index in the test DB"
RanKKI Oct 12, 2022
bfae787
docs: api info
RanKKI Oct 12, 2022
e09984d
Revert "remove: delete index"
RanKKI Oct 12, 2022
b99f86c
remove: api of delete index
RanKKI Oct 12, 2022
074a8b2
feat: put non-exists subject in a index will create one
RanKKI Oct 13, 2022
1845ce6
style: DB field name
RanKKI Oct 15, 2022
45a75b6
fix: response on invalid payload & invalidate cache after update
RanKKI Oct 17, 2022
d5da8a9
docs: decompose requried payload and response
RanKKI Oct 17, 2022
14f1eca
Merge branch 'bangumi:master' into feat/indices_part_a
RanKKI Oct 17, 2022
f5298bb
refactor: index package
RanKKI Oct 17, 2022
4323205
refactor: indexID as param
RanKKI Oct 18, 2022
51d9451
feat: all input string should be printable
RanKKI Oct 18, 2022
714b699
fix: lint error
RanKKI Oct 22, 2022
6ce4fa6
Merge branch 'master' into feat/indices_part_a
RanKKI Oct 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions internal/domain/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ var ErrUserNotFound = errgo.MsgNoTrace(ErrNotFound, "user not found")
var ErrSubjectNotCollected = errgo.MsgNoTrace(ErrNotFound, "subject is not collected by user")

var ErrInput = errors.New("input not valid")

var ErrExists = errors.New("item already exists")
12 changes: 12 additions & 0 deletions internal/domain/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,23 @@ import (

type IndexRepo interface {
Get(ctx context.Context, id model.IndexID) (model.Index, error)
New(ctx context.Context, i *model.Index) error
Update(ctx context.Context, id model.IndexID, title string, desc string) error
Delete(ctx context.Context, id model.IndexID) error

CountSubjects(ctx context.Context, id model.IndexID, subjectType model.SubjectType) (int64, error)
ListSubjects(
ctx context.Context, id model.IndexID, subjectType model.SubjectType, limit, offset int,
) ([]IndexSubject, error)
AddIndexSubject(
ctx context.Context, id model.IndexID, subjectID model.SubjectID, sort uint32, comment string,
) (*IndexSubject, error)
UpdateIndexSubject(
ctx context.Context, id model.IndexID, subjectID model.SubjectID, sort uint32, comment string,
) error
DeleteIndexSubject(
ctx context.Context, id model.IndexID, subjectID model.SubjectID,
) error
}

type IndexSubject struct {
Expand Down
214 changes: 198 additions & 16 deletions internal/index/mysql_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import (
"time"

"go.uber.org/zap"
"gorm.io/gen"
"gorm.io/gorm"

"github.com/bangumi/server/internal/dal/dao"
"github.com/bangumi/server/internal/dal/query"
"github.com/bangumi/server/internal/domain"
"github.com/bangumi/server/internal/model"
Expand All @@ -38,7 +40,7 @@ type mysqlRepo struct {
log *zap.Logger
}

func (r mysqlRepo) isNsfw(ctx context.Context, id uint32) (bool, error) {
func (r mysqlRepo) isNsfw(ctx context.Context, id model.IndexID) (bool, error) {
i, err := r.q.IndexSubject.WithContext(ctx).
Join(r.q.Subject, r.q.IndexSubject.Sid.EqCol(r.q.Subject.ID)).
Where(r.q.IndexSubject.Rid.Eq(id), r.q.Subject.Nsfw.Is(true)).Count()
Expand All @@ -50,7 +52,7 @@ func (r mysqlRepo) isNsfw(ctx context.Context, id uint32) (bool, error) {
return i != 0, nil
}

func (r mysqlRepo) Get(ctx context.Context, id uint32) (model.Index, error) {
func (r mysqlRepo) Get(ctx context.Context, id model.IndexID) (model.Index, error) {
i, err := r.q.Index.WithContext(ctx).
Where(r.q.Index.ID.Eq(id), r.q.Index.Ban.Is(false)).First()
if err != nil {
Expand All @@ -66,22 +68,45 @@ func (r mysqlRepo) Get(ctx context.Context, id uint32) (model.Index, error) {
return model.Index{}, err
}

return model.Index{
CreatedAt: time.Unix(int64(i.Dateline), 0),
Title: i.Title,
Description: i.Desc,
CreatorID: i.CreatorID,
Total: i.SubjectTotal,
ID: id,
Comments: i.Replies,
Collects: i.Collects,
Ban: i.Ban,
NSFW: nsfw,
}, nil
ret := daoToModel(i)
ret.NSFW = nsfw
return *ret, nil
}

func (r mysqlRepo) New(ctx context.Context, i *model.Index) error {
dao := modelToDAO(i)
if err := r.q.Index.WithContext(ctx).Create(dao); err != nil {
return errgo.Wrap(err, "failed to create index in db")
}
i.ID = dao.ID
return nil
}

func (r mysqlRepo) Update(ctx context.Context, id model.IndexID, title string, desc string) error {
query := r.q.Index.WithContext(ctx)
result, err := query.Where(r.q.Index.ID.Eq(id)).Updates(dao.Index{
Title: title,
Desc: desc,
})
return r.WrapResult(result, err, "failed to update index info")
}

func (r mysqlRepo) Delete(ctx context.Context, id model.IndexID) error {
return r.q.Transaction(func(tx *query.Query) error {
result, err := tx.Index.WithContext(ctx).Where(tx.Index.ID.Eq(id)).Delete()
if err = r.WrapResult(result, err, "failed to delete index"); err != nil {
return err
}
result, err = tx.IndexSubject.WithContext(ctx).Where(tx.IndexSubject.Rid.Eq(id)).Delete()
if err = r.WrapResult(result, err, "failed to delete subjects in the index"); err != nil {
return err
}
return nil
})
}

func (r mysqlRepo) CountSubjects(
ctx context.Context, id uint32, subjectType model.SubjectType,
ctx context.Context, id model.IndexID, subjectType model.SubjectType,
) (int64, error) {
q := r.q.IndexSubject.WithContext(ctx).Where(r.q.IndexSubject.Rid.Eq(id))
if subjectType != 0 {
Expand All @@ -98,7 +123,7 @@ func (r mysqlRepo) CountSubjects(

func (r mysqlRepo) ListSubjects(
ctx context.Context,
id uint32,
id model.IndexID,
subjectType model.SubjectType,
limit, offset int,
) ([]domain.IndexSubject, error) {
Expand Down Expand Up @@ -130,3 +155,160 @@ func (r mysqlRepo) ListSubjects(

return results, nil
}

func (r mysqlRepo) AddIndexSubject(
ctx context.Context, id model.IndexID,
subjectID model.SubjectID, sort uint32, comment string,
) (*domain.IndexSubject, error) {
var err error

index, err := r.Get(ctx, id)
if err != nil {
return nil, err
}

subjectDO, err := r.q.Subject.WithContext(ctx).
Where(r.q.Subject.ID.Eq(subjectID)).
First()

if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, domain.ErrSubjectNotFound
}
return nil, errgo.Wrap(err, "dal")
}

now := time.Now()

indexSubject, err := r.q.IndexSubject.WithContext(ctx).
Where(r.q.IndexSubject.Rid.Eq(id), r.q.IndexSubject.Sid.Eq(uint32(subjectID))).First()

if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errgo.Wrap(err, "dal")
}

if indexSubject != nil && indexSubject.ID != 0 {
return nil, domain.ErrExists
}

err = r.addSubjectToIndex(ctx, index, &dao.IndexSubject{
Comment: comment,
Order: sort,
Dateline: uint32(now.Unix()),
Type: subjectDO.TypeID,
Rid: id,
Sid: uint32(subjectID),
})

if err != nil {
return nil, errgo.Wrap(err, "dal")
}

subject, err := subject.ConvertDao(subjectDO)
if err != nil {
return nil, errgo.Wrap(err, "subject.ConvertDao")
}

return &domain.IndexSubject{
AddedAt: now,
Comment: comment,
Subject: subject,
}, nil
}

func (r mysqlRepo) addSubjectToIndex(ctx context.Context, index model.Index, subject *dao.IndexSubject) error {
return r.q.Transaction(func(tx *query.Query) error {
err := r.q.IndexSubject.WithContext(ctx).Create(subject)
if err != nil {
return errgo.Wrap(err, "failed to create subject in index")
}

result, err := r.q.Index.WithContext(ctx).
Where(r.q.Index.ID.Eq(index.ID)).
Updates(dao.Index{
Lasttouch: uint32(time.Now().Unix()),
SubjectTotal: index.Total + 1,
})

return r.WrapResult(result, err, "failed to update index info")
})
}

func (r mysqlRepo) UpdateIndexSubject(
ctx context.Context, id model.IndexID, subjectID model.SubjectID, sort uint32, comment string,
) error {
q := r.q.IndexSubject
result, err := q.WithContext(ctx).
Where(q.Rid.Eq(id), q.Sid.Eq(uint32(subjectID))).
Updates(dao.IndexSubject{
Comment: comment,
Order: sort,
})
return r.WrapResult(result, err, "failed to update index subject")
}

func (r mysqlRepo) DeleteIndexSubject(
ctx context.Context, id model.IndexID, subjectID model.SubjectID,
) error {
return r.q.Transaction(func(tx *query.Query) error {
index, err := r.Get(ctx, id)
if err != nil {
return err
}
result, err := r.q.IndexSubject.WithContext(ctx).
Where(r.q.IndexSubject.Rid.Eq(id), r.q.IndexSubject.Sid.Eq(uint32(subjectID))).
Delete()
if err = r.WrapResult(result, err, "failed to delete index subject"); err != nil {
return err
}
result, err = r.q.Index.WithContext(ctx).Where(r.q.Index.ID.Eq(id)).Updates(dao.Index{
SubjectTotal: index.Total - 1,
})
if err = r.WrapResult(result, err, "failed to update index info"); err != nil {
return err
}
return nil
})
}

func (r mysqlRepo) WrapResult(result gen.ResultInfo, err error, msg string) error {
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return domain.ErrNotFound
}
return errgo.Wrap(err, msg)
}
if result.Error != nil {
return result.Error
}
return nil
}

func daoToModel(index *dao.Index) *model.Index {
return &model.Index{
ID: index.ID,
Title: index.Title,
Description: index.Desc,
CreatorID: index.CreatorID,
Total: index.SubjectTotal,
Comments: index.Replies,
Collects: index.Collects,
Ban: index.Ban,
NSFW: false, // check nsfw outside of this function
CreatedAt: time.Unix(int64(index.Dateline), 0),
UpdateAt: time.Unix(int64(index.Lasttouch), 0),
}
}

func modelToDAO(index *model.Index) *dao.Index {
return &dao.Index{
ID: index.ID,
Type: 0,
Title: index.Title,
Desc: index.Description,
CreatorID: index.CreatorID,
Ban: index.Ban,
Dateline: int32(index.CreatedAt.Unix()),
Lasttouch: uint32(index.UpdateAt.Unix()),
}
}
Loading