diff --git a/auto/api/v1/relax.go b/auto/api/v1/relax.go index 0f394cea..e88fc8c7 100644 --- a/auto/api/v1/relax.go +++ b/auto/api/v1/relax.go @@ -43,7 +43,12 @@ func RegisterRelaxServant(e *gin.Engine, s Relax) { return } resp, err := s.GetUnreadMsgCount(req) - s.Render(c, resp, err) + if err != nil { + s.Render(c, nil, err) + return + } + var rv _render_ = resp + rv.Render(c) }) } diff --git a/go.mod b/go.mod index 4676474b..b96e0d9b 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/alimy/mir/v4 v4.0.0 - github.com/alimy/tryst v0.8.0 + github.com/alimy/tryst v0.8.2 github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible github.com/allegro/bigcache/v3 v3.1.0 github.com/bufbuild/connect-go v1.10.0 @@ -79,6 +79,7 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.6 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect diff --git a/go.sum b/go.sum index 9ee164db..4f9b4638 100644 --- a/go.sum +++ b/go.sum @@ -125,8 +125,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alimy/mir/v4 v4.0.0 h1:MzGfmoLjjvR69jbZEmpKJO3tUuqB0RGRv1UWPbtukBg= github.com/alimy/mir/v4 v4.0.0/go.mod h1:d58dBvw2KImcVbAUANrciEV/of0arMNsI9c/5UNCMMc= -github.com/alimy/tryst v0.8.0 h1:21iEWSDheTHW8iIhWEwII6YOpQeDSGT5u21nq6rM/AE= -github.com/alimy/tryst v0.8.0/go.mod h1:K//dPeoE/nnv2Jw8C3iPE7n8mO6LVqAxVmqbopM9nAk= +github.com/alimy/tryst v0.8.2 h1:azu5B58vS6m/ZeHovYGWjVvEOJN2llDIBLxuN3qtMtk= +github.com/alimy/tryst v0.8.2/go.mod h1:ua2eJbFrisHPh7z93Bgc0jNBE8Khu1SCx2p/6t3OzZI= github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible h1:Sg/2xHwDrioHpxTN6WMiwbXTpUEinBpHsN7mG21Rc2k= github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/allegro/bigcache/v3 v3.1.0 h1:H2Vp8VOvxcrB91o86fUSVJFqeuz8kpyyB02eH3bSzwk= @@ -729,6 +729,8 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM= +github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= diff --git a/internal/conf/cache.go b/internal/conf/cache.go new file mode 100644 index 00000000..ae3875b2 --- /dev/null +++ b/internal/conf/cache.go @@ -0,0 +1,30 @@ +// Copyright 2023 ROC. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package conf + +import ( + "fmt" + + "github.com/alimy/tryst/cache" +) + +const ( + _defaultKeyPoolSize = 128 +) + +// 以下包含一些在cache中会用到的池化后的key +var ( + KeyUnreadMsg cache.KeyPool[int64] +) + +func initCacheKeyPool() { + poolSize := _defaultKeyPoolSize + if poolSize < CacheSetting.KeyPoolSize { + poolSize = CacheSetting.KeyPoolSize + } + KeyUnreadMsg = cache.MustKeyPool[int64](poolSize, func(key int64) string { + return fmt.Sprintf("paopao:unreadmsg:%d", key) + }) +} diff --git a/internal/conf/redis.go b/internal/conf/cache_redis.go similarity index 92% rename from internal/conf/redis.go rename to internal/conf/cache_redis.go index 93799b82..00564a31 100644 --- a/internal/conf/redis.go +++ b/internal/conf/cache_redis.go @@ -29,6 +29,8 @@ func MustRedisClient() rueidis.Client { log.Fatalf("create a redis client failed: %s", err) } _redisClient = client + // 顺便初始化一下CacheKeyPool + initCacheKeyPool() }) return _redisClient } diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 13c71b83..bc4be72f 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -35,6 +35,7 @@ var ( DocsServerSetting *httpServerConf MobileServerSetting *grpcServerConf AppSetting *appConf + CacheSetting *cacheConf EventManagerSetting *eventManagerConf CacheIndexSetting *cacheIndexConf SimpleCacheIndexSetting *simpleCacheIndexConf @@ -70,6 +71,7 @@ func setupSetting(suite []string, noDefault bool) error { objects := map[string]any{ "App": &AppSetting, + "Cache": &CacheSetting, "EventManager": &EventManagerSetting, "PprofServer": &PprofServerSetting, "WebServer": &WebServerSetting, @@ -117,6 +119,7 @@ func setupSetting(suite []string, noDefault bool) error { } } + CacheSetting.CientSideCacheExpire *= time.Second EventManagerSetting.TickWaitTime *= time.Second JWTSetting.Expire *= time.Second SimpleCacheIndexSetting.CheckTickDuration *= time.Second diff --git a/internal/conf/config.yaml b/internal/conf/config.yaml index bc23149b..5f6c8ceb 100644 --- a/internal/conf/config.yaml +++ b/internal/conf/config.yaml @@ -5,6 +5,10 @@ App: # APP基础设置项 DefaultContextTimeout: 60 DefaultPageSize: 10 MaxPageSize: 100 +Cache: + KeyPoolSize: 256 # 键的池大小, 设置范围[128, ++], 默认256 + CientSideCacheExpire: 60 # 客户端缓存过期时间 默认60s + UnreadMsgExpire: 60 # 未读消息过期时间,单位秒, 默认60s EventManager: # 事件管理器的配置参数 MinWorker: 10 # 最小后台工作者, 设置范围[5, ++], 默认10 MaxEventBuf: 100 # 最大log缓存条数, 设置范围[10, ++], 默认100 diff --git a/internal/conf/setting.go b/internal/conf/setting.go index 26c4395c..04fcd9c9 100644 --- a/internal/conf/setting.go +++ b/internal/conf/setting.go @@ -96,6 +96,12 @@ type appConf struct { MaxPageSize int } +type cacheConf struct { + KeyPoolSize int + CientSideCacheExpire time.Duration + UnreadMsgExpire int64 +} + type eventManagerConf struct { MinWorker int MaxEventBuf int diff --git a/internal/core/cache.go b/internal/core/cache.go index 8d8c3b42..2a0db675 100644 --- a/internal/core/cache.go +++ b/internal/core/cache.go @@ -97,3 +97,9 @@ type RedisCache interface { SetRechargeStatus(ctx context.Context, tradeNo string) error DelRechargeStatus(ctx context.Context, tradeNo string) error } + +type WebCache interface { + GetUnreadMsgCountResp(uid int64) ([]byte, error) + PutUnreadMsgCountResp(uid int64, data []byte) error + DelUnreadMsgCountResp(uid int64) error +} diff --git a/internal/dao/cache/cache.go b/internal/dao/cache/cache.go index 3a2938cb..05f6fce8 100644 --- a/internal/dao/cache/cache.go +++ b/internal/dao/cache/cache.go @@ -6,6 +6,7 @@ package cache import ( "context" + "sync" "time" "github.com/allegro/bigcache/v3" @@ -14,6 +15,10 @@ import ( "github.com/sirupsen/logrus" ) +var ( + _onceInit sync.Once +) + func NewRedisCache() core.RedisCache { return &redisCache{ c: conf.MustRedisClient(), @@ -48,6 +53,11 @@ func NewRedisCacheIndexService(ips core.IndexPostsService, ams core.Authorizatio return cacheIndex, cacheIndex } +func NewWebCache() core.WebCache { + lazyInitial() + return _webCache +} + func NewSimpleCacheIndexService(indexPosts core.IndexPostsService) (core.CacheIndexService, core.VersionInfo) { s := conf.SimpleCacheIndexSetting cacheIndex := &simpleCacheIndexServant{ @@ -88,3 +98,9 @@ func NewNoneCacheIndexService(indexPosts core.IndexPostsService) (core.CacheInde } return obj, obj } + +func lazyInitial() { + _onceInit.Do(func() { + _webCache = newWebCache() + }) +} diff --git a/internal/dao/cache/web.go b/internal/dao/cache/web.go new file mode 100644 index 00000000..d911c5bc --- /dev/null +++ b/internal/dao/cache/web.go @@ -0,0 +1,66 @@ +// Copyright 2023 ROC. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package cache + +import ( + "context" + "time" + + "github.com/Masterminds/semver/v3" + "github.com/redis/rueidis" + "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/pkg/utils" +) + +var ( + _webCache core.WebCache = (*redisWebCache)(nil) +) + +type redisWebCache struct { + cscExpire time.Duration + unreadMsgExpire int64 + c rueidis.Client +} + +func (s *redisWebCache) Name() string { + return "RedisWebCache" +} + +func (s *redisWebCache) Version() *semver.Version { + return semver.MustParse("v0.1.0") +} + +func (s *redisWebCache) GetUnreadMsgCountResp(uid int64) ([]byte, error) { + key := conf.KeyUnreadMsg.Get(uid) + res, err := rueidis.MGetCache(s.c, context.Background(), s.cscExpire, []string{key}) + if err != nil { + return nil, err + } + message := res[key] + return message.AsBytes() +} + +func (s *redisWebCache) PutUnreadMsgCountResp(uid int64, data []byte) error { + return s.c.Do(context.Background(), s.c.B().Set(). + Key(conf.KeyUnreadMsg.Get(uid)). + Value(utils.String(data)). + ExSeconds(s.unreadMsgExpire). + Build()). + Error() +} + +func (s *redisWebCache) DelUnreadMsgCountResp(uid int64) error { + return s.c.Do(context.Background(), s.c.B().Del().Key(conf.KeyUnreadMsg.Get(uid)).Build()).Error() +} + +func newWebCache() *redisWebCache { + s := conf.CacheSetting + return &redisWebCache{ + cscExpire: s.CientSideCacheExpire, + unreadMsgExpire: s.UnreadMsgExpire, + c: conf.MustRedisClient(), + } +} diff --git a/internal/model/joint/joint.go b/internal/model/joint/joint.go index fa7e4729..79246ece 100644 --- a/internal/model/joint/joint.go +++ b/internal/model/joint/joint.go @@ -14,3 +14,9 @@ type BasePageInfo struct { func (r *BasePageInfo) SetPageInfo(page int, pageSize int) { r.Page, r.PageSize = page, pageSize } + +type JsonResp struct { + Code int `json:"code"` + Msg string `json:"msg,omitempty"` + Data any `json:"data,omitempty"` +} diff --git a/internal/model/joint/json.go b/internal/model/joint/json.go new file mode 100644 index 00000000..ad71f5de --- /dev/null +++ b/internal/model/joint/json.go @@ -0,0 +1,15 @@ +// Copyright 2023 ROC. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package joint + +import ( + stdJson "encoding/json" + + "github.com/rocboss/paopao-ce/pkg/json" +) + +func RespMarshal(data any) (stdJson.RawMessage, error) { + return json.Marshal(data) +} diff --git a/internal/model/web/relax.go b/internal/model/web/relax.go index 432f86c5..e75ae315 100644 --- a/internal/model/web/relax.go +++ b/internal/model/web/relax.go @@ -4,10 +4,31 @@ package web +import ( + "encoding/json" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/rocboss/paopao-ce/internal/model/joint" +) + type GetUnreadMsgCountReq struct { SimpleInfo `json:"-" binding:"-"` } type GetUnreadMsgCountResp struct { - Count int64 `json:"count"` + Count int64 `json:"count"` + JsonResp json.RawMessage `json:"-"` +} + +func (r *GetUnreadMsgCountResp) Render(c *gin.Context) { + if len(r.JsonResp) != 0 { + c.JSON(http.StatusOK, r.JsonResp) + } else { + c.JSON(http.StatusOK, &joint.JsonResp{ + Code: 0, + Msg: "success", + Data: r, + }) + } } diff --git a/internal/servants/base/base.go b/internal/servants/base/base.go index 3492c73f..afe857c8 100644 --- a/internal/servants/base/base.go +++ b/internal/servants/base/base.go @@ -22,6 +22,7 @@ import ( "github.com/rocboss/paopao-ce/internal/dao" "github.com/rocboss/paopao-ce/internal/dao/cache" "github.com/rocboss/paopao-ce/internal/events" + "github.com/rocboss/paopao-ce/internal/model/joint" "github.com/rocboss/paopao-ce/pkg/app" "github.com/rocboss/paopao-ce/pkg/xerror" ) @@ -39,12 +40,6 @@ type DaoServant struct { Redis core.RedisCache } -type JsonResp struct { - Code int `json:"code"` - Msg string `json:"msg,omitempty"` - Data any `json:"data,omitempty"` -} - type SentryHubSetter interface { SetSentryHub(hub *sentry.Hub) } @@ -145,13 +140,13 @@ func bindAnySentry(c *gin.Context, obj any) mir.Error { func RenderAny(c *gin.Context, data any, err mir.Error) { if err == nil { - c.JSON(http.StatusOK, &JsonResp{ + c.JSON(http.StatusOK, &joint.JsonResp{ Code: 0, Msg: "success", Data: data, }) } else { - c.JSON(xerror.HttpStatusCode(err), &JsonResp{ + c.JSON(xerror.HttpStatusCode(err), &joint.JsonResp{ Code: err.StatusCode(), Msg: err.Error(), }) @@ -164,13 +159,13 @@ func (s *BaseServant) Bind(c *gin.Context, obj any) mir.Error { func (s *BaseServant) Render(c *gin.Context, data any, err mir.Error) { if err == nil { - c.JSON(http.StatusOK, &JsonResp{ + c.JSON(http.StatusOK, &joint.JsonResp{ Code: 0, Msg: "success", Data: data, }) } else { - c.JSON(xerror.HttpStatusCode(err), &JsonResp{ + c.JSON(xerror.HttpStatusCode(err), &joint.JsonResp{ Code: err.StatusCode(), Msg: err.Error(), }) diff --git a/internal/servants/web/core.go b/internal/servants/web/core.go index fb822d3c..b0c42019 100644 --- a/internal/servants/web/core.go +++ b/internal/servants/web/core.go @@ -37,6 +37,7 @@ type coreSrv struct { *base.DaoServant oss core.ObjectStorageService + wc core.WebCache } func (s *coreSrv) Chain() gin.HandlersChain { @@ -140,6 +141,8 @@ func (s *coreSrv) ReadMessage(req *web.ReadMessageReq) mir.Error { logrus.Errorf("Ds.ReadMessage err: %s", err) return web.ErrReadMessageFailed } + // 清除未读消息数缓存,不需要处理错误 + s.wc.DelUnreadMsgCountResp(req.Uid) return nil } @@ -168,6 +171,9 @@ func (s *coreSrv) SendUserWhisper(req *web.SendWhisperReq) mir.Error { return web.ErrSendWhisperFailed } + // 清除接收者未读消息缓存, 不需要处理错误 + s.wc.DelUnreadMsgCountResp(req.UserID) + // 写入当日(自然日)计数缓存 s.Redis.IncrCountWhisper(ctx, req.Uid) @@ -365,9 +371,10 @@ func (s *coreSrv) TweetStarStatus(req *web.TweetStarStatusReq) (*web.TweetStarSt return resp, nil } -func newCoreSrv(s *base.DaoServant, oss core.ObjectStorageService) api.Core { +func newCoreSrv(s *base.DaoServant, oss core.ObjectStorageService, wc core.WebCache) api.Core { return &coreSrv{ DaoServant: s, oss: oss, + wc: wc, } } diff --git a/internal/servants/web/events.go b/internal/servants/web/events.go new file mode 100644 index 00000000..f5b354df --- /dev/null +++ b/internal/servants/web/events.go @@ -0,0 +1,84 @@ +// Copyright 2023 ROC. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package web + +import ( + "encoding/json" + "fmt" + + "github.com/alimy/tryst/event" + "github.com/rocboss/paopao-ce/internal/core" + "github.com/rocboss/paopao-ce/internal/core/ms" + "github.com/rocboss/paopao-ce/internal/events" + "github.com/rocboss/paopao-ce/internal/model/joint" + "github.com/rocboss/paopao-ce/internal/model/web" +) + +type cacheUnreadMsgEvent struct { + event.UnimplementedEvent + ds core.DataService + wc core.WebCache + uid int64 +} + +type createMessageEvent struct { + event.UnimplementedEvent + ds core.DataService + wc core.WebCache + message *ms.Message +} + +func onCacheUnreadMsgEvent(uid int64) { + events.OnEvent(&cacheUnreadMsgEvent{ + ds: _ds, + wc: _wc, + uid: uid, + }) +} + +func onCreateMessageEvent(data *ms.Message) { + events.OnEvent(&createMessageEvent{ + ds: _ds, + wc: _wc, + message: data, + }) +} + +func (e *cacheUnreadMsgEvent) Name() string { + return "cacheUnreadMsgEvent" +} + +func (e *cacheUnreadMsgEvent) Action() error { + count, err := e.ds.GetUnreadCount(e.uid) + if err != nil { + return fmt.Errorf("cacheUnreadMsgEvent action occurs error: %w", err) + } + resp := &joint.JsonResp{ + Code: 0, + Msg: "success", + Data: &web.GetUnreadMsgCountResp{ + Count: count, + }, + } + data, err := json.Marshal(resp) + if err != nil { + return fmt.Errorf("cacheUnreadMsgEvent action marshal resp occurs error: %w", err) + } + if err = e.wc.PutUnreadMsgCountResp(e.uid, data); err != nil { + return fmt.Errorf("cacheUnreadMsgEvent action put resp data to redis cache occurs error: %w", err) + } + return nil +} + +func (e *createMessageEvent) Name() string { + return "createMessageEvent" +} + +func (e *createMessageEvent) Action() (err error) { + if _, err = e.ds.CreateMessage(e.message); err == nil { + err = e.wc.DelUnreadMsgCountResp(e.message.ReceiverUserID) + } + return +} diff --git a/internal/servants/web/priv.go b/internal/servants/web/priv.go index f3654415..99d20f8b 100644 --- a/internal/servants/web/priv.go +++ b/internal/servants/web/priv.go @@ -286,8 +286,7 @@ func (s *privSrv) CreateTweet(req *web.CreateTweetReq) (_ *web.CreateTweetResp, } // 创建消息提醒 - // TODO: 优化消息提醒处理机制 - go s.Ds.CreateMessage(&ms.Message{ + onCreateMessageEvent(&ms.Message{ SenderUserID: req.User.ID, ReceiverUserID: user.ID, Type: ms.MsgTypePost, @@ -390,7 +389,7 @@ func (s *privSrv) CreateCommentReply(req *web.CreateCommentReplyReq) (*web.Creat // 创建用户消息提醒 commentMaster, err := s.Ds.GetUserByID(comment.UserID) if err == nil && commentMaster.ID != req.Uid { - go s.Ds.CreateMessage(&ms.Message{ + onCreateMessageEvent(&ms.Message{ SenderUserID: req.Uid, ReceiverUserID: commentMaster.ID, Type: ms.MsgTypeReply, @@ -402,7 +401,7 @@ func (s *privSrv) CreateCommentReply(req *web.CreateCommentReplyReq) (*web.Creat } postMaster, err := s.Ds.GetUserByID(post.UserID) if err == nil && postMaster.ID != req.Uid && commentMaster.ID != postMaster.ID { - go s.Ds.CreateMessage(&ms.Message{ + onCreateMessageEvent(&ms.Message{ SenderUserID: req.Uid, ReceiverUserID: postMaster.ID, Type: ms.MsgTypeReply, @@ -416,7 +415,7 @@ func (s *privSrv) CreateCommentReply(req *web.CreateCommentReplyReq) (*web.Creat user, err := s.Ds.GetUserByID(atUserID) if err == nil && user.ID != req.Uid && commentMaster.ID != user.ID && postMaster.ID != user.ID { // 创建消息提醒 - go s.Ds.CreateMessage(&ms.Message{ + onCreateMessageEvent(&ms.Message{ SenderUserID: req.Uid, ReceiverUserID: user.ID, Type: ms.MsgTypeReply, @@ -522,7 +521,7 @@ func (s *privSrv) CreateComment(req *web.CreateCommentReq) (_ *web.CreateComment // 创建用户消息提醒 postMaster, err := s.Ds.GetUserByID(post.UserID) if err == nil && postMaster.ID != req.Uid { - go s.Ds.CreateMessage(&ms.Message{ + onCreateMessageEvent(&ms.Message{ SenderUserID: req.Uid, ReceiverUserID: postMaster.ID, Type: ms.MsgtypeComment, @@ -538,7 +537,7 @@ func (s *privSrv) CreateComment(req *web.CreateCommentReq) (_ *web.CreateComment } // 创建消息提醒 - go s.Ds.CreateMessage(&ms.Message{ + onCreateMessageEvent(&ms.Message{ SenderUserID: req.Uid, ReceiverUserID: user.ID, Type: ms.MsgtypeComment, diff --git a/internal/servants/web/relax.go b/internal/servants/web/relax.go index bef7da90..f2fee368 100644 --- a/internal/servants/web/relax.go +++ b/internal/servants/web/relax.go @@ -8,10 +8,11 @@ import ( "github.com/alimy/mir/v4" "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/model/web" "github.com/rocboss/paopao-ce/internal/servants/base" "github.com/rocboss/paopao-ce/internal/servants/chain" - "github.com/rocboss/paopao-ce/pkg/xerror" + "github.com/sirupsen/logrus" ) var ( @@ -21,6 +22,7 @@ var ( type relaxSrv struct { api.UnimplementedRelaxServant *base.DaoServant + wc core.WebCache } func (s *relaxSrv) Chain() gin.HandlersChain { @@ -28,17 +30,22 @@ func (s *relaxSrv) Chain() gin.HandlersChain { } func (s *relaxSrv) GetUnreadMsgCount(req *web.GetUnreadMsgCountReq) (*web.GetUnreadMsgCountResp, mir.Error) { - count, err := s.Ds.GetUnreadCount(req.Uid) - if err != nil { - return nil, xerror.ServerError + if data, xerr := s.wc.GetUnreadMsgCountResp(req.Uid); xerr == nil && len(data) > 0 { + // logrus.Debugln("GetUnreadMsgCount get resp from cache") + return &web.GetUnreadMsgCountResp{ + JsonResp: data, + }, nil + } else { + logrus.Warnf("GetUnreadMsgCount from cache occurs error: %s", xerr) } - return &web.GetUnreadMsgCountResp{ - Count: count, - }, nil + // 使用缓存机制特殊处理 + onCacheUnreadMsgEvent(req.Uid) + return &web.GetUnreadMsgCountResp{}, nil } -func newRelaxSrv(s *base.DaoServant) api.Relax { +func newRelaxSrv(s *base.DaoServant, wc core.WebCache) api.Relax { return &relaxSrv{ DaoServant: s, + wc: wc, } } diff --git a/internal/servants/web/web.go b/internal/servants/web/web.go index 9c955310..9d8fe081 100644 --- a/internal/servants/web/web.go +++ b/internal/servants/web/web.go @@ -11,27 +11,31 @@ import ( "github.com/gin-gonic/gin" api "github.com/rocboss/paopao-ce/auto/api/v1" "github.com/rocboss/paopao-ce/internal/conf" + "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao" + "github.com/rocboss/paopao-ce/internal/dao/cache" "github.com/rocboss/paopao-ce/internal/servants/base" ) var ( _enablePhoneVerify bool _disallowUserRegister bool + _ds core.DataService + _wc core.WebCache + _oss core.ObjectStorageService _onceInitial sync.Once ) // RouteWeb register web route func RouteWeb(e *gin.Engine) { lazyInitial() - oss := dao.ObjectStorageService() ds := base.NewDaoServant() // aways register servants api.RegisterAdminServant(e, newAdminSrv(ds)) - api.RegisterCoreServant(e, newCoreSrv(ds, oss)) - api.RegisterRelaxServant(e, newRelaxSrv(ds)) + api.RegisterCoreServant(e, newCoreSrv(ds, _oss, _wc)) + api.RegisterRelaxServant(e, newRelaxSrv(ds, _wc)) api.RegisterLooseServant(e, newLooseSrv(ds)) - api.RegisterPrivServant(e, newPrivSrv(ds, oss)) + api.RegisterPrivServant(e, newPrivSrv(ds, _oss)) api.RegisterPubServant(e, newPubSrv(ds)) api.RegisterFollowshipServant(e, newFollowshipSrv(ds)) api.RegisterFriendshipServant(e, newFriendshipSrv(ds)) @@ -48,5 +52,8 @@ func lazyInitial() { _onceInitial.Do(func() { _enablePhoneVerify = cfg.If("Sms") _disallowUserRegister = cfg.If("Web:DisallowUserRegister") + _oss = dao.ObjectStorageService() + _ds = dao.DataService() + _wc = cache.NewWebCache() }) } diff --git a/pkg/utils/str.go b/pkg/utils/str.go index a69f02ec..199ad092 100644 --- a/pkg/utils/str.go +++ b/pkg/utils/str.go @@ -7,6 +7,7 @@ package utils import ( "math/rand" "time" + "unsafe" ) type StrType int @@ -41,3 +42,10 @@ func RandStr(size int, kind StrType) []byte { } return result } + +func String(data []byte) string { + if size := len(data); size > 0 { + return unsafe.String(unsafe.SliceData(data), size) + } + return "" +}