You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by li...@apache.org on 2023/11/28 09:49:41 UTC

(incubator-answer) branch refactor/collection created (now 0e430827)

This is an automated email from the ASF dual-hosted git repository.

linkinstar pushed a change to branch refactor/collection
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git


      at 0e430827 refactor(collection): refactor collection

This branch includes the following new commits:

     new 0e430827 refactor(collection): refactor collection

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(incubator-answer) 01/01: refactor(collection): refactor collection

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

linkinstar pushed a commit to branch refactor/collection
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git

commit 0e430827c0e8ce130807d308b933bcbf4e8821c9
Author: LinkinStars <li...@foxmail.com>
AuthorDate: Tue Nov 28 17:00:06 2023 +0800

    refactor(collection): refactor collection
---
 internal/controller/collection_controller.go      |  21 +---
 internal/repo/collection/collection_group_repo.go |  37 ++++++
 internal/repo/collection/collection_repo.go       |  43 ++++---
 internal/repo/question/question_repo.go           |  23 +++-
 internal/schema/collection_group_schema.go        |  17 +--
 internal/service/collection_group_service.go      |   1 +
 internal/service/collection_service.go            | 135 ++++------------------
 internal/service/question_common/question.go      |   6 +-
 8 files changed, 108 insertions(+), 175 deletions(-)

diff --git a/internal/controller/collection_controller.go b/internal/controller/collection_controller.go
index 74005fc4..4e3eff38 100644
--- a/internal/controller/collection_controller.go
+++ b/internal/controller/collection_controller.go
@@ -22,14 +22,10 @@ package controller
 import (
 	"github.com/apache/incubator-answer/internal/base/handler"
 	"github.com/apache/incubator-answer/internal/base/middleware"
-	"github.com/apache/incubator-answer/internal/base/reason"
 	"github.com/apache/incubator-answer/internal/schema"
 	"github.com/apache/incubator-answer/internal/service"
-	"github.com/apache/incubator-answer/pkg/converter"
 	"github.com/apache/incubator-answer/pkg/uid"
 	"github.com/gin-gonic/gin"
-	"github.com/jinzhu/copier"
-	"github.com/segmentfault/pacman/errors"
 )
 
 // CollectionController collection controller
@@ -57,21 +53,10 @@ func (cc *CollectionController) CollectionSwitch(ctx *gin.Context) {
 	if handler.BindAndCheck(ctx, req) {
 		return
 	}
-	req.ObjectID = uid.DeShortID(req.ObjectID)
-
-	dto := &schema.CollectionSwitchDTO{}
-	_ = copier.Copy(dto, req)
 
-	dto.UserID = middleware.GetLoginUserIDFromContext(ctx)
-
-	if converter.StringToInt64(req.ObjectID) < 1 {
-		return
-	}
-	if converter.StringToInt64(dto.UserID) < 1 {
-		handler.HandleResponse(ctx, errors.Unauthorized(reason.UnauthorizedError), nil)
-		return
-	}
+	req.ObjectID = uid.DeShortID(req.ObjectID)
+	req.UserID = middleware.GetLoginUserIDFromContext(ctx)
 
-	resp, err := cc.collectionService.CollectionSwitch(ctx, dto)
+	resp, err := cc.collectionService.CollectionSwitch(ctx, req)
 	handler.HandleResponse(ctx, err, resp)
 }
diff --git a/internal/repo/collection/collection_group_repo.go b/internal/repo/collection/collection_group_repo.go
index d0d6c804..0fc9c27a 100644
--- a/internal/repo/collection/collection_group_repo.go
+++ b/internal/repo/collection/collection_group_repo.go
@@ -21,6 +21,7 @@ package collection
 
 import (
 	"context"
+	"xorm.io/xorm"
 
 	"github.com/apache/incubator-answer/internal/base/data"
 	"github.com/apache/incubator-answer/internal/base/pager"
@@ -68,6 +69,42 @@ func (cr *collectionGroupRepo) AddCollectionDefaultGroup(ctx context.Context, us
 	return
 }
 
+// CreateDefaultGroupIfNotExist create default group if not exist
+func (cr *collectionGroupRepo) CreateDefaultGroupIfNotExist(ctx context.Context, userID string) (
+	collectionGroup *entity.CollectionGroup, err error) {
+	_, err = cr.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
+		session = session.Context(ctx)
+		old := &entity.CollectionGroup{
+			UserID:       userID,
+			DefaultGroup: schema.CGDefault,
+		}
+		exist, err := session.ForUpdate().Get(old)
+		if err != nil {
+			return nil, err
+		}
+		if exist {
+			collectionGroup = old
+			return old, nil
+		}
+
+		defaultGroup := &entity.CollectionGroup{
+			Name:         "default",
+			DefaultGroup: schema.CGDefault,
+			UserID:       userID,
+		}
+		_, err = session.Insert(defaultGroup)
+		if err != nil {
+			return nil, err
+		}
+		collectionGroup = defaultGroup
+		return nil, nil
+	})
+	if err != nil {
+		return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+	}
+	return collectionGroup, nil
+}
+
 // UpdateCollectionGroup update collection group
 func (cr *collectionGroupRepo) UpdateCollectionGroup(ctx context.Context, collectionGroup *entity.CollectionGroup, cols []string) (err error) {
 	_, err = cr.data.DB.Context(ctx).ID(collectionGroup.ID).Cols(cols...).Update(collectionGroup)
diff --git a/internal/repo/collection/collection_repo.go b/internal/repo/collection/collection_repo.go
index ea075497..c67b7bd2 100644
--- a/internal/repo/collection/collection_repo.go
+++ b/internal/repo/collection/collection_repo.go
@@ -50,42 +50,39 @@ func NewCollectionRepo(data *data.Data, uniqueIDRepo unique.UniqueIDRepo) collec
 
 // AddCollection add collection
 func (cr *collectionRepo) AddCollection(ctx context.Context, collection *entity.Collection) (err error) {
-	needAdd := false
+	collection.ID, err = cr.uniqueIDRepo.GenUniqueIDStr(ctx, collection.TableName())
+	if err != nil {
+		return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+	}
+
 	_, err = cr.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
 		session = session.Context(ctx)
-		var has bool
-		dbcollection := &entity.Collection{}
-		result = nil
-		has, err = session.Where("user_id = ? and object_id = ?", collection.UserID, collection.ObjectID).Get(dbcollection)
+		old := &entity.Collection{
+			UserID:   collection.UserID,
+			ObjectID: collection.ObjectID,
+		}
+		exist, err := session.ForUpdate().Get(old)
 		if err != nil {
-			return
+			return nil, err
+		}
+		if exist {
+			return nil, nil
 		}
-		if has {
-			return
+		_, err = session.Insert(collection)
+		if err != nil {
+			return nil, err
 		}
-		needAdd = true
 		return
 	})
 	if err != nil {
-		return
-	}
-	if needAdd {
-		id, err := cr.uniqueIDRepo.GenUniqueIDStr(ctx, collection.TableName())
-		if err == nil {
-			collection.ID = id
-			_, err = cr.data.DB.Context(ctx).Insert(collection)
-			if err != nil {
-				return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
-			}
-		}
+		return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
 	}
-
-	return err
+	return nil
 }
 
 // RemoveCollection delete collection
 func (cr *collectionRepo) RemoveCollection(ctx context.Context, id string) (err error) {
-	_, err = cr.data.DB.Context(ctx).Where("id =?", id).Delete(&entity.Collection{})
+	_, err = cr.data.DB.Context(ctx).Where("id = ?", id).Delete(&entity.Collection{})
 	if err != nil {
 		return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
 	}
diff --git a/internal/repo/question/question_repo.go b/internal/repo/question/question_repo.go
index 9288fce8..2cd9a325 100644
--- a/internal/repo/question/question_repo.go
+++ b/internal/repo/question/question_repo.go
@@ -28,6 +28,7 @@ import (
 	"strings"
 	"time"
 	"unicode"
+	"xorm.io/xorm"
 
 	"github.com/apache/incubator-answer/internal/base/handler"
 	"xorm.io/builder"
@@ -127,14 +128,26 @@ func (qr *questionRepo) UpdateAnswerCount(ctx context.Context, questionID string
 	return nil
 }
 
-func (qr *questionRepo) UpdateCollectionCount(ctx context.Context, questionID string, num int) (err error) {
+func (qr *questionRepo) UpdateCollectionCount(ctx context.Context, questionID string) (count int64, err error) {
 	questionID = uid.DeShortID(questionID)
-	question := &entity.Question{}
-	_, err = qr.data.DB.Context(ctx).Where("id =?", questionID).Incr("collection_count", num).Update(question)
+	_, err = qr.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
+		session = session.Context(ctx)
+		count, err = session.Count(&entity.Collection{ObjectID: questionID})
+		if err != nil {
+			return nil, err
+		}
+
+		question := &entity.Question{CollectionCount: int(count)}
+		_, err = session.ID(questionID).MustCols("collection_count").Update(question)
+		if err != nil {
+			return nil, err
+		}
+		return
+	})
 	if err != nil {
-		return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+		return 0, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
 	}
-	return nil
+	return count, nil
 }
 
 func (qr *questionRepo) UpdateQuestionStatus(ctx context.Context, questionID string, status int) (err error) {
diff --git a/internal/schema/collection_group_schema.go b/internal/schema/collection_group_schema.go
index 212d6993..3177f3f1 100644
--- a/internal/schema/collection_group_schema.go
+++ b/internal/schema/collection_group_schema.go
@@ -28,24 +28,15 @@ const (
 
 // CollectionSwitchReq switch collection request
 type CollectionSwitchReq struct {
-	// object TagID
 	ObjectID string `validate:"required" json:"object_id"`
-	// user collection group TagID
-	GroupID string `validate:"required" json:"group_id"`
-}
-
-// CollectionSwitchDTO  collection data transfer object
-type CollectionSwitchDTO struct {
-	ObjectID string
-	GroupID  string
-	UserID   string
+	GroupID  string `validate:"required" json:"group_id"`
+	Bookmark bool   `validate:"omitempty" json:"bookmark"`
+	UserID   string `json:"-"`
 }
 
 // CollectionSwitchResp switch collection response
 type CollectionSwitchResp struct {
-	ObjectID              string `json:"object_id"`
-	Switch                bool   `json:"switch"`
-	ObjectCollectionCount string `json:"object_collection_count"`
+	ObjectCollectionCount int64 `json:"object_collection_count"`
 }
 
 // AddCollectionGroupReq add collection group request
diff --git a/internal/service/collection_group_service.go b/internal/service/collection_group_service.go
index 0ca0236e..2620c54c 100644
--- a/internal/service/collection_group_service.go
+++ b/internal/service/collection_group_service.go
@@ -33,6 +33,7 @@ import (
 type CollectionGroupRepo interface {
 	AddCollectionGroup(ctx context.Context, collectionGroup *entity.CollectionGroup) (err error)
 	AddCollectionDefaultGroup(ctx context.Context, userID string) (collectionGroup *entity.CollectionGroup, err error)
+	CreateDefaultGroupIfNotExist(ctx context.Context, userID string) (collectionGroup *entity.CollectionGroup, err error)
 	UpdateCollectionGroup(ctx context.Context, collectionGroup *entity.CollectionGroup, cols []string) (err error)
 	GetCollectionGroup(ctx context.Context, id string) (collectionGroup *entity.CollectionGroup, exist bool, err error)
 	GetCollectionGroupPage(ctx context.Context, page, pageSize int, collectionGroup *entity.CollectionGroup) (collectionGroupList []*entity.CollectionGroup, total int64, err error)
diff --git a/internal/service/collection_service.go b/internal/service/collection_service.go
index d12fb829..1072d1ab 100644
--- a/internal/service/collection_service.go
+++ b/internal/service/collection_service.go
@@ -21,14 +21,10 @@ package service
 
 import (
 	"context"
-	"fmt"
-
 	"github.com/apache/incubator-answer/internal/entity"
 	"github.com/apache/incubator-answer/internal/schema"
 	collectioncommon "github.com/apache/incubator-answer/internal/service/collection_common"
 	questioncommon "github.com/apache/incubator-answer/internal/service/question_common"
-	"github.com/segmentfault/pacman/errors"
-	"github.com/segmentfault/pacman/log"
 )
 
 // CollectionService user service
@@ -50,127 +46,40 @@ func NewCollectionService(
 	}
 }
 
-func (cs *CollectionService) CollectionSwitch(ctx context.Context, dto *schema.CollectionSwitchDTO) (resp *schema.CollectionSwitchResp, err error) {
-	resp = &schema.CollectionSwitchResp{}
-	dbData, has, err := cs.collectionRepo.GetOneByObjectIDAndUser(ctx, dto.UserID, dto.ObjectID)
-	if err != nil {
-		return
-	}
-	if has {
-		err = cs.collectionRepo.RemoveCollection(ctx, dbData.ID)
-		if err != nil {
-			return nil, err
-		}
-		err = cs.questionCommon.UpdateCollectionCount(ctx, dto.ObjectID, -1)
-		if err != nil {
-			log.Error("UpdateCollectionCount", err.Error())
-		}
-		var count int64
-		count, err = cs.objectCollectionCount(ctx, dto.ObjectID)
-		if err != nil {
-			return resp, err
-		}
-		resp.ObjectCollectionCount = fmt.Sprintf("%v", count)
-		resp.Switch = false
-		return resp, err
-	}
-
-	if dto.GroupID == "" || dto.GroupID == "0" {
-		var (
-			defaultGroup *entity.CollectionGroup
-			has          bool
-		)
-		defaultGroup, has, err = cs.collectionGroupRepo.GetDefaultID(ctx, dto.UserID)
-		if err != nil {
-			return nil, err
-		}
-		if !has {
-			var dbdefaultGroup *entity.CollectionGroup
-			dbdefaultGroup, err = cs.collectionGroupRepo.AddCollectionDefaultGroup(ctx, dto.UserID)
-			if err != nil {
-				return nil, err
-			}
-			dto.GroupID = dbdefaultGroup.ID
-		} else {
-			dto.GroupID = defaultGroup.ID
-		}
-	}
-	collection := &entity.Collection{
-		UserCollectionGroupID: dto.GroupID,
-		UserID:                dto.UserID,
-		ObjectID:              dto.ObjectID,
-	}
-
-	err = cs.collectionRepo.AddCollection(ctx, collection)
+func (cs *CollectionService) CollectionSwitch(ctx context.Context, req *schema.CollectionSwitchReq) (
+	resp *schema.CollectionSwitchResp, err error) {
+	collectionGroup, err := cs.collectionGroupRepo.CreateDefaultGroupIfNotExist(ctx, req.UserID)
 	if err != nil {
-		return
+		return nil, err
 	}
-	err = cs.questionCommon.UpdateCollectionCount(ctx, dto.ObjectID, 1)
-	if err != nil {
-		log.Error("UpdateCollectionCount", err.Error())
-	}
-	count, err := cs.objectCollectionCount(ctx, dto.ObjectID)
-	if err != nil {
-		return
-	}
-	resp.ObjectCollectionCount = fmt.Sprintf("%d", count)
-	resp.Switch = true
-	return
-}
-
-func (cs *CollectionService) objectCollectionCount(ctx context.Context, objectID string) (int64, error) {
-	count, err := cs.collectionRepo.CountByObjectID(ctx, objectID)
-	return count, err
-}
 
-func (cs *CollectionService) add(ctx context.Context, collection *entity.Collection) error {
-	_, has, err := cs.collectionRepo.GetOneByObjectIDAndUser(ctx, collection.UserID, collection.ObjectID)
+	collection, exist, err := cs.collectionRepo.GetOneByObjectIDAndUser(ctx, req.UserID, req.ObjectID)
 	if err != nil {
-		return err
+		return nil, err
 	}
-	if has {
-		return errors.BadRequest("already collected")
+	if (!req.Bookmark && !exist) || (req.Bookmark && exist) {
+		return nil, nil
 	}
 
-	if collection.UserCollectionGroupID == "" || collection.UserCollectionGroupID == "0" {
-		var (
-			defaultGroup *entity.CollectionGroup
-			has          bool
-		)
-		defaultGroup, has, err = cs.collectionGroupRepo.GetDefaultID(ctx, collection.UserID)
-		if err != nil {
-			return err
-		}
-		if !has {
-			defaultGroup, err = cs.collectionGroupRepo.AddCollectionDefaultGroup(ctx, collection.UserID)
-			if err != nil {
-				return err
-			}
-			collection.UserCollectionGroupID = defaultGroup.ID
-
-		} else {
-			collection.UserCollectionGroupID = defaultGroup.ID
+	if req.Bookmark {
+		collection = &entity.Collection{
+			UserID:                req.UserID,
+			ObjectID:              req.ObjectID,
+			UserCollectionGroupID: collectionGroup.ID,
 		}
+		err = cs.collectionRepo.AddCollection(ctx, collection)
+	} else {
+		err = cs.collectionRepo.RemoveCollection(ctx, collection.ID)
 	}
-	err = cs.collectionRepo.AddCollection(ctx, collection)
 	if err != nil {
-		return err
+		return nil, err
 	}
-	return nil
-}
 
-// Cancel
-func (cs *CollectionService) cancel(ctx context.Context, collection *entity.Collection) error {
-	dbData, has, err := cs.collectionRepo.GetOneByObjectIDAndUser(ctx, collection.UserID, collection.ObjectID)
-	if err != nil {
-		return err
-	}
-	if !has {
-		return errors.BadRequest("collected record does not exist")
-	}
-	err = cs.collectionRepo.RemoveCollection(ctx, dbData.ID)
+	// For now, we only support bookmark for question, so we just update question collection count
+	resp = &schema.CollectionSwitchResp{}
+	resp.ObjectCollectionCount, err = cs.questionCommon.UpdateCollectionCount(ctx, req.ObjectID)
 	if err != nil {
-		return err
+		return nil, err
 	}
-	return nil
+	return resp, nil
 }
diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go
index b12a9dec..5c663861 100644
--- a/internal/service/question_common/question.go
+++ b/internal/service/question_common/question.go
@@ -63,7 +63,7 @@ type QuestionRepo interface {
 	GetQuestionsByTitle(ctx context.Context, title string, pageSize int) (questionList []*entity.Question, err error)
 	UpdatePvCount(ctx context.Context, questionID string) (err error)
 	UpdateAnswerCount(ctx context.Context, questionID string, num int) (err error)
-	UpdateCollectionCount(ctx context.Context, questionID string, num int) (err error)
+	UpdateCollectionCount(ctx context.Context, questionID string) (count int64, err error)
 	UpdateAccepted(ctx context.Context, question *entity.Question) (err error)
 	UpdateLastAnswer(ctx context.Context, question *entity.Question) (err error)
 	FindByID(ctx context.Context, id []string) (questionList []*entity.Question, err error)
@@ -135,8 +135,8 @@ func (qs *QuestionCommon) UpdateAnswerCount(ctx context.Context, questionID stri
 	return qs.questionRepo.UpdateAnswerCount(ctx, questionID, int(count))
 }
 
-func (qs *QuestionCommon) UpdateCollectionCount(ctx context.Context, questionID string, num int) error {
-	return qs.questionRepo.UpdateCollectionCount(ctx, questionID, num)
+func (qs *QuestionCommon) UpdateCollectionCount(ctx context.Context, questionID string) (count int64, err error) {
+	return qs.questionRepo.UpdateCollectionCount(ctx, questionID)
 }
 
 func (qs *QuestionCommon) UpdateAccepted(ctx context.Context, questionID, AnswerID string) error {