diff --git a/biz/application/service/moment.go b/biz/application/service/moment.go index ee3cf65..f6bba1c 100644 --- a/biz/application/service/moment.go +++ b/biz/application/service/moment.go @@ -5,11 +5,15 @@ import ( "github.com/google/wire" "github.com/xh-polaris/gopkg/pagination/esp" "github.com/xh-polaris/gopkg/pagination/mongop" + "github.com/xh-polaris/meowchat-content/biz/infrastructure/config" "github.com/xh-polaris/meowchat-content/biz/infrastructure/consts" "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/moment" "github.com/xh-polaris/meowchat-content/biz/infrastructure/util/convertor" "github.com/xh-polaris/service-idl-gen-go/kitex_gen/meowchat/content" + "github.com/zeromicro/go-zero/core/stores/redis" "go.mongodb.org/mongo-driver/bson/primitive" + "strconv" + "time" ) type IMomentService interface { @@ -22,8 +26,10 @@ type IMomentService interface { } type MomentService struct { + Config *config.Config MomentMongoMapper moment.IMongoMapper MomentEsMapper moment.IEsMapper + Redis *redis.Redis } var MomentSet = wire.NewSet( @@ -102,6 +108,7 @@ func (s *MomentService) RetrieveMoment(ctx context.Context, req *content.Retriev } func (s *MomentService) CreateMoment(ctx context.Context, req *content.CreateMomentReq) (*content.CreateMomentResp, error) { + resp := new(content.CreateMomentResp) m := req.Moment data := &moment.Moment{ Photos: m.Photos, @@ -117,7 +124,66 @@ func (s *MomentService) CreateMoment(ctx context.Context, req *content.CreateMom return nil, err } - return &content.CreateMomentResp{MomentId: data.ID.Hex()}, nil + resp.MomentId = data.ID.Hex() + t, err := s.Redis.GetCtx(ctx, "contentTimes"+m.UserId) + if err != nil { + return resp, nil + } + r, err := s.Redis.GetCtx(ctx, "contentDate"+m.UserId) + if err != nil { + return resp, nil + } else if r == "" { + resp.GetFish = true + resp.GetFishTimes = 1 + err = s.Redis.SetexCtx(ctx, "contentTimes"+m.UserId, "1", 86400) + if err != nil { + resp.GetFish = false + return resp, nil + } + err = s.Redis.SetexCtx(ctx, "contentDate"+m.UserId, strconv.FormatInt(time.Now().Unix(), 10), 86400) + if err != nil { + resp.GetFish = false + return resp, nil + } + } else { + times, err := strconv.ParseInt(t, 10, 64) + if err != nil { + return resp, nil + } + resp.GetFishTimes = times + 1 + date, err := strconv.ParseInt(r, 10, 64) + if err != nil { + return resp, nil + } + lastTime := time.Unix(date, 0) + err = s.Redis.SetexCtx(ctx, "contentTimes"+m.UserId, strconv.FormatInt(times+1, 10), 86400) + if err != nil { + return resp, nil + } + err = s.Redis.SetexCtx(ctx, "contentDate"+m.UserId, strconv.FormatInt(time.Now().Unix(), 10), 86400) + if err != nil { + return resp, nil + } + if lastTime.Day() == time.Now().Day() && lastTime.Month() == time.Now().Month() && lastTime.Year() == time.Now().Year() { + err = s.Redis.SetexCtx(ctx, "contentTimes"+m.UserId, strconv.FormatInt(times+1, 10), 86400) + if err != nil { + return resp, nil + } + if times >= s.Config.GetFishTimes { + resp.GetFish = false + } else { + resp.GetFish = true + } + } else { + err = s.Redis.SetexCtx(ctx, "contentTimes"+m.UserId, "1", 86400) + if err != nil { + return resp, nil + } + resp.GetFish = true + resp.GetFishTimes = 1 + } + } + return resp, nil } func (s *MomentService) UpdateMoment(ctx context.Context, req *content.UpdateMomentReq) (*content.UpdateMomentResp, error) { diff --git a/biz/application/service/plan.go b/biz/application/service/plan.go index 032ac32..55b7901 100644 --- a/biz/application/service/plan.go +++ b/biz/application/service/plan.go @@ -12,6 +12,7 @@ import ( "github.com/xh-polaris/meowchat-content/biz/infrastructure/util/convertor" "github.com/xh-polaris/service-idl-gen-go/kitex_gen/meowchat/content" "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" "sort" "time" ) @@ -165,33 +166,51 @@ func (s *PlanService) DeletePlan(ctx context.Context, req *content.DeletePlanReq } func (s *PlanService) DonateFish(ctx context.Context, req *content.DonateFishReq) (*content.DonateFishResp, error) { - data, err := s.FishMongoMapper.FindOne(ctx, req.UserId) - if err != nil { - return nil, err - } - data.FishNum = data.FishNum - req.Fish - err = s.FishMongoMapper.Update(ctx, data) + dbClient, err := s.FishMongoMapper.StartClient(ctx) if err != nil { return nil, err } - err = s.DonateMongoMapper.Insert(ctx, &donate.Donate{ - UserId: req.UserId, - PlanId: req.PlanId, - FishNum: req.Fish, + err = dbClient.UseSession(ctx, func(sessionContext mongo.SessionContext) error { + err = sessionContext.StartTransaction() + if err != nil { + return err + } + err = s.FishMongoMapper.Add(sessionContext, req.UserId, -req.Fish) + if err != nil { + return err + } + + err = s.DonateMongoMapper.Insert(sessionContext, &donate.Donate{ + UserId: req.UserId, + PlanId: req.PlanId, + FishNum: req.Fish, + }) + if err != nil { + err = sessionContext.AbortTransaction(sessionContext) + if err != nil { + return err + } + return err + } + err = s.PlanMongoMapper.Add(sessionContext, req.PlanId, req.Fish) + if err != nil { + err = sessionContext.AbortTransaction(sessionContext) + if err != nil { + return err + } + return err + } + err = sessionContext.CommitTransaction(sessionContext) + if err != nil { + err = sessionContext.AbortTransaction(sessionContext) + if err != nil { + return err + } + return err + } + return nil }) - if err != nil { - return nil, err - } - res, err := s.PlanMongoMapper.FindOne(ctx, req.PlanId) - if err != nil { - return nil, err - } - res.NowFish = res.NowFish + req.Fish - err = s.PlanMongoMapper.Update(ctx, res) - if err != nil { - return nil, err - } return &content.DonateFishResp{}, nil } diff --git a/biz/application/service/post.go b/biz/application/service/post.go index 40b6423..fabdfc3 100644 --- a/biz/application/service/post.go +++ b/biz/application/service/post.go @@ -5,11 +5,15 @@ import ( "github.com/google/wire" "github.com/xh-polaris/gopkg/pagination/esp" "github.com/xh-polaris/gopkg/pagination/mongop" + "github.com/xh-polaris/meowchat-content/biz/infrastructure/config" "github.com/xh-polaris/meowchat-content/biz/infrastructure/consts" "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/post" "github.com/xh-polaris/meowchat-content/biz/infrastructure/util/convertor" "github.com/xh-polaris/service-idl-gen-go/kitex_gen/meowchat/content" + "github.com/zeromicro/go-zero/core/stores/redis" "go.mongodb.org/mongo-driver/bson/primitive" + "strconv" + "time" ) type IPostService interface { @@ -23,8 +27,10 @@ type IPostService interface { } type PostService struct { + Config *config.Config PostMongoMapper post.IMongoMapper PostEsMapper post.IEsMapper + Redis *redis.Redis } var PostSet = wire.NewSet( @@ -33,6 +39,7 @@ var PostSet = wire.NewSet( ) func (s *PostService) CreatePost(ctx context.Context, req *content.CreatePostReq) (*content.CreatePostResp, error) { + resp := new(content.CreatePostResp) p := &post.Post{ Title: req.Title, Text: req.Text, @@ -44,7 +51,66 @@ func (s *PostService) CreatePost(ctx context.Context, req *content.CreatePostReq if err != nil { return nil, err } - return &content.CreatePostResp{PostId: p.ID.Hex()}, nil + resp.PostId = p.ID.Hex() + data, err := s.Redis.GetCtx(ctx, "contentTimes"+req.UserId) + if err != nil { + return resp, nil + } + r, err := s.Redis.GetCtx(ctx, "contentDate"+req.UserId) + if err != nil { + return resp, nil + } else if r == "" { + resp.GetFish = true + resp.GetFishTimes = 1 + err = s.Redis.SetexCtx(ctx, "contentTimes"+req.UserId, "1", 86400) + if err != nil { + resp.GetFish = false + return resp, nil + } + err = s.Redis.SetexCtx(ctx, "contentDate"+req.UserId, strconv.FormatInt(time.Now().Unix(), 10), 86400) + if err != nil { + resp.GetFish = false + return resp, nil + } + } else { + times, err := strconv.ParseInt(data, 10, 64) + if err != nil { + return resp, nil + } + resp.GetFishTimes = times + 1 + m, err := strconv.ParseInt(r, 10, 64) + if err != nil { + return resp, nil + } + lastTime := time.Unix(m, 0) + err = s.Redis.SetexCtx(ctx, "contentTimes"+req.UserId, strconv.FormatInt(times+1, 10), 86400) + if err != nil { + return resp, nil + } + err = s.Redis.SetexCtx(ctx, "contentDate"+req.UserId, strconv.FormatInt(time.Now().Unix(), 10), 86400) + if err != nil { + return resp, nil + } + if lastTime.Day() == time.Now().Day() && lastTime.Month() == time.Now().Month() && lastTime.Year() == time.Now().Year() { + err = s.Redis.SetexCtx(ctx, "contentTimes"+req.UserId, strconv.FormatInt(times+1, 10), 86400) + if err != nil { + return resp, nil + } + if times >= s.Config.GetFishTimes { + resp.GetFish = false + } else { + resp.GetFish = true + } + } else { + err = s.Redis.SetexCtx(ctx, "contentTimes"+req.UserId, "1", 86400) + if err != nil { + return resp, nil + } + resp.GetFish = true + resp.GetFishTimes = 1 + } + } + return resp, nil } func (s *PostService) RetrievePost(ctx context.Context, req *content.RetrievePostReq) (*content.RetrievePostResp, error) { diff --git a/biz/infrastructure/config/config.go b/biz/infrastructure/config/config.go index a039f93..939140d 100644 --- a/biz/infrastructure/config/config.go +++ b/biz/infrastructure/config/config.go @@ -4,6 +4,7 @@ import ( "github.com/zeromicro/go-zero/core/conf" "github.com/zeromicro/go-zero/core/service" "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/redis" "os" ) @@ -22,6 +23,8 @@ type Config struct { } Cache cache.CacheConf Elasticsearch ElasticsearchConf + Redis *redis.RedisConf + GetFishTimes int64 } func NewConfig() (*Config, error) { diff --git a/biz/infrastructure/mapper/fish/mongo.go b/biz/infrastructure/mapper/fish/mongo.go index 1c40931..9e46ec5 100644 --- a/biz/infrastructure/mapper/fish/mongo.go +++ b/biz/infrastructure/mapper/fish/mongo.go @@ -3,6 +3,7 @@ package fish import ( "context" "github.com/xh-polaris/meowchat-content/biz/infrastructure/consts" + "go.mongodb.org/mongo-driver/mongo" "time" "github.com/xh-polaris/meowchat-content/biz/infrastructure/config" @@ -22,6 +23,8 @@ type ( FindOne(ctx context.Context, id string) (*Fish, error) Update(ctx context.Context, data *Fish) error Delete(ctx context.Context, id string) error + Add(ctx context.Context, id string, add int64) error + StartClient(ctx context.Context) (*mongo.Client, error) } MongoMapper struct { @@ -86,3 +89,16 @@ func (m *MongoMapper) Delete(ctx context.Context, id string) error { _, err = m.conn.DeleteOne(ctx, key, bson.M{consts.ID: oid}) return err } + +func (m *MongoMapper) Add(ctx context.Context, id string, add int64) error { + key := prefixFishCacheKey + id + filter := bson.M{consts.ID: id} + update := bson.M{"$inc": bson.M{consts.FishNum: add}, "$set": bson.M{consts.UpdateAt: time.Now()}} + _, err := m.conn.UpdateOne(ctx, key, filter, update) + return err +} + +func (m *MongoMapper) StartClient(ctx context.Context) (*mongo.Client, error) { + client := m.conn.Database().Client() + return client, nil +} diff --git a/biz/infrastructure/mapper/plan/mongo.go b/biz/infrastructure/mapper/plan/mongo.go index 20989f2..652587c 100644 --- a/biz/infrastructure/mapper/plan/mongo.go +++ b/biz/infrastructure/mapper/plan/mongo.go @@ -24,6 +24,7 @@ type ( FindOne(ctx context.Context, id string) (*Plan, error) Update(ctx context.Context, data *Plan) error Delete(ctx context.Context, id string) error + Add(ctx context.Context, id string, add int64) error FindMany(ctx context.Context, fopts *FilterOptions, popts *pagination.PaginationOptions, sorter mongop.MongoCursor) ([]*Plan, error) Count(ctx context.Context, filter *FilterOptions) (int64, error) FindManyAndCount(ctx context.Context, fopts *FilterOptions, popts *pagination.PaginationOptions, sorter mongop.MongoCursor) ([]*Plan, int64, error) @@ -181,3 +182,11 @@ func (m *MongoMapper) Delete(ctx context.Context, id string) error { _, err = m.conn.DeleteOne(ctx, key, bson.M{consts.ID: oid}) return err } + +func (m *MongoMapper) Add(ctx context.Context, id string, add int64) error { + key := prefixPlanCacheKey + id + filter := bson.M{consts.ID: id} + update := bson.M{"$inc": bson.M{consts.FishNum: add}, "$set": bson.M{consts.UpdateAt: time.Now()}} + _, err := m.conn.UpdateOne(ctx, key, filter, update) + return err +} diff --git a/biz/infrastructure/stores/redis/redis.go b/biz/infrastructure/stores/redis/redis.go new file mode 100644 index 0000000..db7c012 --- /dev/null +++ b/biz/infrastructure/stores/redis/redis.go @@ -0,0 +1,10 @@ +package redis + +import ( + "github.com/xh-polaris/meowchat-content/biz/infrastructure/config" + "github.com/zeromicro/go-zero/core/stores/redis" +) + +func NewRedis(config *config.Config) *redis.Redis { + return redis.MustNewRedis(*config.Redis) +} diff --git a/go.mod b/go.mod index 2ef6a0e..b2efeee 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/kitex-contrib/obs-opentelemetry v0.2.3 github.com/mitchellh/mapstructure v1.1.2 github.com/xh-polaris/gopkg v0.0.0-20230805125627-ce41556a654d - github.com/xh-polaris/service-idl-gen-go v0.0.0-20230813101042-26c6385e25a8 + github.com/xh-polaris/service-idl-gen-go v0.0.0-20230819155341-4a3ac3fe3b89 github.com/zeromicro/go-zero v1.5.4 go.mongodb.org/mongo-driver v1.12.0 google.golang.org/grpc v1.56.2 diff --git a/go.sum b/go.sum index 7e9b178..ffb6afe 100644 --- a/go.sum +++ b/go.sum @@ -386,8 +386,8 @@ github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6 github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xh-polaris/gopkg v0.0.0-20230805125627-ce41556a654d h1:xAbXPYbhcqB9/NOnmwsGcjhTVQzRd0xP7jJpGTXmOHM= github.com/xh-polaris/gopkg v0.0.0-20230805125627-ce41556a654d/go.mod h1:eFkuwj6uq1k4hbDa66TijCWGL4PrNeWaNmAnxfWDeU0= -github.com/xh-polaris/service-idl-gen-go v0.0.0-20230813101042-26c6385e25a8 h1:us6cv8ashLDusy5qj4/9rS9E/pP3lFfpcFtdE22G+9Y= -github.com/xh-polaris/service-idl-gen-go v0.0.0-20230813101042-26c6385e25a8/go.mod h1:KjBt4ZOfugCsdAbFlrniKMDrpJAJobm8KEezTvKVnJM= +github.com/xh-polaris/service-idl-gen-go v0.0.0-20230819155341-4a3ac3fe3b89 h1:LxD9sZVUqcdi+6npBUvxm5NaNLLJlPLpWNmXNFDqWfE= +github.com/xh-polaris/service-idl-gen-go v0.0.0-20230819155341-4a3ac3fe3b89/go.mod h1:KjBt4ZOfugCsdAbFlrniKMDrpJAJobm8KEezTvKVnJM= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/provider/provider.go b/provider/provider.go index c64b78c..62c0dd7 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -10,6 +10,7 @@ import ( "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/moment" "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/plan" "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/post" + "github.com/xh-polaris/meowchat-content/biz/infrastructure/stores/redis" "github.com/xh-polaris/meowchat-content/biz/application/service" ) @@ -29,6 +30,7 @@ var ApplicationSet = wire.NewSet( var InfrastructureSet = wire.NewSet( config.NewConfig, + redis.NewRedis, MapperSet, ) diff --git a/provider/wire_gen.go b/provider/wire_gen.go index 65f20b3..ed66ec8 100644 --- a/provider/wire_gen.go +++ b/provider/wire_gen.go @@ -17,6 +17,7 @@ import ( "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/moment" "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/plan" "github.com/xh-polaris/meowchat-content/biz/infrastructure/mapper/post" + "github.com/xh-polaris/meowchat-content/biz/infrastructure/stores/redis" ) // Injectors from wire.go: @@ -38,15 +39,20 @@ func NewContentServerImpl() (*adaptor.ContentServerImpl, error) { } momentIMongoMapper := moment.NewMongoMapper(configConfig) momentIEsMapper := moment.NewEsMapper(configConfig) + redisRedis := redis.NewRedis(configConfig) momentService := &service.MomentService{ + Config: configConfig, MomentMongoMapper: momentIMongoMapper, MomentEsMapper: momentIEsMapper, + Redis: redisRedis, } postIMongoMapper := post.NewMongoMapper(configConfig) postIEsMapper := post.NewEsMapper(configConfig) postService := &service.PostService{ + Config: configConfig, PostMongoMapper: postIMongoMapper, PostEsMapper: postIEsMapper, + Redis: redisRedis, } planIMongoMapper := plan.NewMongoMapper(configConfig) planIEsMapper := plan.NewEsMapper(configConfig)