This is an automated email from the ASF dual-hosted git repository.
linkinstar pushed a commit to branch feat/1.4.0/badge
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
The following commit(s) were added to refs/heads/feat/1.4.0/badge by this push:
new bede0adb feat(badge): award badge for user
bede0adb is described below
commit bede0adbf783a840fdeefec8afeb61e1e71cb864
Author: LinkinStars <[email protected]>
AuthorDate: Wed Aug 14 10:37:37 2024 +0800
feat(badge): award badge for user
---
cmd/wire_gen.go | 4 +-
docs/docs.go | 19 ++++++
internal/entity/badge_award_entity.go | 16 ++---
internal/repo/badge/badge_event_rule.go | 2 +-
internal/repo/badge_award/badge_award_repo.go | 88 +++++++++++++++++++--------
internal/service/badge/badge_award_service.go | 47 +++++---------
internal/service/badge/badge_event_handler.go | 34 ++++++-----
7 files changed, 129 insertions(+), 81 deletions(-)
diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index d4034b6b..9acd76ee 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -263,9 +263,9 @@ func initApplication(debug bool, serverConf *conf.Server,
dbConf *data.Database,
badgeGroupRepo := badge_group.NewBadgeGroupRepo(dataData, uniqueIDRepo)
badgeAwardRepo := badge_award.NewBadgeAwardRepo(dataData, uniqueIDRepo)
eventRuleRepo := badge.NewEventRuleRepo(dataData)
- badgeEventService := badge2.NewBadgeEventService(dataData,
eventQueueService, badgeRepo, eventRuleRepo)
- badgeService := badge2.NewBadgeService(badgeRepo, badgeGroupRepo,
badgeAwardRepo, badgeEventService)
badgeAwardService := badge2.NewBadgeAwardService(badgeAwardRepo,
badgeRepo, userCommon, objService)
+ badgeEventService := badge2.NewBadgeEventService(dataData,
eventQueueService, badgeRepo, eventRuleRepo, badgeAwardService)
+ badgeService := badge2.NewBadgeService(badgeRepo, badgeGroupRepo,
badgeAwardRepo, badgeEventService)
badgeController := controller.NewBadgeController(badgeService,
badgeAwardService)
controller_adminBadgeController :=
controller_admin.NewBadgeController(badgeService)
answerAPIRouter := router.NewAnswerAPIRouter(langController,
userController, commentController, reportController, voteController,
tagController, followController, collectionController, questionController,
answerController, searchController, revisionController, rankController,
userAdminController, reasonController, themeController, siteInfoController,
controllerSiteInfoController, notificationController, dashboardController,
uploadController, activityController, roleController, pluginCon [...]
diff --git a/docs/docs.go b/docs/docs.go
index 7fef400f..cfefe0ed 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -1,3 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
// Package docs Code generated by swaggo/swag. DO NOT EDIT
package docs
diff --git a/internal/entity/badge_award_entity.go
b/internal/entity/badge_award_entity.go
index 0eb30227..5ba475cd 100644
--- a/internal/entity/badge_award_entity.go
+++ b/internal/entity/badge_award_entity.go
@@ -24,18 +24,20 @@ import "time"
const (
IsBadgeNotDeleted = 0
IsBadgeDeleted = 1
+
+ BadgeOnceAwardKey = "0"
)
// BadgeAward badge_award
type BadgeAward struct {
ID string `xorm:"not null pk BIGINT(20) id"`
- CreatedAt time.Time `json:"created_at" xorm:"created not null
default CURRENT_TIMESTAMP TIMESTAMP created_at"`
- UpdatedAt time.Time `json:"updated_at" xorm:"updated not null
default CURRENT_TIMESTAMP TIMESTAMP updated_at"`
- UserID string `json:"user_id" xorm:"not null index
BIGINT(20) user_id"`
- BadgeID string `json:"badge_id" xorm:"not null index
BIGINT(20) badge_id"`
- AwardKey string `json:"award_key" xorm:"not null index
VARCHAR(64) award_key"`
- BadgeGroupID int64 `json:"badge_group_id" xorm:"not null index
BIGINT(20) badge_group_id"`
- IsBadgeDeleted int8 `json:"is_badge_deleted" xorm:"not null index
TINYINT(1) is_badge_deleted"`
+ CreatedAt time.Time `xorm:"created not null default
CURRENT_TIMESTAMP TIMESTAMP created_at"`
+ UpdatedAt time.Time `xorm:"updated not null default
CURRENT_TIMESTAMP TIMESTAMP updated_at"`
+ UserID string `xorm:"not null index BIGINT(20) user_id"`
+ BadgeID string `xorm:"not null index BIGINT(20) badge_id"`
+ AwardKey string `xorm:"not null index VARCHAR(64) award_key"`
+ BadgeGroupID int64 `xorm:"not null index BIGINT(20)
badge_group_id"`
+ IsBadgeDeleted int8 `xorm:"not null TINYINT(1) is_badge_deleted"`
}
// TableName badge_award table name
diff --git a/internal/repo/badge/badge_event_rule.go
b/internal/repo/badge/badge_event_rule.go
index 41d56686..f912c2bb 100644
--- a/internal/repo/badge/badge_event_rule.go
+++ b/internal/repo/badge/badge_event_rule.go
@@ -99,7 +99,7 @@ func (br *eventRuleRepo) FirstUpdateUserProfile(ctx
context.Context,
return nil, nil
}
if len(bean.Bio) > 0 {
- return append(awards, br.createBadgeAward(event.UserID, b.ID,
"")), nil
+ return append(awards, br.createBadgeAward(event.UserID, b.ID,
entity.BadgeOnceAwardKey)), nil
}
return nil, nil
}
diff --git a/internal/repo/badge_award/badge_award_repo.go
b/internal/repo/badge_award/badge_award_repo.go
index 5a5d56cd..058fa864 100644
--- a/internal/repo/badge_award/badge_award_repo.go
+++ b/internal/repo/badge_award/badge_award_repo.go
@@ -21,6 +21,7 @@ package badge_award
import (
"context"
+ "fmt"
"github.com/apache/incubator-answer/internal/base/data"
"github.com/apache/incubator-answer/internal/base/pager"
"github.com/apache/incubator-answer/internal/base/reason"
@@ -28,6 +29,7 @@ import (
"github.com/apache/incubator-answer/internal/service/badge"
"github.com/apache/incubator-answer/internal/service/unique"
"github.com/segmentfault/pacman/errors"
+ "xorm.io/xorm"
)
type badgeAwardRepo struct {
@@ -42,38 +44,62 @@ func NewBadgeAwardRepo(data *data.Data, uniqueIDRepo
unique.UniqueIDRepo) badge.
}
}
-func (r *badgeAwardRepo) Add(ctx context.Context, badgeAward
*entity.BadgeAward) (err error) {
+// AwardBadgeForUser award badge for user
+func (r *badgeAwardRepo) AwardBadgeForUser(ctx context.Context, badgeAward
*entity.BadgeAward) (err error) {
badgeAward.ID, err = r.uniqueIDRepo.GenUniqueIDStr(ctx,
entity.BadgeAward{}.TableName())
if err != nil {
- return
+ return err
}
- _, err = r.data.DB.Context(ctx).Insert(badgeAward)
- return
-}
-func (r *badgeAwardRepo) CheckIsAward(ctx context.Context, badgeID string,
userID string, awardKey string, singleOrMulti int8) (isAward bool) {
- isAward = false
- if singleOrMulti == entity.BadgeSingleAward {
- _, exists, err := r.GetByUserIdAndBadgeId(ctx, userID, badgeID)
+
+ _, err = r.data.DB.Transaction(func(session *xorm.Session) (result any,
err error) {
+ session = session.Context(ctx)
+
+ badgeInfo := &entity.Badge{}
+ exist, err :=
session.ID(badgeAward.BadgeID).ForUpdate().Get(badgeInfo)
if err != nil {
- err =
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
- return
+ return nil, err
}
- if exists {
- return true
+ if !exist {
+ return nil, fmt.Errorf("badge not exist")
}
- } else {
- _, exists, err := r.GetByUserIdAndBadgeIdAndObjectId(ctx,
userID, badgeID, awardKey)
+
+ old := &entity.BadgeAward{}
+ exist, err = session.Where("user_id = ? AND badge_id = ? AND
award_key = ? AND is_badge_deleted = 0",
+ badgeAward.UserID, badgeAward.BadgeID,
badgeAward.AwardKey).Get(old)
if err != nil {
- err =
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
- return
+ return nil, err
}
- if exists {
- return true
+ if exist {
+ return nil, fmt.Errorf("badge already awarded")
}
+
+ _, err = session.Insert(badgeAward)
+ if err != nil {
+ return nil, err
+ }
+
+ return session.ID(badgeInfo.ID).Incr("award_count",
1).Update(&entity.Badge{})
+ })
+ if err != nil {
+ return
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
+ return nil
+}
- return
+// CheckIsAward check this badge is awarded for this user or not
+func (r *badgeAwardRepo) CheckIsAward(ctx context.Context, badgeID, userID,
awardKey string, singleOrMulti int8) (
+ isAward bool, err error) {
+ if singleOrMulti == entity.BadgeSingleAward {
+ _, isAward, err = r.GetByUserIdAndBadgeId(ctx, userID, badgeID)
+ } else {
+ _, isAward, err = r.GetByUserIdAndBadgeIdAndAwardKey(ctx,
userID, badgeID, awardKey)
+ }
+ if err != nil {
+ err =
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+ }
+ return isAward, err
}
+
func (r *badgeAwardRepo) CountByUserIdAndBadgeLevel(ctx context.Context,
userID string, badgeLevel entity.BadgeLevel) (awardCount int64) {
return
}
@@ -161,13 +187,25 @@ func (r *badgeAwardRepo) ListNewestByUserIdAndLevel(ctx
context.Context, userID
}
// GetByUserIdAndBadgeId get badge award by user id and badge id
-func (r *badgeAwardRepo) GetByUserIdAndBadgeId(ctx context.Context, userID
string, badgeID string) (badgeAward *entity.BadgeAward, exists bool, err error)
{
- exists, err = r.data.DB.Context(ctx).Where("user_id = ? AND badge_id =
? AND is_badge_deleted = 0", userID, badgeID).Get(&badgeAward)
+func (r *badgeAwardRepo) GetByUserIdAndBadgeId(ctx context.Context, userID
string, badgeID string) (
+ badgeAward *entity.BadgeAward, exists bool, err error) {
+ badgeAward = &entity.BadgeAward{}
+ exists, err = r.data.DB.Context(ctx).
+ Where("user_id = ? AND badge_id = ? AND is_badge_deleted = 0",
userID, badgeID).Get(badgeAward)
+ if err != nil {
+ err =
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+ }
return
}
-// GetByUserIdAndBadgeIdAndObjectId get badge award by user id, badge id and
object id
-func (r *badgeAwardRepo) GetByUserIdAndBadgeIdAndObjectId(ctx context.Context,
userID string, badgeID string, awardKey string) (badgeAward *entity.BadgeAward,
exists bool, err error) {
- exists, err = r.data.DB.Context(ctx).Where("user_id = ? AND badge_id =
? AND award_key = ? AND is_badge_deleted = 0", userID, badgeID,
awardKey).Get(&badgeAward)
+// GetByUserIdAndBadgeIdAndAwardKey get badge award by user id and badge id
and award key
+func (r *badgeAwardRepo) GetByUserIdAndBadgeIdAndAwardKey(ctx context.Context,
userID string, badgeID string, awardKey string) (
+ badgeAward *entity.BadgeAward, exists bool, err error) {
+ badgeAward = &entity.BadgeAward{}
+ exists, err = r.data.DB.Context(ctx).
+ Where("user_id = ? AND badge_id = ? AND award_key = ? AND
is_badge_deleted = 0", userID, badgeID, awardKey).Get(badgeAward)
+ if err != nil {
+ err =
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+ }
return
}
diff --git a/internal/service/badge/badge_award_service.go
b/internal/service/badge/badge_award_service.go
index 96a9743f..3883de61 100644
--- a/internal/service/badge/badge_award_service.go
+++ b/internal/service/badge/badge_award_service.go
@@ -33,12 +33,11 @@ import (
"github.com/jinzhu/copier"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
- "time"
)
type BadgeAwardRepo interface {
- Add(ctx context.Context, badgeAward *entity.BadgeAward) (err error)
- CheckIsAward(ctx context.Context, badgeID string, userID string,
awardKey string, singleOrMulti int8) bool
+ CheckIsAward(ctx context.Context, badgeID string, userID string,
awardKey string, singleOrMulti int8) (isAward bool, err error)
+ AwardBadgeForUser(ctx context.Context, badgeAward *entity.BadgeAward)
(err error)
CountByUserIdAndBadgeLevel(ctx context.Context, userID string,
badgeLevel entity.BadgeLevel) (awardCount int64)
CountByUserId(ctx context.Context, userID string) (awardCount int64)
@@ -62,7 +61,7 @@ type BadgeAwardRepo interface {
ListNewestByUserIdAndLevel(ctx context.Context, userID string, level
int, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64,
err error)
GetByUserIdAndBadgeId(ctx context.Context, userID string, badgeID
string) (badgeAward *entity.BadgeAward, exists bool, err error)
- GetByUserIdAndBadgeIdAndObjectId(ctx context.Context, userID string,
badgeID string, awardKey string) (badgeAward *entity.BadgeAward, exists bool,
err error)
+ GetByUserIdAndBadgeIdAndAwardKey(ctx context.Context, userID string,
badgeID string, awardKey string) (badgeAward *entity.BadgeAward, exists bool,
err error)
}
type BadgeAwardService struct {
@@ -151,48 +150,32 @@ func (b *BadgeAwardService) GetBadgeAwardList(
}
// Award award badge
-func (b *BadgeAwardService) Award(ctx context.Context, badgeID string, userID
string, awardKey string, force bool, createdAt time.Time) (err error) {
- var (
- badgeData *entity.Badge
- exists, awarded bool
- )
-
- badgeData, exists, err = b.badgeRepo.GetByID(ctx, badgeID)
+func (b *BadgeAwardService) Award(ctx context.Context, badgeID string, userID
string, awardKey string) (err error) {
+ badgeData, exists, err := b.badgeRepo.GetByID(ctx, badgeID)
if err != nil {
- return
+ return err
}
if !exists || badgeData.Status == entity.BadgeStatusInactive {
- err = errors.BadRequest(reason.BadgeObjectNotFound)
- return
+ return errors.BadRequest(reason.BadgeObjectNotFound)
}
- awarded = b.badgeAwardRepo.CheckIsAward(ctx, badgeID, userID, awardKey,
badgeData.Single)
- if !force && awarded {
- return
+ alreadyAwarded, err := b.badgeAwardRepo.CheckIsAward(ctx, badgeID,
userID, awardKey, badgeData.Single)
+ if err != nil {
+ return err
}
-
- if createdAt.IsZero() {
- createdAt = time.Now()
+ if alreadyAwarded {
+ return nil
}
- err = b.badgeAwardRepo.Add(ctx, &entity.BadgeAward{
- CreatedAt: createdAt,
- UpdatedAt: createdAt,
+ badgeAward := &entity.BadgeAward{
UserID: userID,
BadgeID: badgeID,
AwardKey: awardKey,
BadgeGroupID: badgeData.BadgeGroupID,
- IsBadgeDeleted: 0,
- })
- if err != nil {
- return
+ IsBadgeDeleted: entity.IsBadgeNotDeleted,
}
-
- // increment badge award count
- err = b.badgeRepo.UpdateAwardCount(ctx, badgeID, 1)
-
- return
+ return b.badgeAwardRepo.AwardBadgeForUser(ctx, badgeAward)
}
// GetUserBadgeAwardList get user badge award list
diff --git a/internal/service/badge/badge_event_handler.go
b/internal/service/badge/badge_event_handler.go
index 09331197..f990260b 100644
--- a/internal/service/badge/badge_event_handler.go
+++ b/internal/service/badge/badge_event_handler.go
@@ -21,12 +21,11 @@ package badge
import (
"context"
+ "github.com/apache/incubator-answer/internal/base/data"
"github.com/apache/incubator-answer/internal/entity"
+ "github.com/apache/incubator-answer/internal/schema"
"github.com/apache/incubator-answer/internal/service/event_queue"
"github.com/segmentfault/pacman/log"
-
- "github.com/apache/incubator-answer/internal/base/data"
- "github.com/apache/incubator-answer/internal/schema"
)
type BadgeEventService struct {
@@ -35,6 +34,7 @@ type BadgeEventService struct {
badgeAwardRepo BadgeAwardRepo
badgeRepo BadgeRepo
eventRuleRepo EventRuleRepo
+ badgeAwardService *BadgeAwardService
}
type EventRuleHandler func(ctx context.Context, event *schema.EventMsg)
(awards []*entity.BadgeAward, err error)
@@ -48,12 +48,14 @@ func NewBadgeEventService(
eventQueueService event_queue.EventQueueService,
badgeRepo BadgeRepo,
eventRuleRepo EventRuleRepo,
+ badgeAwardService *BadgeAwardService,
) *BadgeEventService {
n := &BadgeEventService{
data: data,
eventQueueService: eventQueueService,
badgeRepo: badgeRepo,
eventRuleRepo: eventRuleRepo,
+ badgeAwardService: badgeAwardService,
}
eventQueueService.RegisterHandler(n.Handler)
return n
@@ -65,18 +67,22 @@ func (ns *BadgeEventService) Handler(ctx context.Context,
msg *schema.EventMsg)
return nil
}
- badgeIDs := make([]string, 0)
- for _, award := range awards {
- badgeIDs = append(badgeIDs, award.BadgeID)
- }
+ //badgeIDs := make([]string, 0)
+ //for _, award := range awards {
+ // badgeIDs = append(badgeIDs, award.BadgeID)
+ //}
+ //
+ //badges, err := ns.badgeRepo.GetByIDs(ctx, badgeIDs)
+ //if err != nil {
+ // log.Errorf("error getting badges %+v: %v", badgeIDs, err)
+ // return err
+ //}
- badges, err := ns.badgeRepo.GetByIDs(ctx, badgeIDs)
- if err != nil {
- log.Errorf("error getting badges %+v: %v", badgeIDs, err)
- return err
+ for _, award := range awards {
+ err := ns.badgeAwardService.Award(ctx, award.BadgeID,
award.UserID, award.AwardKey)
+ if err != nil {
+ log.Debugf("error awarding badge %s: %v",
award.BadgeID, err)
+ }
}
-
- // TODO: award badges to user
- log.Debugf("awarding badges %+v to user", badges)
return nil
}