This is an automated email from the ASF dual-hosted git repository. linkinstar pushed a commit to branch fix/1.3.5/question in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
commit a7b23982c93dc75719ed40eef10c038b450b1b09 Author: LinkinStars <[email protected]> AuthorDate: Fri Jun 7 14:39:36 2024 +0800 refactor(meta): Adjust the meta structure of the operation from map to array to ensure correct sorting. --- internal/schema/meta_schema.go | 85 +++++++++++++++++++++++++--- internal/service/meta/meta_service.go | 103 +++++++++++----------------------- 2 files changed, 111 insertions(+), 77 deletions(-) diff --git a/internal/schema/meta_schema.go b/internal/schema/meta_schema.go index d5fa46ff..60f32ba0 100644 --- a/internal/schema/meta_schema.go +++ b/internal/schema/meta_schema.go @@ -31,14 +31,85 @@ type GetReactionReq struct { UserID string `json:"-"` } -type ReactionSummaryMeta map[string][]string +// ReactionsSummaryMeta reactions summary meta +type ReactionsSummaryMeta struct { + Reactions []*ReactionSummaryMeta `json:"reactions"` +} + +// ReactionSummaryMeta reaction summary meta +type ReactionSummaryMeta struct { + Emoji string `json:"emoji"` + UserIDs []string `json:"user_ids"` +} + +// AddReactionSummary add user operation to reaction summary +func (r *ReactionsSummaryMeta) AddReactionSummary(emoji, userID string) { + for _, reaction := range r.Reactions { + if reaction.Emoji != emoji { + continue + } + exist := false + for _, id := range reaction.UserIDs { + if id == userID { + exist = true + break + } + } + if !exist { + reaction.UserIDs = append(reaction.UserIDs, userID) + } + return + } + r.Reactions = append(r.Reactions, &ReactionSummaryMeta{ + Emoji: emoji, + UserIDs: []string{userID}, + }) +} + +// RemoveReactionSummary remove user operation from reaction summary +func (r *ReactionsSummaryMeta) RemoveReactionSummary(emoji, userID string) { + for _, reaction := range r.Reactions { + if reaction.Emoji != emoji { + continue + } + updated := make([]string, 0, len(r.Reactions)) + for _, id := range reaction.UserIDs { + if id != userID { + updated = append(updated, id) + } + } + reaction.UserIDs = updated + } +} + +// CheckUserInReactionSummary check user's operation if in reaction summary +func (r *ReactionsSummaryMeta) CheckUserInReactionSummary(emoji, userID string) bool { + for _, reaction := range r.Reactions { + if reaction.Emoji != emoji { + continue + } + for _, id := range reaction.UserIDs { + if id == userID { + return true + } + } + } + return false +} -type ReactionItem struct { - Count int `json:"count"` - Tooltip string `json:"tooltip"` - IsActive bool `json:"is_active"` +// GetReactionByObjectIdResp get reaction by object id response +type GetReactionByObjectIdResp struct { + ReactionSummary []*ReactionRespItem `json:"reaction_summary"` } -type ReactionResp struct { - ReactionSummary map[string]*ReactionItem `json:"reaction_summary"` +// ReactionRespItem reaction response item +type ReactionRespItem struct { + // Emoji is the reaction emoji + Emoji string `json:"emoji"` + // Count is the number of users who reacted + Count int `json:"count"` + // Tooltip is the user's name who reacted + Tooltip string `json:"tooltip"` + // IsActive is if current user has reacted + IsActive bool `json:"is_active"` } diff --git a/internal/service/meta/meta_service.go b/internal/service/meta/meta_service.go index fa208729..1026b173 100644 --- a/internal/service/meta/meta_service.go +++ b/internal/service/meta/meta_service.go @@ -58,7 +58,7 @@ func NewMetaService(metaCommonService *metacommon.MetaCommonService, userCommon } // GetReactionByObjectId get reaction -func (ms *MetaService) GetReactionByObjectId(ctx context.Context, req *schema.GetReactionReq) (resp *schema.ReactionResp, err error) { +func (ms *MetaService) GetReactionByObjectId(ctx context.Context, req *schema.GetReactionReq) (resp *schema.GetReactionByObjectIdResp, err error) { reactionMeta, err := ms.metaCommonService.GetMetaByObjectIdAndKey(ctx, req.ObjectID, entity.ObjectReactSummaryKey) // if not exist, return nil @@ -71,16 +71,16 @@ func (ms *MetaService) GetReactionByObjectId(ctx context.Context, req *schema.Ge } } - var reaction schema.ReactionSummaryMeta + var reaction schema.ReactionsSummaryMeta err = json.Unmarshal([]byte(reactionMeta.Value), &reaction) if err != nil { return nil, err } - return ms.convertToReactionResp(ctx, req.UserID, reaction) + return ms.convertToReactionResp(ctx, req.UserID, &reaction) } // AddOrUpdateReaction add or update reaction -func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.UpdateReactionReq) (resp *schema.ReactionResp, err error) { +func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.UpdateReactionReq) (resp *schema.GetReactionByObjectIdResp, err error) { // check if object exist and it's answer or question objectType, err := obj.GetObjectTypeStrByObjectID(req.ObjectID) if err != nil { @@ -107,23 +107,18 @@ func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.Upda } // add or update - var reaction schema.ReactionSummaryMeta + reactions := &schema.ReactionsSummaryMeta{} err = ms.metaCommonService.AddOrUpdateMetaByObjectIdAndKey(ctx, req.ObjectID, entity.ObjectReactSummaryKey, func(meta *entity.Meta, exist bool) (*entity.Meta, error) { // if not exist, create new one - if !exist { - reaction = schema.ReactionSummaryMeta{} - } else { - err = json.Unmarshal([]byte(meta.Value), &reaction) - if err != nil { - return nil, err - } + if exist { + _ = json.Unmarshal([]byte(meta.Value), reactions) } // update reaction - ms.updateReaction(req, reaction) + ms.updateReaction(req, reactions) // write back to meta repo - reactSumBytes, err := json.Marshal(reaction) + reactSumBytes, err := json.Marshal(reactions) if err != nil { return nil, err } @@ -139,7 +134,7 @@ func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.Upda return nil, myErrors.InternalServer(reason.DatabaseError).WithError(err) } - resp, err = ms.convertToReactionResp(ctx, req.UserID, reaction) + resp, err = ms.convertToReactionResp(ctx, req.UserID, reactions) if err != nil { return nil, err } @@ -148,80 +143,48 @@ func (ms *MetaService) AddOrUpdateReaction(ctx context.Context, req *schema.Upda } // updateReaction update reaction -func (ms *MetaService) updateReaction(req *schema.UpdateReactionReq, reaction schema.ReactionSummaryMeta) { - emojiUserIds, ok := reaction[req.Emoji] - - if !ok { - emojiUserIds = make([]string, 0) - } - - found := false - for _, item := range emojiUserIds { - if item == req.UserID { - found = true - break - } - } - - removeItem := func(arr []string, target string) []string { - result := make([]string, 0, len(arr)) - - for _, item := range arr { - if item != target { - result = append(result, item) - } - } - - return result - } - - if req.Reaction == "activate" && !found { - emojiUserIds = append(emojiUserIds, req.UserID) - } else if req.Reaction == "deactivate" && found { - emojiUserIds = removeItem(emojiUserIds, req.UserID) +func (ms *MetaService) updateReaction(req *schema.UpdateReactionReq, reactions *schema.ReactionsSummaryMeta) { + if req.Reaction == "activate" { + reactions.AddReactionSummary(req.Emoji, req.UserID) + } else if req.Reaction == "deactivate" { + reactions.RemoveReactionSummary(req.Emoji, req.UserID) } - - reaction[req.Emoji] = emojiUserIds } -func (ms *MetaService) convertToReactionResp(ctx context.Context, userId string, reaction schema.ReactionSummaryMeta) (*schema.ReactionResp, error) { +func (ms *MetaService) convertToReactionResp(ctx context.Context, userId string, r *schema.ReactionsSummaryMeta) ( + resp *schema.GetReactionByObjectIdResp, err error) { lang := handler.GetLangByCtx(ctx) - resp := &schema.ReactionResp{ - ReactionSummary: make(map[string]*schema.ReactionItem), - } - isInArray := func(arr []string, target string) bool { - for _, str := range arr { - if str == target { - return true - } - } - return false + resp = &schema.GetReactionByObjectIdResp{ + ReactionSummary: make([]*schema.ReactionRespItem, 0), } // traverse map and convert to username - for emoji, userIds := range reaction { - resp.ReactionSummary[emoji] = &schema.ReactionItem{ - IsActive: isInArray(userIds, userId), + for _, reaction := range r.Reactions { + item := &schema.ReactionRespItem{ + Emoji: reaction.Emoji, + IsActive: r.CheckUserInReactionSummary(reaction.Emoji, userId), } - userNames := make([]string, 0) - userBasicInfos, err := ms.userCommon.BatchUserBasicInfoByID(ctx, userIds) - resp.ReactionSummary[emoji].Count = len(userBasicInfos) + + usernames := make([]string, 0) + userBasicInfos, err := ms.userCommon.BatchUserBasicInfoByID(ctx, reaction.UserIDs) + item.Count = len(userBasicInfos) if err != nil { return resp, err } // get username for _, userBasicInfo := range userBasicInfos { - userNames = append(userNames, userBasicInfo.Username) - if len(userNames) == 5 && len(userBasicInfos) > 5 { - resp.ReactionSummary[emoji].Tooltip = translator.TrWithData(lang, constant.ReactionTooltipLabel, map[string]string{ + usernames = append(usernames, userBasicInfo.Username) + if len(usernames) == 5 && len(userBasicInfos) > 5 { + item.Tooltip = translator.TrWithData(lang, constant.ReactionTooltipLabel, map[string]string{ "Count": strconv.Itoa(len(userBasicInfos) - 5), - "Names": strings.Join(userNames, ", "), + "Names": strings.Join(usernames, ", "), }) break } } if len(userBasicInfos) <= 5 { - resp.ReactionSummary[emoji].Tooltip = strings.Join(userNames, ", ") + item.Tooltip = strings.Join(usernames, ", ") } + resp.ReactionSummary = append(resp.ReactionSummary, item) } return resp, nil
