From ef7fab579bfa9b83c14317d01b665078ed6c1a7c Mon Sep 17 00:00:00 2001 From: Michael Li Date: Mon, 9 Jan 2023 14:13:46 +0800 Subject: [PATCH] lightship: add Lightship feature base support --- README.md | 8 +-- ROADMAP.md | 2 +- features-status.md | 6 +-- internal/dao/jinzhu/index.go | 96 +++++++++++++++++++++++++++++------ internal/dao/jinzhu/jinzhu.go | 37 ++++++++++---- pkg/debug/errors.go | 13 +++++ 6 files changed, 128 insertions(+), 34 deletions(-) create mode 100644 pkg/debug/errors.go diff --git a/README.md b/README.md index 4ebdd34d..11a0be12 100644 --- a/README.md +++ b/README.md @@ -328,8 +328,8 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r |`Bot` | 子服务 | WIP | 开启Bot服务| |`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务| |`Docs` | 子服务 | WIP | 开启开发者文档服务| -|`Frontend:Web` | 子服务 | 内测 | 开启独立前端服务| -|`Frontend:EmbedWeb` | 子服务 | 内测 | 开启内嵌于后端Web API服务中的前端服务| +|`Frontend:Web` | 子服务 | 稳定 | 开启独立前端服务| +|`Frontend:EmbedWeb` | 子服务 | 稳定 | 开启内嵌于后端Web API服务中的前端服务| |`Deprecated:Web` | 子服务 | 稳定 | 开启旧的Web服务| |`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM,默认使用 `Gorm` + `MySQL`组合| |`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM| @@ -345,7 +345,7 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r |`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能| |`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能| |`Redis` | 缓存 | 稳定 | Redis缓存功能 | -|`SimpleCacheIndex` | 缓存 | 稳定 | 提供简单的 广场推文列表 的缓存功能 | +|`SimpleCacheIndex` | 缓存 | Deprecated | 提供简单的 广场推文列表 的缓存功能 | |`BigCacheIndex` | 缓存 | 稳定(推荐) | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 | |`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 | |`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 | @@ -355,7 +355,7 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r |`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 | |`Friendship` | 关系模式 | 内测(默认) | 弱关系好友模式,类似微信朋友圈 | |`Followship` | 关系模式 | WIP | 关注者模式,类似Twitter的Follow模式 | -|`Lightship` | 关系模式 | WIP | 开放模式,所有推文都公开可见 | +|`Lightship` | 关系模式 | 内测 | 开放模式,所有推文都公开可见 | |`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 | |`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 | |`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能,提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) | diff --git a/ROADMAP.md b/ROADMAP.md index fc0e6681..2ab924bf 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,7 +3,7 @@ paopao-ce roadmap. ### v0.2.0 * [x] add `Friendship` feature -* [ ] add `Lightship` feature +* [x] add `Lightship` feature * [ ] add `Sqlx` feature * [x] add new `Web` service * [x] add `Frontend:Web` feature diff --git a/features-status.md b/features-status.md index bfc6f80c..c2ac559b 100644 --- a/features-status.md +++ b/features-status.md @@ -97,7 +97,7 @@ * [ ] 提按文档 * [x] 接口定义 * [x] 业务逻辑实现 -* `SimpleCacheIndex` 提供简单的 广场推文列表 的缓存功能能; +* `SimpleCacheIndex` 提供简单的 广场推文列表 的缓存功能能(目前状态: Deprecated); * [ ] 提按文档 * [x] 接口定义 * [x] 业务逻辑实现 @@ -144,8 +144,8 @@ * [ ] 业务逻辑实现 * `Lightship` 开放模式,所有推文都公开可见(目前状态: WIP); * [x] 提按文档 - * [ ] 接口定义 - * [ ] 业务逻辑实现 + * [x] 接口定义 + * [x] 业务逻辑实现 ### 支付: * `Alipay` 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能; diff --git a/internal/dao/jinzhu/index.go b/internal/dao/jinzhu/index.go index 7548de49..fc7e2007 100644 --- a/internal/dao/jinzhu/index.go +++ b/internal/dao/jinzhu/index.go @@ -7,43 +7,41 @@ package jinzhu import ( "github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr" + "github.com/rocboss/paopao-ce/pkg/debug" "github.com/sirupsen/logrus" "gorm.io/gorm" ) var ( - _ core.IndexPostsService = (*indexPostsServant)(nil) + _ core.IndexPostsService = (*friendIndexServant)(nil) + _ core.IndexPostsService = (*followIndexServant)(nil) + _ core.IndexPostsService = (*lightIndexServant)(nil) _ core.IndexPostsService = (*simpleIndexPostsServant)(nil) ) -type indexPostsServant struct { +type friendIndexServant struct { ams core.AuthorizationManageService ths core.TweetHelpService db *gorm.DB } -type simpleIndexPostsServant struct { +type followIndexServant struct { ths core.TweetHelpService db *gorm.DB } -func newIndexPostsService(db *gorm.DB) core.IndexPostsService { - return &indexPostsServant{ - ams: NewAuthorizationManageService(), - ths: newTweetHelpService(db), - db: db, - } +type lightIndexServant struct { + ths core.TweetHelpService + db *gorm.DB } -func newSimpleIndexPostsService(db *gorm.DB) core.IndexPostsService { - return &simpleIndexPostsServant{ - ths: newTweetHelpService(db), - db: db, - } +type simpleIndexPostsServant struct { + ths core.TweetHelpService + db *gorm.DB } // IndexPosts 根据userId查询广场推文列表,简单做到不同用户的主页都是不同的; -func (s *indexPostsServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { +func (s *friendIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { predicates := dbr.Predicates{ "ORDER": []any{"is_top DESC, latest_replied_on DESC"}, } @@ -77,6 +75,45 @@ func (s *indexPostsServant) IndexPosts(user *core.User, offset int, limit int) ( }, nil } +// IndexPosts 根据userId查询广场推文列表 +func (s *followIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { + // TODO + return nil, debug.ErrNotImplemented +} + +// IndexPosts 根据userId查询广场推文列表,获取公开可见Tweet或者所属用户的私有Tweet +func (s *lightIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) { + predicates := dbr.Predicates{ + "ORDER": []any{"is_top DESC, latest_replied_on DESC"}, + } + if user == nil { + predicates["visibility = ?"] = []any{dbr.PostVisitPublic} + } else if !user.IsAdmin { + args := []any{dbr.PostVisitPublic, dbr.PostVisitPrivate, user.ID} + predicates["visibility = ? OR (visibility = ? AND user_id = ?)"] = args + } + + posts, err := (&dbr.Post{}).Fetch(s.db, predicates, offset, limit) + if err != nil { + logrus.Debugf("gormIndexPostsServant.IndexPosts err: %v", err) + return nil, err + } + formatPosts, err := s.ths.MergePosts(posts) + if err != nil { + return nil, err + } + + total, err := (&dbr.Post{}).CountBy(s.db, predicates) + if err != nil { + return nil, err + } + + return &core.IndexTweetList{ + Tweets: formatPosts, + Total: total, + }, nil +} + // simpleCacheIndexGetPosts simpleCacheIndex 专属获取广场推文列表函数 func (s *simpleIndexPostsServant) IndexPosts(_user *core.User, offset int, limit int) (*core.IndexTweetList, error) { predicates := dbr.Predicates{ @@ -105,3 +142,32 @@ func (s *simpleIndexPostsServant) IndexPosts(_user *core.User, offset int, limit Total: total, }, nil } + +func newFriendIndexService(db *gorm.DB, ams core.AuthorizationManageService, ths core.TweetHelpService) core.IndexPostsService { + return &friendIndexServant{ + ams: ams, + ths: ths, + db: db, + } +} + +func newFollowIndexService(db *gorm.DB, ths core.TweetHelpService) core.IndexPostsService { + return &followIndexServant{ + ths: ths, + db: db, + } +} + +func newLightIndexService(db *gorm.DB, ths core.TweetHelpService) core.IndexPostsService { + return &lightIndexServant{ + ths: ths, + db: db, + } +} + +func newSimpleIndexPostsService(db *gorm.DB, ths core.TweetHelpService) core.IndexPostsService { + return &simpleIndexPostsServant{ + ths: ths, + db: db, + } +} diff --git a/internal/dao/jinzhu/jinzhu.go b/internal/dao/jinzhu/jinzhu.go index f708e064..6d15f1b5 100644 --- a/internal/dao/jinzhu/jinzhu.go +++ b/internal/dao/jinzhu/jinzhu.go @@ -40,33 +40,48 @@ type dataServant struct { } func NewDataService() (core.DataService, core.VersionInfo) { - // initialize CacheIndex if needed var ( - c core.CacheIndexService - v core.VersionInfo + v core.VersionInfo + cis core.CacheIndexService + ips core.IndexPostsService ) db := conf.MustGormDB() pvs := security.NewPhoneVerifyService() + ams := NewAuthorizationManageService() + ths := newTweetHelpService(db) - i := newIndexPostsService(db) + // initialize core.IndexPostsService + if cfg.If("Friendship") { + ips = newFriendIndexService(db, ams, ths) + } else if cfg.If("Followship") { + ips = newFollowIndexService(db, ths) + } else if cfg.If("Lightship") { + ips = newLightIndexService(db, ths) + } else { + // default use lightship post index service + ips = newLightIndexService(db, ths) + } + + // initialize core.CacheIndexService if cfg.If("SimpleCacheIndex") { - i = newSimpleIndexPostsService(db) - c, v = cache.NewSimpleCacheIndexService(i) + // simpleCache use special post index service + ips = newSimpleIndexPostsService(db, ths) + cis, v = cache.NewSimpleCacheIndexService(ips) } else if cfg.If("BigCacheIndex") { - a := newAuthorizationManageService(db) - c, v = cache.NewBigCacheIndexService(i, a) + // TODO: make cache index post in different scence like friendship/followship/lightship + cis, v = cache.NewBigCacheIndexService(ips, ams) } else { - c, v = cache.NewNoneCacheIndexService(i) + cis, v = cache.NewNoneCacheIndexService(ips) } logrus.Infof("use %s as cache index service by version: %s", v.Name(), v.Version()) ds := &dataServant{ - IndexPostsService: c, + IndexPostsService: cis, WalletService: newWalletService(db), MessageService: newMessageService(db), TopicService: newTopicService(db), TweetService: newTweetService(db), - TweetManageService: newTweetManageService(db, c), + TweetManageService: newTweetManageService(db, cis), TweetHelpService: newTweetHelpService(db), CommentService: newCommentService(db), CommentManageService: newCommentManageService(db), diff --git a/pkg/debug/errors.go b/pkg/debug/errors.go new file mode 100644 index 00000000..04a404ca --- /dev/null +++ b/pkg/debug/errors.go @@ -0,0 +1,13 @@ +// 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 debug + +import ( + "errors" +) + +var ( + ErrNotImplemented = errors.New("not implemented") +)