From 879c781e35d2b7041c322b511c8b2fe6c23c2e52 Mon Sep 17 00:00:00 2001 From: LinkinStars Date: Thu, 25 May 2023 20:13:18 +0800 Subject: [PATCH] refactor(config): remove all config global variables and cache all config related data --- cmd/wire_gen.go | 38 +++-- internal/base/constant/config_key.go | 4 +- internal/entity/config_entity.go | 38 ++++- internal/repo/activity/activity_repo.go | 42 +++-- internal/repo/activity/user_active_repo.go | 49 +++--- internal/repo/activity/vote_repo.go | 26 +-- .../repo/activity_common/activity_repo.go | 39 +++-- internal/repo/config/config_repo.go | 158 +++++++----------- internal/repo/rank/user_rank_repo.go | 19 +-- internal/repo/reason/reason_repo.go | 20 +-- internal/repo/repo_test/config_repo_test.go | 15 +- internal/repo/repo_test/reason_repo_test.go | 3 +- internal/repo/repo_test/user_repo_test.go | 27 ++- internal/repo/user/user_repo.go | 9 +- internal/service/activity/activity.go | 15 +- .../service/activity_type/activity_type.go | 17 +- internal/service/config/config_service.go | 80 ++++++++- .../service/dashboard/dashboard_service.go | 17 +- internal/service/export/email_service.go | 22 +-- .../plugin_common/plugin_common_service.go | 10 +- internal/service/provider.go | 2 + internal/service/question_common/question.go | 17 +- internal/service/rank/rank_service.go | 8 +- .../service/report_admin/report_backyard.go | 20 ++- .../report_handle_admin/report_handle.go | 30 ++-- internal/service/siteinfo/siteinfo_service.go | 12 +- internal/service/vote_service.go | 11 +- 27 files changed, 421 insertions(+), 327 deletions(-) diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 0a8d27c5..58a7c5ce 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -51,6 +51,7 @@ import ( "github.com/answerdev/answer/internal/service/collection_common" comment2 "github.com/answerdev/answer/internal/service/comment" "github.com/answerdev/answer/internal/service/comment_common" + config2 "github.com/answerdev/answer/internal/service/config" "github.com/answerdev/answer/internal/service/dashboard" export2 "github.com/answerdev/answer/internal/service/export" "github.com/answerdev/answer/internal/service/follow" @@ -108,14 +109,15 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, langController := controller.NewLangController(i18nTranslator, siteInfoCommonService) authRepo := auth.NewAuthRepo(dataData) authService := auth2.NewAuthService(authRepo) - configRepo := config.NewConfigRepo(dataData) - userRepo := user.NewUserRepo(dataData, configRepo) + userRepo := user.NewUserRepo(dataData) uniqueIDRepo := unique.NewUniqueIDRepo(dataData) - activityRepo := activity_common.NewActivityRepo(dataData, uniqueIDRepo, configRepo) - userRankRepo := rank.NewUserRankRepo(dataData, configRepo) - userActiveActivityRepo := activity.NewUserActiveActivityRepo(dataData, activityRepo, userRankRepo, configRepo) + configRepo := config.NewConfigRepo(dataData) + configService := config2.NewConfigService(configRepo) + activityRepo := activity_common.NewActivityRepo(dataData, uniqueIDRepo, configService) + userRankRepo := rank.NewUserRankRepo(dataData, configService) + userActiveActivityRepo := activity.NewUserActiveActivityRepo(dataData, activityRepo, userRankRepo, configService) emailRepo := export.NewEmailRepo(dataData) - emailService := export2.NewEmailService(configRepo, emailRepo, siteInfoRepo) + emailService := export2.NewEmailService(configService, emailRepo, siteInfoRepo) userRoleRelRepo := role.NewUserRoleRelRepo(dataData) roleRepo := role.NewRoleRepo(dataData) roleService := role2.NewRoleService(roleRepo) @@ -143,13 +145,13 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, commentService := comment2.NewCommentService(commentRepo, commentCommonRepo, userCommon, objService, voteRepo, emailService, userRepo) rolePowerRelRepo := role.NewRolePowerRelRepo(dataData) rolePowerRelService := role2.NewRolePowerRelService(rolePowerRelRepo, userRoleRelService) - rankService := rank2.NewRankService(userCommon, userRankRepo, objService, userRoleRelService, rolePowerRelService, configRepo) + rankService := rank2.NewRankService(userCommon, userRankRepo, objService, userRoleRelService, rolePowerRelService, configService) commentController := controller.NewCommentController(commentService, rankService) reportRepo := report.NewReportRepo(dataData, uniqueIDRepo) reportService := report2.NewReportService(reportRepo, objService) reportController := controller.NewReportController(reportService, rankService) - serviceVoteRepo := activity.NewVoteRepo(dataData, uniqueIDRepo, configRepo, activityRepo, userRankRepo, voteRepo) - voteService := service.NewVoteService(serviceVoteRepo, uniqueIDRepo, configRepo, questionRepo, answerRepo, commentCommonRepo, objService) + serviceVoteRepo := activity.NewVoteRepo(dataData, uniqueIDRepo, configService, activityRepo, userRankRepo, voteRepo) + voteService := service.NewVoteService(serviceVoteRepo, uniqueIDRepo, configService, questionRepo, answerRepo, commentCommonRepo, objService) voteController := controller.NewVoteController(voteService, rankService) followRepo := activity_common.NewFollowRepo(dataData, uniqueIDRepo, activityRepo) tagService := tag2.NewTagService(tagRepo, tagCommonService, revisionService, followRepo, siteInfoCommonService) @@ -163,7 +165,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, answerCommon := answercommon.NewAnswerCommon(answerRepo) metaRepo := meta.NewMetaRepo(dataData) metaService := meta2.NewMetaService(metaRepo) - questionCommon := questioncommon.NewQuestionCommon(questionRepo, answerRepo, voteRepo, followRepo, tagCommonService, userCommon, collectionCommon, answerCommon, metaService, configRepo) + questionCommon := questioncommon.NewQuestionCommon(questionRepo, answerRepo, voteRepo, followRepo, tagCommonService, userCommon, collectionCommon, answerCommon, metaService, configService) collectionService := service.NewCollectionService(collectionRepo, collectionGroupRepo, questionCommon) collectionController := controller.NewCollectionController(collectionService) answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo) @@ -172,7 +174,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, userRepo, revisionService, metaService, collectionCommon, answerActivityService, dataData, emailService) answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService) questionController := controller.NewQuestionController(questionService, answerService, rankService) - dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData) + dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configService, siteInfoCommonService, serviceConf, dataData) answerController := controller.NewAnswerController(answerService, rankService, dashboardService) searchParser := search_parser.NewSearchParser(tagCommonService, userCommon) searchRepo := search_common.NewSearchRepo(dataData, uniqueIDRepo, userCommon) @@ -181,17 +183,17 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, serviceRevisionService := service.NewRevisionService(revisionRepo, userCommon, questionCommon, answerService, objService, questionRepo, answerRepo, tagRepo, tagCommonService) revisionController := controller.NewRevisionController(serviceRevisionService, rankService) rankController := controller.NewRankController(rankService) - reportHandle := report_handle_admin.NewReportHandle(questionCommon, commentRepo, configRepo) - reportAdminService := report_admin.NewReportAdminService(reportRepo, userCommon, answerRepo, questionRepo, commentCommonRepo, reportHandle, configRepo, objService) + reportHandle := report_handle_admin.NewReportHandle(questionCommon, commentRepo, configService) + reportAdminService := report_admin.NewReportAdminService(reportRepo, userCommon, answerRepo, questionRepo, commentCommonRepo, reportHandle, configService, objService) controller_adminReportController := controller_admin.NewReportController(reportAdminService) userAdminRepo := user.NewUserAdminRepo(dataData, authRepo) userAdminService := user_admin.NewUserAdminService(userAdminRepo, userRoleRelService, authService, userCommon, userActiveActivityRepo) userAdminController := controller_admin.NewUserAdminController(userAdminService) - reasonRepo := reason.NewReasonRepo(configRepo) + reasonRepo := reason.NewReasonRepo(configService) reasonService := reason2.NewReasonService(reasonRepo) reasonController := controller.NewReasonController(reasonService) themeController := controller_admin.NewThemeController() - siteInfoService := siteinfo.NewSiteInfoService(siteInfoRepo, siteInfoCommonService, emailService, tagCommonService, configRepo) + siteInfoService := siteinfo.NewSiteInfoService(siteInfoRepo, siteInfoCommonService, emailService, tagCommonService, configService) siteInfoController := controller_admin.NewSiteInfoController(siteInfoService) siteinfoController := controller.NewSiteinfoController(siteInfoCommonService) notificationRepo := notification.NewNotificationRepo(dataData) @@ -201,13 +203,13 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, dashboardController := controller.NewDashboardController(dashboardService) uploadController := controller.NewUploadController(uploaderService) activityCommon := activity_common2.NewActivityCommon(activityRepo) - activityActivityRepo := activity.NewActivityRepo(dataData) + activityActivityRepo := activity.NewActivityRepo(dataData, configService) commentCommonService := comment_common.NewCommentCommonService(commentCommonRepo) - activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaService) + activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaService, configService) activityController := controller.NewActivityController(activityCommon, activityService) roleController := controller_admin.NewRoleController(roleService) pluginConfigRepo := plugin_config.NewPluginConfigRepo(dataData) - pluginCommonService := plugin_common.NewPluginCommonService(pluginConfigRepo, configRepo) + pluginCommonService := plugin_common.NewPluginCommonService(pluginConfigRepo, configService) pluginController := controller_admin.NewPluginController(pluginCommonService) answerAPIRouter := router.NewAnswerAPIRouter(langController, userController, commentController, reportController, voteController, tagController, followController, collectionController, questionController, answerController, searchController, revisionController, rankController, controller_adminReportController, userAdminController, reasonController, themeController, siteInfoController, siteinfoController, notificationController, dashboardController, uploadController, activityController, roleController, pluginController) swaggerRouter := router.NewSwaggerRouter(swaggerConf) diff --git a/internal/base/constant/config_key.go b/internal/base/constant/config_key.go index a184badf..fb8be903 100644 --- a/internal/base/constant/config_key.go +++ b/internal/base/constant/config_key.go @@ -1,5 +1,7 @@ package constant const ( - PluginStatus = "plugin.status" + PluginStatus = "plugin.status" + ConfigID2KEYCacheKeyPrefix = "answer:config:id:" + ConfigKEY2ContentCacheKeyPrefix = "answer:config:key:" ) diff --git a/internal/entity/config_entity.go b/internal/entity/config_entity.go index 361e7acc..908903a1 100644 --- a/internal/entity/config_entity.go +++ b/internal/entity/config_entity.go @@ -1,5 +1,11 @@ package entity +import ( + "encoding/json" + + "github.com/answerdev/answer/pkg/converter" +) + // Config config type Config struct { ID int `xorm:"not null pk autoincr INT(11) id"` @@ -8,6 +14,36 @@ type Config struct { } // TableName config table name -func (Config) TableName() string { +func (c *Config) TableName() string { return "config" } + +func (c *Config) BuildByJSON(data []byte) { + cf := &Config{} + _ = json.Unmarshal(data, cf) + c.ID = cf.ID + c.Key = cf.Key + c.Value = cf.Value +} + +func (c *Config) JsonString() string { + data, _ := json.Marshal(c) + return string(data) +} + +// GetIntValue get int value +func (c *Config) GetIntValue() int { + return converter.StringToInt(c.Value) +} + +// GetArrayStringValue get array string value +func (c *Config) GetArrayStringValue() []string { + var arr []string + _ = json.Unmarshal([]byte(c.Value), &arr) + return arr +} + +// GetByteValue get byte value +func (c *Config) GetByteValue() []byte { + return []byte(c.Value) +} diff --git a/internal/repo/activity/activity_repo.go b/internal/repo/activity/activity_repo.go index c1971eab..1c364dbf 100644 --- a/internal/repo/activity/activity_repo.go +++ b/internal/repo/activity/activity_repo.go @@ -8,22 +8,26 @@ import ( "github.com/answerdev/answer/internal/base/data" "github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/entity" - "github.com/answerdev/answer/internal/repo/config" "github.com/answerdev/answer/internal/service/activity" + "github.com/answerdev/answer/internal/service/config" "github.com/segmentfault/pacman/errors" + "github.com/segmentfault/pacman/log" ) // activityRepo activity repository type activityRepo struct { - data *data.Data + data *data.Data + configService *config.ConfigService } // NewActivityRepo new repository func NewActivityRepo( data *data.Data, + configService *config.ConfigService, ) activity.ActivityRepo { return &activityRepo{ - data: data, + data: data, + configService: configService, } } @@ -33,17 +37,7 @@ func (ar *activityRepo) GetObjectAllActivity(ctx context.Context, objectID strin session := ar.data.DB.Context(ctx).Desc("created_at") if !showVote { - var activityTypeNotShown []int - for _, obj := range []string{constant.AnswerObjectType, constant.QuestionObjectType, constant.CommentObjectType} { - for _, act := range []string{ - constant.ActVotedDown, - constant.ActVotedUp, - constant.ActVoteDown, - constant.ActVoteUp, - } { - activityTypeNotShown = append(activityTypeNotShown, config.Key2IDMapping[fmt.Sprintf("%s.%s", obj, act)]) - } - } + activityTypeNotShown := ar.getAllActivityType(ctx) session.NotIn("activity_type", activityTypeNotShown) } err = session.Find(&activityList, &entity.Activity{OriginalObjectID: objectID}) @@ -52,3 +46,23 @@ func (ar *activityRepo) GetObjectAllActivity(ctx context.Context, objectID strin } return activityList, nil } + +func (ar *activityRepo) getAllActivityType(ctx context.Context) (activityTypes []int) { + var activityTypeNotShown []int + for _, obj := range []string{constant.AnswerObjectType, constant.QuestionObjectType, constant.CommentObjectType} { + for _, act := range []string{ + constant.ActVotedDown, + constant.ActVotedUp, + constant.ActVoteDown, + constant.ActVoteUp, + } { + id, err := ar.configService.GetIDByKey(ctx, fmt.Sprintf("%s.%s", obj, act)) + if err != nil { + log.Error(err) + } else { + activityTypeNotShown = append(activityTypeNotShown, id) + } + } + } + return activityTypeNotShown +} diff --git a/internal/repo/activity/user_active_repo.go b/internal/repo/activity/user_active_repo.go index b70a0dac..0f6099d1 100644 --- a/internal/repo/activity/user_active_repo.go +++ b/internal/repo/activity/user_active_repo.go @@ -16,10 +16,10 @@ import ( // UserActiveActivityRepo answer accepted type UserActiveActivityRepo struct { - data *data.Data - activityRepo activity_common.ActivityRepo - userRankRepo rank.UserRankRepo - configRepo config.ConfigRepo + data *data.Data + activityRepo activity_common.ActivityRepo + userRankRepo rank.UserRankRepo + configService *config.ConfigService } const ( @@ -31,37 +31,36 @@ func NewUserActiveActivityRepo( data *data.Data, activityRepo activity_common.ActivityRepo, userRankRepo rank.UserRankRepo, - configRepo config.ConfigRepo, + configService *config.ConfigService, ) activity.UserActiveActivityRepo { return &UserActiveActivityRepo{ - data: data, - activityRepo: activityRepo, - userRankRepo: userRankRepo, - configRepo: configRepo, + data: data, + activityRepo: activityRepo, + userRankRepo: userRankRepo, + configService: configService, } } // UserActive accept other answer func (ar *UserActiveActivityRepo) UserActive(ctx context.Context, userID string) (err error) { + cfg, err := ar.configService.GetConfigByKey(ctx, UserActivated) + if err != nil { + return err + } + activityType := cfg.ID + deltaRank := cfg.GetIntValue() + addActivity := &entity.Activity{ + UserID: userID, + ObjectID: "0", + OriginalObjectID: "0", + ActivityType: activityType, + Rank: deltaRank, + HasRank: 1, + } + _, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) { session = session.Context(ctx) - activityType, err := ar.configRepo.GetConfigType(UserActivated) - if err != nil { - return nil, err - } - deltaRank, err := ar.configRepo.GetInt(UserActivated) - if err != nil { - return nil, err - } - addActivity := &entity.Activity{ - UserID: userID, - ObjectID: "0", - OriginalObjectID: "0", - ActivityType: activityType, - Rank: deltaRank, - HasRank: 1, - } _, exists, err := ar.activityRepo.GetActivity(ctx, session, "0", addActivity.UserID, activityType) if err != nil { return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() diff --git a/internal/repo/activity/vote_repo.go b/internal/repo/activity/vote_repo.go index ba0d774d..58bf1510 100644 --- a/internal/repo/activity/vote_repo.go +++ b/internal/repo/activity/vote_repo.go @@ -30,30 +30,30 @@ import ( // VoteRepo activity repository type VoteRepo struct { - data *data.Data - uniqueIDRepo unique.UniqueIDRepo - configRepo config.ConfigRepo - activityRepo activity_common.ActivityRepo - userRankRepo rank.UserRankRepo - voteCommon activity_common.VoteRepo + data *data.Data + uniqueIDRepo unique.UniqueIDRepo + configService *config.ConfigService + activityRepo activity_common.ActivityRepo + userRankRepo rank.UserRankRepo + voteCommon activity_common.VoteRepo } // NewVoteRepo new repository func NewVoteRepo( data *data.Data, uniqueIDRepo unique.UniqueIDRepo, - configRepo config.ConfigRepo, + configService *config.ConfigService, activityRepo activity_common.ActivityRepo, userRankRepo rank.UserRankRepo, voteCommon activity_common.VoteRepo, ) service.VoteRepo { return &VoteRepo{ - data: data, - uniqueIDRepo: uniqueIDRepo, - configRepo: configRepo, - activityRepo: activityRepo, - userRankRepo: userRankRepo, - voteCommon: voteCommon, + data: data, + uniqueIDRepo: uniqueIDRepo, + configService: configService, + activityRepo: activityRepo, + userRankRepo: userRankRepo, + voteCommon: voteCommon, } } diff --git a/internal/repo/activity_common/activity_repo.go b/internal/repo/activity_common/activity_repo.go index 3717ae0e..20a37181 100644 --- a/internal/repo/activity_common/activity_repo.go +++ b/internal/repo/activity_common/activity_repo.go @@ -21,34 +21,37 @@ import ( // ActivityRepo activity repository type ActivityRepo struct { - data *data.Data - uniqueIDRepo unique.UniqueIDRepo - configRepo config.ConfigRepo + data *data.Data + uniqueIDRepo unique.UniqueIDRepo + configService *config.ConfigService } // NewActivityRepo new repository func NewActivityRepo( data *data.Data, uniqueIDRepo unique.UniqueIDRepo, - configRepo config.ConfigRepo, + configService *config.ConfigService, ) activity_common.ActivityRepo { return &ActivityRepo{ - data: data, - uniqueIDRepo: uniqueIDRepo, - configRepo: configRepo, + data: data, + uniqueIDRepo: uniqueIDRepo, + configService: configService, } } -func (ar *ActivityRepo) GetActivityTypeByObjID(ctx context.Context, objectID string, action string) (activityType, rank, hasRank int, err error) { +func (ar *ActivityRepo) GetActivityTypeByObjID(ctx context.Context, objectID string, action string) ( + activityType, rank, hasRank int, err error) { objectKey, err := obj.GetObjectTypeStrByObjectID(objectID) if err != nil { return } confKey := fmt.Sprintf("%s.%s", objectKey, action) - activityType, _ = ar.configRepo.GetConfigType(confKey) - - rank, err = ar.configRepo.GetInt(confKey) + cfg, err := ar.configService.GetConfigByKey(ctx, confKey) + if err != nil { + return + } + rank = cfg.GetIntValue() hasRank = 0 if rank != 0 { hasRank = 1 @@ -57,20 +60,20 @@ func (ar *ActivityRepo) GetActivityTypeByObjID(ctx context.Context, objectID str } func (ar *ActivityRepo) GetActivityTypeByObjKey(ctx context.Context, objectKey, action string) (activityType int, err error) { - confKey := fmt.Sprintf("%s.%s", objectKey, action) - activityType, err = ar.configRepo.GetConfigType(confKey) + configKey := fmt.Sprintf("%s.%s", objectKey, action) + cfg, err := ar.configService.GetConfigByKey(ctx, configKey) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } - return + return cfg.ID, nil } func (ar *ActivityRepo) GetActivityTypeByConfigKey(ctx context.Context, configKey string) (activityType int, err error) { - activityType, err = ar.configRepo.GetConfigType(configKey) + cfg, err := ar.configService.GetConfigByKey(ctx, configKey) if err != nil { err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } - return + return cfg.ID, nil } func (ar *ActivityRepo) GetActivity(ctx context.Context, session *xorm.Session, @@ -134,9 +137,9 @@ func (ar *ActivityRepo) GetUsersWhoHasVoteMost( actIDs := make([]int, 0) for _, act := range activity_type.ActivityTypeList { - configType, err := ar.configRepo.GetConfigType(act) + cfg, err := ar.configService.GetConfigByKey(ctx, act) if err == nil { - actIDs = append(actIDs, configType) + actIDs = append(actIDs, cfg.ID) } } diff --git a/internal/repo/config/config_repo.go b/internal/repo/config/config_repo.go index 77d63773..6b7bb98e 100644 --- a/internal/repo/config/config_repo.go +++ b/internal/repo/config/config_repo.go @@ -2,29 +2,20 @@ package config import ( "context" - "encoding/json" "fmt" - "sync" - - "github.com/answerdev/answer/internal/service/config" - "github.com/answerdev/answer/pkg/converter" + "github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/base/data" "github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/entity" + "github.com/answerdev/answer/internal/service/config" "github.com/segmentfault/pacman/errors" -) - -var ( - Key2ValueMapping = make(map[string]interface{}) - Key2IDMapping = make(map[string]int) - ID2KeyMapping = make(map[int]string) + "github.com/segmentfault/pacman/log" ) // configRepo config repository type configRepo struct { data *data.Data - mu sync.Mutex } // NewConfigRepo new repository @@ -32,110 +23,87 @@ func NewConfigRepo(data *data.Data) config.ConfigRepo { repo := &configRepo{ data: data, } - repo.init() return repo } -// init initializes the Key2ValueMapping map data structures -func (cr *configRepo) init() { - cr.mu.Lock() - defer cr.mu.Unlock() - rows := &[]entity.Config{} - err := cr.data.DB.Context(context.TODO()).Find(rows) - if err == nil { - for _, row := range *rows { - Key2ValueMapping[row.Key] = row.Value - Key2IDMapping[row.Key] = row.ID - ID2KeyMapping[row.ID] = row.Key +func (cr configRepo) GetConfigByID(ctx context.Context, id int) (c *entity.Config, err error) { + cacheKey := fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, id) + if cacheData, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && len(cacheData) > 0 { + c = &entity.Config{} + c.BuildByJSON([]byte(cacheData)) + if c.ID > 0 { + return c, nil } } -} -// Get Base method for getting the config value -// Key string -func (cr *configRepo) Get(key string) (interface{}, error) { - value, ok := Key2ValueMapping[key] - if ok { - return value, nil - } else { - return value, errors.InternalServer(reason.DatabaseError).WithMsg(fmt.Sprintf("no such config key: %v", key)) - } -} - -// GetString method for getting the config value to string -// key string -func (cr *configRepo) GetString(key string) (string, error) { - value, err := cr.Get(key) + c = &entity.Config{} + exist, err := cr.data.DB.ID(id).Get(c) if err != nil { - return "", err + return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } - str, ok := value.(string) - if !ok { - return "", errors.InternalServer(reason.DatabaseError).WithMsg(fmt.Sprintf("config value is wrong type: %v", key)) + if !exist { + return nil, errors.BadRequest(reason.ObjectNotFound) } - return str, nil + + // update cache + if err := cr.data.Cache.SetString(ctx, cacheKey, c.JsonString(), -1); err != nil { + log.Error(err) + } + return c, nil } -// GetInt method for getting the config value to int64 -// key string -func (cr *configRepo) GetInt(key string) (int, error) { - value, err := cr.GetString(key) - if err != nil { - return 0, err +func (cr configRepo) GetConfigByKey(ctx context.Context, key string) (c *entity.Config, err error) { + cacheKey := constant.ConfigKEY2ContentCacheKeyPrefix + key + if cacheData, err := cr.data.Cache.GetString(ctx, cacheKey); err == nil && len(cacheData) > 0 { + c = &entity.Config{} + c.BuildByJSON([]byte(cacheData)) + if c.ID > 0 { + return c, nil + } } - return converter.StringToInt(value), nil + + c = &entity.Config{Key: key} + exist, err := cr.data.DB.Context(ctx).Get(c) + if err != nil { + return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() + } + if !exist { + return nil, errors.BadRequest(reason.ObjectNotFound) + } + + // update cache + if err := cr.data.Cache.SetString(ctx, cacheKey, c.JsonString(), -1); err != nil { + log.Error(err) + } + return c, nil } -// GetArrayString method for getting the config value to string array -func (cr *configRepo) GetArrayString(key string) ([]string, error) { - arr := &[]string{} - value, err := cr.GetString(key) +func (cr configRepo) UpdateConfig(ctx context.Context, key string, value string) (err error) { + // check if key exists + cf := &entity.Config{} + exist, err := cr.data.DB.Context(ctx).Get(cf) if err != nil { - return nil, err + return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } - err = json.Unmarshal([]byte(value), arr) - return *arr, err -} - -// GetConfigType method for getting the config type -func (cr *configRepo) GetConfigType(key string) (int, error) { - value, ok := Key2IDMapping[key] - if !ok { - return 0, errors.InternalServer(reason.DatabaseError).WithMsg(fmt.Sprintf("no such config type: %v", key)) - } - return value, nil -} - -// GetJsonConfigByIDAndSetToObject get config key from config id -func (cr *configRepo) GetJsonConfigByIDAndSetToObject(id int, object any) (err error) { - key, ok := ID2KeyMapping[id] - if !ok { - return errors.InternalServer(reason.DatabaseError).WithMsg(fmt.Sprintf("no such config id: %v", id)) + if !exist { + return errors.BadRequest(reason.ObjectNotFound) } - conf, err := cr.Get(key) + // update database + _, err = cr.data.DB.Context(ctx).ID(cf.ID).Update(&entity.Config{Value: value}) if err != nil { - return errors.InternalServer(reason.DatabaseError).WithError(err) + return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() } - str, ok := conf.(string) - if !ok { - return errors.InternalServer(reason.DatabaseError).WithMsg(fmt.Sprintf("no such config id: %v", id)) + + cacheVal := cf.JsonString() + // update cache + if err := cr.data.Cache.SetString(ctx, + constant.ConfigKEY2ContentCacheKeyPrefix+key, cacheVal, -1); err != nil { + log.Error(err) } - err = json.Unmarshal([]byte(str), object) - if err != nil { - err = errors.InternalServer(reason.DatabaseError).WithMsg(fmt.Sprintf("no such config id: %v", id)) - } - return -} - -// SetConfig set config -func (cr *configRepo) SetConfig(ctx context.Context, key, value string) (err error) { - id := Key2IDMapping[key] - _, err = cr.data.DB.Context(ctx).ID(id).Update(&entity.Config{Value: value}) - if err != nil { - err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack() - } else { - Key2ValueMapping[key] = value + if err := cr.data.Cache.SetString(ctx, + fmt.Sprintf("%s%d", constant.ConfigID2KEYCacheKeyPrefix, cf.ID), cacheVal, -1); err != nil { + log.Error(err) } return } diff --git a/internal/repo/rank/user_rank_repo.go b/internal/repo/rank/user_rank_repo.go index beac7ec6..06570fec 100644 --- a/internal/repo/rank/user_rank_repo.go +++ b/internal/repo/rank/user_rank_repo.go @@ -19,15 +19,15 @@ import ( // UserRankRepo user rank repository type UserRankRepo struct { - data *data.Data - configRepo config.ConfigRepo + data *data.Data + configService *config.ConfigService } // NewUserRankRepo new repository -func NewUserRankRepo(data *data.Data, configRepo config.ConfigRepo) rank.UserRankRepo { +func NewUserRankRepo(data *data.Data, configService *config.ConfigService) rank.UserRankRepo { return &UserRankRepo{ - data: data, - configRepo: configRepo, + data: data, + configService: configService, } } @@ -94,14 +94,13 @@ func (ur *UserRankRepo) checkUserTodayRank(ctx context.Context, session *xorm.Session, userID string, activityType int, ) (isReachStandard bool, err error) { // exclude daily rank - exclude, _ := ur.configRepo.GetArrayString("daily_rank_limit.exclude") + exclude, _ := ur.configService.GetArrayStringValue(ctx, "daily_rank_limit.exclude") for _, item := range exclude { - var excludeActivityType int - excludeActivityType, err = ur.configRepo.GetInt(item) + cfg, err := ur.configService.GetConfigByKey(ctx, item) if err != nil { return false, err } - if activityType == excludeActivityType { + if activityType == cfg.ID { return false, nil } } @@ -121,7 +120,7 @@ func (ur *UserRankRepo) checkUserTodayRank(ctx context.Context, } // max rank - maxDailyRank, err := ur.configRepo.GetInt("daily_rank_limit") + maxDailyRank, err := ur.configService.GetIntValue(ctx, "daily_rank_limit") if err != nil { return false, err } diff --git a/internal/repo/reason/reason_repo.go b/internal/repo/reason/reason_repo.go index b9b8b4bd..251d1752 100644 --- a/internal/repo/reason/reason_repo.go +++ b/internal/repo/reason/reason_repo.go @@ -13,12 +13,12 @@ import ( ) type reasonRepo struct { - configRepo config.ConfigRepo + configService *config.ConfigService } -func NewReasonRepo(configRepo config.ConfigRepo) reason_common.ReasonRepo { +func NewReasonRepo(configService *config.ConfigService) reason_common.ReasonRepo { return &reasonRepo{ - configRepo: configRepo, + configService: configService, } } @@ -27,31 +27,25 @@ func (rr *reasonRepo) ListReasons(ctx context.Context, objectType, action string reasonAction := fmt.Sprintf("%s.%s.reasons", objectType, action) resp = make([]*schema.ReasonItem, 0) - reasonKeys, err := rr.configRepo.GetArrayString(reasonAction) + reasonKeys, err := rr.configService.GetArrayStringValue(ctx, reasonAction) if err != nil { return nil, err } for _, reasonKey := range reasonKeys { - cfgValue, err := rr.configRepo.GetString(reasonKey) + cfg, err := rr.configService.GetConfigByKey(ctx, reasonKey) if err != nil { log.Error(err) continue } reason := &schema.ReasonItem{} - err = json.Unmarshal([]byte(cfgValue), reason) + err = json.Unmarshal(cfg.GetByteValue(), reason) if err != nil { log.Error(err) continue } reason.Translate(reasonKey, lang) - - reason.ReasonType, err = rr.configRepo.GetConfigType(reasonKey) - if err != nil { - log.Error(err) - continue - } - + reason.ReasonType = cfg.ID resp = append(resp, reason) } return resp, nil diff --git a/internal/repo/repo_test/config_repo_test.go b/internal/repo/repo_test/config_repo_test.go index 5f76ddef..233abc51 100644 --- a/internal/repo/repo_test/config_repo_test.go +++ b/internal/repo/repo_test/config_repo_test.go @@ -3,19 +3,18 @@ package repo_test import ( "testing" - "github.com/answerdev/answer/internal/repo/config" "github.com/answerdev/answer/internal/schema" "github.com/stretchr/testify/assert" ) func Test_configRepo_Get(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) _, err := configRepo.Get("email.config") assert.NoError(t, err) } func Test_configRepo_GetArrayString(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) got, err := configRepo.GetArrayString("daily_rank_limit.exclude") assert.NoError(t, err) assert.Equal(t, 1, len(got)) @@ -23,7 +22,7 @@ func Test_configRepo_GetArrayString(t *testing.T) { } func Test_configRepo_GetConfigById(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) closeInfo := &schema.GetReportTypeResp{} err := configRepo.GetJsonConfigByIDAndSetToObject(74, closeInfo) @@ -33,27 +32,27 @@ func Test_configRepo_GetConfigById(t *testing.T) { } func Test_configRepo_GetConfigType(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) configType, err := configRepo.GetConfigType("answer.accepted") assert.NoError(t, err) assert.Equal(t, 1, configType) } func Test_configRepo_GetInt(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) got, err := configRepo.GetInt("answer.accepted") assert.NoError(t, err) assert.Equal(t, 15, got) } func Test_configRepo_GetString(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) _, err := configRepo.GetString("email.config") assert.NoError(t, err) } func Test_configRepo_SetConfig(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) got, err := configRepo.GetString("email.config") assert.NoError(t, err) diff --git a/internal/repo/repo_test/reason_repo_test.go b/internal/repo/repo_test/reason_repo_test.go index 0e3e91e9..c6092e57 100644 --- a/internal/repo/repo_test/reason_repo_test.go +++ b/internal/repo/repo_test/reason_repo_test.go @@ -4,13 +4,12 @@ import ( "context" "testing" - "github.com/answerdev/answer/internal/repo/config" "github.com/answerdev/answer/internal/repo/reason" "github.com/stretchr/testify/assert" ) func Test_reasonRepo_ListReasons(t *testing.T) { - configRepo := config.NewConfigRepo(testDataSource) + configRepo := config_common.NewConfigRepo(testDataSource) reasonRepo := reason.NewReasonRepo(configRepo) reasonItems, err := reasonRepo.ListReasons(context.TODO(), "question", "close") assert.NoError(t, err) diff --git a/internal/repo/repo_test/user_repo_test.go b/internal/repo/repo_test/user_repo_test.go index 7b6f24ac..105f9885 100644 --- a/internal/repo/repo_test/user_repo_test.go +++ b/internal/repo/repo_test/user_repo_test.go @@ -5,13 +5,12 @@ import ( "testing" "github.com/answerdev/answer/internal/entity" - "github.com/answerdev/answer/internal/repo/config" "github.com/answerdev/answer/internal/repo/user" "github.com/stretchr/testify/assert" ) func Test_userRepo_AddUser(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) userInfo := &entity.User{ Username: "answer", Pass: "answer", @@ -26,7 +25,7 @@ func Test_userRepo_AddUser(t *testing.T) { } func Test_userRepo_BatchGetByID(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) got, err := userRepo.BatchGetByID(context.TODO(), []string{"1"}) assert.NoError(t, err) assert.Equal(t, 1, len(got)) @@ -34,7 +33,7 @@ func Test_userRepo_BatchGetByID(t *testing.T) { } func Test_userRepo_GetByEmail(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) got, exist, err := userRepo.GetByEmail(context.TODO(), "admin@admin.com") assert.NoError(t, err) assert.True(t, exist) @@ -42,7 +41,7 @@ func Test_userRepo_GetByEmail(t *testing.T) { } func Test_userRepo_GetByUserID(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) got, exist, err := userRepo.GetByUserID(context.TODO(), "1") assert.NoError(t, err) assert.True(t, exist) @@ -50,7 +49,7 @@ func Test_userRepo_GetByUserID(t *testing.T) { } func Test_userRepo_GetByUsername(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) got, exist, err := userRepo.GetByUsername(context.TODO(), "admin") assert.NoError(t, err) assert.True(t, exist) @@ -58,7 +57,7 @@ func Test_userRepo_GetByUsername(t *testing.T) { } func Test_userRepo_IncreaseAnswerCount(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.IncreaseAnswerCount(context.TODO(), "1", 1) assert.NoError(t, err) @@ -69,7 +68,7 @@ func Test_userRepo_IncreaseAnswerCount(t *testing.T) { } func Test_userRepo_IncreaseQuestionCount(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.IncreaseQuestionCount(context.TODO(), "1", 1) assert.NoError(t, err) @@ -80,19 +79,19 @@ func Test_userRepo_IncreaseQuestionCount(t *testing.T) { } func Test_userRepo_UpdateEmail(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.UpdateEmail(context.TODO(), "1", "admin@admin.com") assert.NoError(t, err) } func Test_userRepo_UpdateEmailStatus(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.UpdateEmailStatus(context.TODO(), "1", entity.EmailStatusToBeVerified) assert.NoError(t, err) } func Test_userRepo_UpdateInfo(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.UpdateInfo(context.TODO(), &entity.User{ID: "1", Bio: "test"}) assert.NoError(t, err) @@ -103,19 +102,19 @@ func Test_userRepo_UpdateInfo(t *testing.T) { } func Test_userRepo_UpdateLastLoginDate(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.UpdateLastLoginDate(context.TODO(), "1") assert.NoError(t, err) } func Test_userRepo_UpdateNoticeStatus(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.UpdateNoticeStatus(context.TODO(), "1", 1) assert.NoError(t, err) } func Test_userRepo_UpdatePass(t *testing.T) { - userRepo := user.NewUserRepo(testDataSource, config.NewConfigRepo(testDataSource)) + userRepo := user.NewUserRepo(testDataSource, config_common.NewConfigRepo(testDataSource)) err := userRepo.UpdatePass(context.TODO(), "1", "admin") assert.NoError(t, err) } diff --git a/internal/repo/user/user_repo.go b/internal/repo/user/user_repo.go index 3baa4b1e..72f7dc5c 100644 --- a/internal/repo/user/user_repo.go +++ b/internal/repo/user/user_repo.go @@ -8,7 +8,6 @@ import ( "github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/entity" "github.com/answerdev/answer/internal/schema" - "github.com/answerdev/answer/internal/service/config" usercommon "github.com/answerdev/answer/internal/service/user_common" "github.com/answerdev/answer/pkg/converter" "github.com/answerdev/answer/plugin" @@ -19,15 +18,13 @@ import ( // userRepo user repository type userRepo struct { - data *data.Data - configRepo config.ConfigRepo + data *data.Data } // NewUserRepo new repository -func NewUserRepo(data *data.Data, configRepo config.ConfigRepo) usercommon.UserRepo { +func NewUserRepo(data *data.Data) usercommon.UserRepo { return &userRepo{ - data: data, - configRepo: configRepo, + data: data, } } diff --git a/internal/service/activity/activity.go b/internal/service/activity/activity.go index 1688de42..9f1e9158 100644 --- a/internal/service/activity/activity.go +++ b/internal/service/activity/activity.go @@ -8,10 +8,10 @@ import ( "github.com/answerdev/answer/internal/base/constant" "github.com/answerdev/answer/internal/entity" - "github.com/answerdev/answer/internal/repo/config" "github.com/answerdev/answer/internal/schema" "github.com/answerdev/answer/internal/service/activity_common" "github.com/answerdev/answer/internal/service/comment_common" + "github.com/answerdev/answer/internal/service/config" "github.com/answerdev/answer/internal/service/meta" "github.com/answerdev/answer/internal/service/object_info" "github.com/answerdev/answer/internal/service/revision_common" @@ -38,6 +38,7 @@ type ActivityService struct { commentCommonService *comment_common.CommentCommonService revisionService *revision_common.RevisionService metaService *meta.MetaService + configService *config.ConfigService } // NewActivityService new activity service @@ -50,6 +51,7 @@ func NewActivityService( commentCommonService *comment_common.CommentCommonService, revisionService *revision_common.RevisionService, metaService *meta.MetaService, + configService *config.ConfigService, ) *ActivityService { return &ActivityService{ objectInfoService: objectInfoService, @@ -60,6 +62,7 @@ func NewActivityService( commentCommonService: commentCommonService, revisionService: revisionService, metaService: metaService, + configService: configService, } } @@ -97,9 +100,15 @@ func (as *ActivityService) GetObjectTimeline(ctx context.Context, req *schema.Ge item.ObjectID = uid.EnShortID(act.ObjectID) } + cfg, err := as.configService.GetConfigByID(ctx, act.ActivityType) + if err == nil { + log.Error(err) + } else { + item.ActivityType = cfg.Key + } // database save activity type is number, change to activity type string is like "question.asked". - // so we need to cut the front part of '.' - _, item.ActivityType, _ = strings.Cut(config.ID2KeyMapping[act.ActivityType], ".") + // so we need to cut the front part of '.', only need string like 'asked' + _, item.ActivityType, _ = strings.Cut(cfg.Key, ".") // format activity type string to show if isHidden, formattedActivityType := formatActivity(item.ActivityType); isHidden { continue diff --git a/internal/service/activity_type/activity_type.go b/internal/service/activity_type/activity_type.go index 22ab8490..65f7992f 100644 --- a/internal/service/activity_type/activity_type.go +++ b/internal/service/activity_type/activity_type.go @@ -1,9 +1,5 @@ package activity_type -import ( - "github.com/answerdev/answer/internal/repo/config" -) - const ( QuestionVoteUp = "question.vote_up" QuestionVoteDown = "question.vote_down" @@ -51,10 +47,11 @@ var ( ) func Format(activityTypeID int) string { - activityTypeStr := config.ID2KeyMapping[activityTypeID] - activityTypeFlag := activityTypeFlagMapping[activityTypeStr] - if len(activityTypeFlag) == 0 { - return "edit" // to edit - } - return activityTypeFlag // todo i18n support + return "" + //activityTypeStr := config_common.ID2KeyMapping[activityTypeID] + //activityTypeFlag := activityTypeFlagMapping[activityTypeStr] + //if len(activityTypeFlag) == 0 { + // return "edit" // to edit + //} + //return activityTypeFlag // todo i18n support } diff --git a/internal/service/config/config_service.go b/internal/service/config/config_service.go index b5af20ae..6adc4177 100644 --- a/internal/service/config/config_service.go +++ b/internal/service/config/config_service.go @@ -1,16 +1,18 @@ package config -import "context" +import ( + "context" + "encoding/json" + "fmt" + + "github.com/answerdev/answer/internal/entity" +) // ConfigRepo config repository type ConfigRepo interface { - Get(key string) (interface{}, error) - GetString(key string) (string, error) - GetInt(key string) (int, error) - GetArrayString(key string) ([]string, error) - GetConfigType(key string) (int, error) - GetJsonConfigByIDAndSetToObject(id int, value any) (err error) - SetConfig(ctx context.Context, key, value string) (err error) + GetConfigByID(ctx context.Context, id int) (c *entity.Config, err error) + GetConfigByKey(ctx context.Context, key string) (c *entity.Config, err error) + UpdateConfig(ctx context.Context, key, value string) (err error) } // ConfigService user service @@ -18,8 +20,70 @@ type ConfigService struct { configRepo ConfigRepo } +// NewConfigService new config service func NewConfigService(configRepo ConfigRepo) *ConfigService { return &ConfigService{ configRepo: configRepo, } } + +// GetIntValue get config int value +func (cs *ConfigService) GetIntValue(ctx context.Context, key string) (val int, err error) { + cf, err := cs.configRepo.GetConfigByKey(ctx, key) + if err != nil { + return 0, err + } + return cf.GetIntValue(), nil +} + +// GetStringValue get config string value +func (cs *ConfigService) GetStringValue(ctx context.Context, key string) (val string, err error) { + cf, err := cs.configRepo.GetConfigByKey(ctx, key) + if err != nil { + return "", err + } + return cf.Value, nil +} + +// GetArrayStringValue get config array string value +func (cs *ConfigService) GetArrayStringValue(ctx context.Context, key string) (val []string, err error) { + cf, err := cs.configRepo.GetConfigByKey(ctx, key) + if err != nil { + return nil, err + } + return cf.GetArrayStringValue(), nil +} + +func (cs *ConfigService) GetJsonConfigByIDAndSetToObject(ctx context.Context, id int, obj any) (err error) { + cf, err := cs.configRepo.GetConfigByID(ctx, id) + if err != nil { + return err + } + err = json.Unmarshal([]byte(cf.Value), obj) + if err != nil { + return fmt.Errorf("[%s] config value is not json format", cf.Key) + } + return nil +} + +// GetConfigByID get config by id +func (cs *ConfigService) GetConfigByID(ctx context.Context, id int) (c *entity.Config, err error) { + return cs.configRepo.GetConfigByID(ctx, id) +} + +func (cs *ConfigService) GetConfigByKey(ctx context.Context, key string) (c *entity.Config, err error) { + return cs.configRepo.GetConfigByKey(ctx, key) +} + +// GetIDByKey get config id by key +func (cs *ConfigService) GetIDByKey(ctx context.Context, key string) (id int, err error) { + cf, err := cs.configRepo.GetConfigByKey(ctx, key) + if err != nil { + return 0, err + } + return cf.ID, nil +} + +func (cs *ConfigService) UpdateConfig(ctx context.Context, key, value string) (err error) { + return cs.configRepo.UpdateConfig(ctx, key, value) +} diff --git a/internal/service/dashboard/dashboard_service.go b/internal/service/dashboard/dashboard_service.go index d8fcc8cb..fa798e69 100644 --- a/internal/service/dashboard/dashboard_service.go +++ b/internal/service/dashboard/dashboard_service.go @@ -35,7 +35,7 @@ type DashboardService struct { voteRepo activity_common.VoteRepo userRepo usercommon.UserRepo reportRepo report_common.ReportRepo - configRepo config.ConfigRepo + configService *config.ConfigService siteInfoService *siteinfo_common.SiteInfoCommonService serviceConfig *service_config.ServiceConfig @@ -49,7 +49,7 @@ func NewDashboardService( voteRepo activity_common.VoteRepo, userRepo usercommon.UserRepo, reportRepo report_common.ReportRepo, - configRepo config.ConfigRepo, + configService *config.ConfigService, siteInfoService *siteinfo_common.SiteInfoCommonService, serviceConfig *service_config.ServiceConfig, @@ -62,7 +62,7 @@ func NewDashboardService( voteRepo: voteRepo, userRepo: userRepo, reportRepo: reportRepo, - configRepo: configRepo, + configService: configService, siteInfoService: siteInfoService, serviceConfig: serviceConfig, @@ -131,12 +131,11 @@ func (ds *DashboardService) Statistical(ctx context.Context) (*schema.DashboardI var activityTypes []int for _, typeKey := range typeKeys { - var t int - t, err = ds.configRepo.GetConfigType(typeKey) + cfg, err := ds.configService.GetConfigByKey(ctx, typeKey) if err != nil { continue } - activityTypes = append(activityTypes, t) + activityTypes = append(activityTypes, cfg.ID) } voteCount, err := ds.voteRepo.GetVoteCount(ctx, activityTypes) @@ -166,7 +165,7 @@ func (ds *DashboardService) Statistical(ctx context.Context) (*schema.DashboardI dashboardInfo.ReportCount = reportCount dashboardInfo.UploadingFiles = true - emailconfig, err := ds.GetEmailConfig() + emailconfig, err := ds.GetEmailConfig(ctx) if err != nil { return dashboardInfo, err } @@ -225,8 +224,8 @@ func (ds *DashboardService) RemoteVersion(ctx context.Context) string { return remoteVersion.Release.Version } -func (ds *DashboardService) GetEmailConfig() (ec *export.EmailConfig, err error) { - emailConf, err := ds.configRepo.GetString("email.config") +func (ds *DashboardService) GetEmailConfig(ctx context.Context) (ec *export.EmailConfig, err error) { + emailConf, err := ds.configService.GetStringValue(ctx, "email.config") if err != nil { return nil, err } diff --git a/internal/service/export/email_service.go b/internal/service/export/email_service.go index c30d1b94..8ab8139f 100644 --- a/internal/service/export/email_service.go +++ b/internal/service/export/email_service.go @@ -24,9 +24,9 @@ import ( // EmailService kit service type EmailService struct { - configRepo config.ConfigRepo - emailRepo EmailRepo - siteInfoRepo siteinfo_common.SiteInfoRepo + configService *config.ConfigService + emailRepo EmailRepo + siteInfoRepo siteinfo_common.SiteInfoRepo } // EmailRepo email repository @@ -36,11 +36,11 @@ type EmailRepo interface { } // NewEmailService email service -func NewEmailService(configRepo config.ConfigRepo, emailRepo EmailRepo, siteInfoRepo siteinfo_common.SiteInfoRepo) *EmailService { +func NewEmailService(configService *config.ConfigService, emailRepo EmailRepo, siteInfoRepo siteinfo_common.SiteInfoRepo) *EmailService { return &EmailService{ - configRepo: configRepo, - emailRepo: emailRepo, - siteInfoRepo: siteInfoRepo, + configService: configService, + emailRepo: emailRepo, + siteInfoRepo: siteInfoRepo, } } @@ -114,7 +114,7 @@ func (es *EmailService) SendAndSaveCodeWithTime( // Send email send func (es *EmailService) Send(ctx context.Context, toEmailAddr, subject, body string) { log.Infof("try to send email to %s", toEmailAddr) - ec, err := es.GetEmailConfig() + ec, err := es.GetEmailConfig(ctx) if err != nil { log.Errorf("get email config failed: %s", err) return @@ -298,8 +298,8 @@ func (es *EmailService) NewCommentTemplate(ctx context.Context, raw *schema.NewC return title, body, nil } -func (es *EmailService) GetEmailConfig() (ec *EmailConfig, err error) { - emailConf, err := es.configRepo.GetString("email.config") +func (es *EmailService) GetEmailConfig(ctx context.Context) (ec *EmailConfig, err error) { + emailConf, err := es.configService.GetStringValue(ctx, "email.config") if err != nil { return nil, err } @@ -314,5 +314,5 @@ func (es *EmailService) GetEmailConfig() (ec *EmailConfig, err error) { // SetEmailConfig set email config func (es *EmailService) SetEmailConfig(ctx context.Context, ec *EmailConfig) (err error) { data, _ := json.Marshal(ec) - return es.configRepo.SetConfig(ctx, "email.config", string(data)) + return es.configService.UpdateConfig(ctx, "email.config", string(data)) } diff --git a/internal/service/plugin_common/plugin_common_service.go b/internal/service/plugin_common/plugin_common_service.go index 69ad45bb..8517e469 100644 --- a/internal/service/plugin_common/plugin_common_service.go +++ b/internal/service/plugin_common/plugin_common_service.go @@ -21,17 +21,17 @@ type PluginConfigRepo interface { // PluginCommonService user service type PluginCommonService struct { - configRepo config.ConfigRepo + configService *config.ConfigService pluginConfigRepo PluginConfigRepo } // NewPluginCommonService new report service func NewPluginCommonService( pluginConfigRepo PluginConfigRepo, - configRepo config.ConfigRepo) *PluginCommonService { + configService *config.ConfigService) *PluginCommonService { // init plugin status - pluginStatus, err := configRepo.GetString(constant.PluginStatus) + pluginStatus, err := configService.GetStringValue(context.TODO(), constant.PluginStatus) if err != nil { log.Error(err) } else { @@ -59,7 +59,7 @@ func NewPluginCommonService( } return &PluginCommonService{ - configRepo: configRepo, + configService: configService, pluginConfigRepo: pluginConfigRepo, } } @@ -70,7 +70,7 @@ func (ps *PluginCommonService) UpdatePluginStatus(ctx context.Context) (err erro if err != nil { return errors.InternalServer(reason.UnknownError).WithError(err) } - return ps.configRepo.SetConfig(ctx, constant.PluginStatus, string(content)) + return ps.configService.UpdateConfig(ctx, constant.PluginStatus, string(content)) } // UpdatePluginConfig update plugin config diff --git a/internal/service/provider.go b/internal/service/provider.go index 8273866c..69c30047 100644 --- a/internal/service/provider.go +++ b/internal/service/provider.go @@ -9,6 +9,7 @@ import ( collectioncommon "github.com/answerdev/answer/internal/service/collection_common" "github.com/answerdev/answer/internal/service/comment" "github.com/answerdev/answer/internal/service/comment_common" + "github.com/answerdev/answer/internal/service/config" "github.com/answerdev/answer/internal/service/dashboard" "github.com/answerdev/answer/internal/service/export" "github.com/answerdev/answer/internal/service/follow" @@ -84,4 +85,5 @@ var ProviderSetService = wire.NewSet( user_external_login.NewUserExternalLoginService, user_external_login.NewUserCenterLoginService, plugin_common.NewPluginCommonService, + config.NewConfigService, ) diff --git a/internal/service/question_common/question.go b/internal/service/question_common/question.go index 2e3b5ddf..6ec1176f 100644 --- a/internal/service/question_common/question.go +++ b/internal/service/question_common/question.go @@ -6,6 +6,7 @@ import ( "time" "github.com/answerdev/answer/internal/base/constant" + "github.com/answerdev/answer/internal/base/handler" "github.com/answerdev/answer/internal/base/reason" "github.com/answerdev/answer/internal/service/activity_common" "github.com/answerdev/answer/internal/service/activity_queue" @@ -62,7 +63,7 @@ type QuestionCommon struct { collectionCommon *collectioncommon.CollectionCommon AnswerCommon *answercommon.AnswerCommon metaService *meta.MetaService - configRepo config.ConfigRepo + configService *config.ConfigService } func NewQuestionCommon(questionRepo QuestionRepo, @@ -74,7 +75,7 @@ func NewQuestionCommon(questionRepo QuestionRepo, collectionCommon *collectioncommon.CollectionCommon, answerCommon *answercommon.AnswerCommon, metaService *meta.MetaService, - configRepo config.ConfigRepo, + configService *config.ConfigService, ) *QuestionCommon { return &QuestionCommon{ questionRepo: questionRepo, @@ -86,7 +87,7 @@ func NewQuestionCommon(questionRepo QuestionRepo, collectionCommon: collectionCommon, AnswerCommon: answerCommon, metaService: metaService, - configRepo: configRepo, + configService: configService, } } @@ -201,14 +202,16 @@ func (qs *QuestionCommon) Info(ctx context.Context, questionID string, loginUser if err != nil { log.Error("json.Unmarshal CloseQuestionMeta error", err.Error()) } else { - closeinfo := &schema.GetReportTypeResp{} - err = qs.configRepo.GetJsonConfigByIDAndSetToObject(closemsg.CloseType, closeinfo) + cfg, err := qs.configService.GetConfigByID(ctx, closemsg.CloseType) if err != nil { log.Error("json.Unmarshal QuestionCloseJson error", err.Error()) } else { + reasonItem := &schema.ReasonItem{} + _ = json.Unmarshal(cfg.GetByteValue(), reasonItem) + reasonItem.Translate(cfg.Key, handler.GetLangByCtx(ctx)) operation := &schema.Operation{} - operation.Type = closeinfo.Name - operation.Description = closeinfo.Description + operation.Type = reasonItem.Name + operation.Description = reasonItem.Description operation.Msg = closemsg.CloseMsg operation.Time = metainfo.CreatedAt.Unix() operation.Level = schema.OperationLevelInfo diff --git a/internal/service/rank/rank_service.go b/internal/service/rank/rank_service.go index 4ef63d00..f8cd63b8 100644 --- a/internal/service/rank/rank_service.go +++ b/internal/service/rank/rank_service.go @@ -34,7 +34,7 @@ type UserRankRepo interface { // RankService rank service type RankService struct { userCommon *usercommon.UserCommon - configRepo config.ConfigRepo + configService *config.ConfigService userRankRepo UserRankRepo objectInfoService *object_info.ObjService roleService *role.UserRoleRelService @@ -48,10 +48,10 @@ func NewRankService( objectInfoService *object_info.ObjService, roleService *role.UserRoleRelService, rolePowerService *role.RolePowerRelService, - configRepo config.ConfigRepo) *RankService { + configService *config.ConfigService) *RankService { return &RankService{ userCommon: userCommon, - configRepo: configRepo, + configService: configService, userRankRepo: userRankRepo, objectInfoService: objectInfoService, roleService: roleService, @@ -213,7 +213,7 @@ func (rs *RankService) getUserPowerMapping(ctx context.Context, userID string) ( func (rs *RankService) checkUserRank(ctx context.Context, userID string, userRank int, action string) ( can bool, rank int) { // get the amount of rank required for the current operation - requireRank, err := rs.configRepo.GetInt(action) + requireRank, err := rs.configService.GetIntValue(ctx, action) if err != nil { log.Error(err) return false, requireRank diff --git a/internal/service/report_admin/report_backyard.go b/internal/service/report_admin/report_backyard.go index f651e8e3..ee817fc7 100644 --- a/internal/service/report_admin/report_backyard.go +++ b/internal/service/report_admin/report_backyard.go @@ -2,9 +2,9 @@ package report_admin import ( "context" + "encoding/json" "github.com/answerdev/answer/internal/base/handler" - configrepo "github.com/answerdev/answer/internal/repo/config" "github.com/answerdev/answer/internal/service/config" "github.com/answerdev/answer/internal/service/object_info" "github.com/answerdev/answer/pkg/htmltext" @@ -32,7 +32,7 @@ type ReportAdminService struct { questionRepo questioncommon.QuestionRepo commentCommonRepo comment_common.CommentCommonRepo reportHandle *report_handle_admin.ReportHandle - configRepo config.ConfigRepo + configService *config.ConfigService objectInfoService *object_info.ObjService } @@ -44,7 +44,7 @@ func NewReportAdminService( questionRepo questioncommon.QuestionRepo, commentCommonRepo comment_common.CommentCommonRepo, reportHandle *report_handle_admin.ReportHandle, - configRepo config.ConfigRepo, + configService *config.ConfigService, objectInfoService *object_info.ObjService) *ReportAdminService { return &ReportAdminService{ reportRepo: reportRepo, @@ -53,7 +53,7 @@ func NewReportAdminService( questionRepo: questionRepo, commentCommonRepo: commentCommonRepo, reportHandle: reportHandle, - configRepo: configRepo, + configService: configService, objectInfoService: objectInfoService, } } @@ -151,21 +151,25 @@ func (rs *ReportAdminService) decorateReportResp(ctx context.Context, resp *sche resp.CommentID = objectInfo.CommentID resp.Title = objectInfo.Title resp.Excerpt = htmltext.FetchExcerpt(objectInfo.Content, "...", 240) - resp.Reason.Translate(configrepo.ID2KeyMapping[resp.ReportType], lang) if resp.ReportType > 0 { resp.Reason = &schema.ReasonItem{ReasonType: resp.ReportType} - err = rs.configRepo.GetJsonConfigByIDAndSetToObject(resp.ReportType, resp.Reason) + cf, err := rs.configService.GetConfigByID(ctx, resp.ReportType) if err != nil { log.Error(err) + } else { + _ = json.Unmarshal([]byte(cf.Value), resp.Reason) + resp.Reason.Translate(cf.Key, lang) } } if resp.FlaggedType > 0 { resp.FlaggedReason = &schema.ReasonItem{ReasonType: resp.FlaggedType} - err = rs.configRepo.GetJsonConfigByIDAndSetToObject(resp.FlaggedType, resp.FlaggedReason) + cf, err := rs.configService.GetConfigByID(ctx, resp.FlaggedType) if err != nil { log.Error(err) + } else { + _ = json.Unmarshal([]byte(cf.Value), resp.Reason) + resp.Reason.Translate(cf.Key, lang) } - resp.Reason.Translate(configrepo.ID2KeyMapping[resp.ReportType], lang) } } diff --git a/internal/service/report_handle_admin/report_handle.go b/internal/service/report_handle_admin/report_handle.go index a7a57272..65601aaa 100644 --- a/internal/service/report_handle_admin/report_handle.go +++ b/internal/service/report_handle_admin/report_handle.go @@ -17,28 +17,34 @@ import ( type ReportHandle struct { questionCommon *questioncommon.QuestionCommon commentRepo comment.CommentRepo - configRepo config.ConfigRepo + configService *config.ConfigService } func NewReportHandle( questionCommon *questioncommon.QuestionCommon, commentRepo comment.CommentRepo, - configRepo config.ConfigRepo) *ReportHandle { + configService *config.ConfigService) *ReportHandle { return &ReportHandle{ questionCommon: questionCommon, commentRepo: commentRepo, - configRepo: configRepo, + configService: configService, } } // HandleObject this handle object status func (rh *ReportHandle) HandleObject(ctx context.Context, reported *entity.Report, req schema.ReportHandleReq) (err error) { + reasonDeleteCfg, err := rh.configService.GetConfigByKey(ctx, "reason.needs_delete") + if err != nil { + return err + } + reasonCloseCfg, err := rh.configService.GetConfigByKey(ctx, "reason.needs_close") + if err != nil { + return err + } var ( - objectID = reported.ObjectID - reportedUserID = reported.ReportedUserID - objectKey string - reasonDelete, _ = rh.configRepo.GetConfigType("reason.needs_delete") - reasonClose, _ = rh.configRepo.GetConfigType("reason.needs_close") + objectID = reported.ObjectID + reportedUserID = reported.ReportedUserID + objectKey string ) objectKey, err = obj.GetObjectTypeStrByObjectID(objectID) @@ -48,9 +54,9 @@ func (rh *ReportHandle) HandleObject(ctx context.Context, reported *entity.Repor switch objectKey { case "question": switch req.FlaggedType { - case reasonDelete: + case reasonDeleteCfg.ID: err = rh.questionCommon.RemoveQuestion(ctx, &schema.RemoveQuestionReq{ID: objectID}) - case reasonClose: + case reasonCloseCfg.ID: err = rh.questionCommon.CloseQuestion(ctx, &schema.CloseQuestionReq{ ID: objectID, CloseType: req.FlaggedType, @@ -59,12 +65,12 @@ func (rh *ReportHandle) HandleObject(ctx context.Context, reported *entity.Repor } case "answer": switch req.FlaggedType { - case reasonDelete: + case reasonDeleteCfg.ID: err = rh.questionCommon.RemoveAnswer(ctx, objectID) } case "comment": switch req.FlaggedType { - case reasonDelete: + case reasonCloseCfg.ID: err = rh.commentRepo.RemoveComment(ctx, objectID) rh.sendNotification(ctx, reportedUserID, objectID, constant.NotificationYourCommentWasDeleted) } diff --git a/internal/service/siteinfo/siteinfo_service.go b/internal/service/siteinfo/siteinfo_service.go index edd2b9de..a1c4c08e 100644 --- a/internal/service/siteinfo/siteinfo_service.go +++ b/internal/service/siteinfo/siteinfo_service.go @@ -26,7 +26,7 @@ type SiteInfoService struct { siteInfoCommonService *siteinfo_common.SiteInfoCommonService emailService *export.EmailService tagCommonService *tagcommon.TagCommonService - configRepo config.ConfigRepo + configService *config.ConfigService } func NewSiteInfoService( @@ -34,7 +34,7 @@ func NewSiteInfoService( siteInfoCommonService *siteinfo_common.SiteInfoCommonService, emailService *export.EmailService, tagCommonService *tagcommon.TagCommonService, - configRepo config.ConfigRepo, + configService *config.ConfigService, ) *SiteInfoService { usersSiteInfo, _ := siteInfoCommonService.GetSiteUsers(context.Background()) if usersSiteInfo != nil { @@ -51,7 +51,7 @@ func NewSiteInfoService( siteInfoCommonService: siteInfoCommonService, emailService: emailService, tagCommonService: tagCommonService, - configRepo: configRepo, + configService: configService, } } @@ -239,7 +239,7 @@ func (s *SiteInfoService) SaveSiteUsers(ctx context.Context, req *schema.SiteUse func (s *SiteInfoService) GetSMTPConfig(ctx context.Context) ( resp *schema.GetSMTPConfigResp, err error, ) { - emailConfig, err := s.emailService.GetEmailConfig() + emailConfig, err := s.emailService.GetEmailConfig(ctx) if err != nil { return nil, err } @@ -250,7 +250,7 @@ func (s *SiteInfoService) GetSMTPConfig(ctx context.Context) ( // UpdateSMTPConfig get smtp config func (s *SiteInfoService) UpdateSMTPConfig(ctx context.Context, req *schema.UpdateSMTPConfigReq) (err error) { - oldEmailConfig, err := s.emailService.GetEmailConfig() + oldEmailConfig, err := s.emailService.GetEmailConfig(ctx) if err != nil { return err } @@ -372,7 +372,7 @@ func (s *SiteInfoService) UpdatePrivilegesConfig(ctx context.Context, req *schem // update privilege in config for _, privilege := range chooseOption.Privileges { - err = s.configRepo.SetConfig(ctx, privilege.Key, fmt.Sprintf("%d", privilege.Value)) + err = s.configService.UpdateConfig(ctx, privilege.Key, fmt.Sprintf("%d", privilege.Value)) if err != nil { return err } diff --git a/internal/service/vote_service.go b/internal/service/vote_service.go index 41ea00e5..1a3096e7 100644 --- a/internal/service/vote_service.go +++ b/internal/service/vote_service.go @@ -35,7 +35,7 @@ type VoteRepo interface { type VoteService struct { voteRepo VoteRepo UniqueIDRepo unique.UniqueIDRepo - configRepo config.ConfigRepo + configService *config.ConfigService questionRepo questioncommon.QuestionRepo answerRepo answercommon.AnswerRepo commentCommonRepo comment_common.CommentCommonRepo @@ -45,7 +45,7 @@ type VoteService struct { func NewVoteService( VoteRepo VoteRepo, uniqueIDRepo unique.UniqueIDRepo, - configRepo config.ConfigRepo, + configService *config.ConfigService, questionRepo questioncommon.QuestionRepo, answerRepo answercommon.AnswerRepo, commentCommonRepo comment_common.CommentCommonRepo, @@ -54,7 +54,7 @@ func NewVoteService( return &VoteService{ voteRepo: VoteRepo, UniqueIDRepo: uniqueIDRepo, - configRepo: configRepo, + configService: configService, questionRepo: questionRepo, answerRepo: answerRepo, commentCommonRepo: commentCommonRepo, @@ -163,12 +163,11 @@ func (vs *VoteService) ListUserVotes(ctx context.Context, req schema.GetVoteWith ) for _, typeKey := range typeKeys { - var t int - t, err = vs.configRepo.GetConfigType(typeKey) + cfg, err := vs.configService.GetConfigByKey(ctx, typeKey) if err != nil { continue } - activityTypes = append(activityTypes, t) + activityTypes = append(activityTypes, cfg.GetIntValue()) } voteList, total, err := vs.voteRepo.ListUserVotes(ctx, req.UserID, req, activityTypes)