feat: community RPC 从内存存储迁移到 ent 数据库

This commit is contained in:
zetaloop
2026-04-24 08:16:31 +08:00
parent 5ad579f03c
commit 6cc14479c5
69 changed files with 14396 additions and 501 deletions
@@ -4,8 +4,11 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/commentlikes"
"juwan-backend/app/community/rpc/internal/models/comments"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
"juwan-backend/app/snowflake/rpc/snowflake"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -30,26 +33,39 @@ func (l *AddCommentLikesLogic) AddCommentLikes(in *pb.AddCommentLikesReq) (*pb.A
return nil, errors.New("commentId and userId are required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
comment, ok := store.Comments[in.GetCommentId()]
if !ok || comment.GetDeletedAt() > 0 {
exists, err := l.svcCtx.CommunityModelRO.Comments.Query().
Where(comments.IDEQ(in.GetCommentId()), comments.DeletedAtIsNil()).
Exist(l.ctx)
if err != nil || !exists {
return nil, errors.New("comment not found")
}
key := commentLikeKey(in.GetCommentId(), in.GetUserId())
if _, exists := store.CommentLikes[key]; exists {
dup, _ := l.svcCtx.CommunityModelRO.CommentLikes.Query().
Where(commentlikes.CommentIDEQ(in.GetCommentId()), commentlikes.UserIDEQ(in.GetUserId())).
Exist(l.ctx)
if dup {
return &pb.AddCommentLikesResp{}, nil
}
store.CommentLikes[key] = &pb.CommentLikes{
CommentId: in.GetCommentId(),
UserId: in.GetUserId(),
CreatedAt: nowUnix(in.GetCreatedAt()),
idResp, err := l.svcCtx.Snowflake.NextId(l.ctx, &snowflake.NextIdReq{})
if err != nil {
return nil, errors.New("create comment like id failed")
}
comment.LikeCount++
_, err = l.svcCtx.CommunityModelRW.CommentLikes.Create().
SetID(idResp.Id).
SetCommentID(in.GetCommentId()).
SetUserID(in.GetUserId()).
Save(l.ctx)
if err != nil {
logx.Errorf("addCommentLikes err: %v", err)
return nil, errors.New("add comment like failed")
}
l.svcCtx.CommunityModelRW.Comments.Update().
Where(comments.IDEQ(in.GetCommentId())).
AddLikeCount(1).
Exec(l.ctx)
return &pb.AddCommentLikesResp{}, nil
}
@@ -4,8 +4,10 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
"juwan-backend/app/snowflake/rpc/snowflake"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -36,27 +38,33 @@ func (l *AddCommentsLogic) AddComments(in *pb.AddCommentsReq) (*pb.AddCommentsRe
return nil, errors.New("content is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
post, ok := store.Posts[in.GetPostId()]
if !ok || post.GetDeletedAt() > 0 {
exists, err := l.svcCtx.CommunityModelRO.Posts.Query().
Where(posts.IDEQ(in.GetPostId()), posts.DeletedAtIsNil()).
Exist(l.ctx)
if err != nil || !exists {
return nil, errors.New("post not found")
}
now := nowUnix(in.GetCreatedAt())
comment := &pb.Comments{
Id: store.NextComment(),
PostId: in.GetPostId(),
AuthorId: in.GetAuthorId(),
Content: in.GetContent(),
LikeCount: 0,
CreatedAt: now,
idResp, err := l.svcCtx.Snowflake.NextId(l.ctx, &snowflake.NextIdReq{})
if err != nil {
return nil, errors.New("create comment id failed")
}
store.Comments[comment.Id] = comment
post.CommentCount++
post.UpdatedAt = now
_, err = l.svcCtx.CommunityModelRW.Comments.Create().
SetID(idResp.Id).
SetPostID(in.GetPostId()).
SetAuthorID(in.GetAuthorId()).
SetContent(in.GetContent()).
Save(l.ctx)
if err != nil {
logx.Errorf("addComments err: %v", err)
return nil, errors.New("add comment failed")
}
l.svcCtx.CommunityModelRW.Posts.Update().
Where(posts.IDEQ(in.GetPostId())).
AddCommentCount(1).
Exec(l.ctx)
return &pb.AddCommentsResp{}, nil
}
@@ -4,8 +4,11 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/postlikes"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
"juwan-backend/app/snowflake/rpc/snowflake"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -26,31 +29,43 @@ func NewAddPostLikesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AddP
// -----------------------postLikes-----------------------
func (l *AddPostLikesLogic) AddPostLikes(in *pb.AddPostLikesReq) (*pb.AddPostLikesResp, error) {
// todo: add your logic here and delete this line
if in.GetPostId() <= 0 || in.GetUserId() <= 0 {
return nil, errors.New("postId and userId are required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
post, ok := store.Posts[in.GetPostId()]
if !ok || post.GetDeletedAt() > 0 {
exists, err := l.svcCtx.CommunityModelRO.Posts.Query().
Where(posts.IDEQ(in.GetPostId()), posts.DeletedAtIsNil()).
Exist(l.ctx)
if err != nil || !exists {
return nil, errors.New("post not found")
}
key := postLikeKey(in.GetPostId(), in.GetUserId())
if _, exists := store.PostLikes[key]; exists {
dup, _ := l.svcCtx.CommunityModelRO.PostLikes.Query().
Where(postlikes.PostIDEQ(in.GetPostId()), postlikes.UserIDEQ(in.GetUserId())).
Exist(l.ctx)
if dup {
return &pb.AddPostLikesResp{}, nil
}
store.PostLikes[key] = &pb.PostLikes{
PostId: in.GetPostId(),
UserId: in.GetUserId(),
CreatedAt: nowUnix(in.GetCreatedAt()),
idResp, err := l.svcCtx.Snowflake.NextId(l.ctx, &snowflake.NextIdReq{})
if err != nil {
return nil, errors.New("create post like id failed")
}
post.LikeCount++
_, err = l.svcCtx.CommunityModelRW.PostLikes.Create().
SetID(idResp.Id).
SetPostID(in.GetPostId()).
SetUserID(in.GetUserId()).
Save(l.ctx)
if err != nil {
logx.Errorf("addPostLikes err: %v", err)
return nil, errors.New("add post like failed")
}
l.svcCtx.CommunityModelRW.Posts.Update().
Where(posts.IDEQ(in.GetPostId())).
AddLikeCount(1).
Exec(l.ctx)
return &pb.AddPostLikesResp{}, nil
}
@@ -6,6 +6,7 @@ import (
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
"juwan-backend/app/snowflake/rpc/snowflake"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -36,32 +37,38 @@ func (l *AddPostsLogic) AddPosts(in *pb.AddPostsReq) (*pb.AddPostsResp, error) {
return nil, errors.New("content is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
idResp, err := l.svcCtx.Snowflake.NextId(l.ctx, &snowflake.NextIdReq{})
if err != nil {
return nil, errors.New("create post id failed")
}
now := nowUnix(in.GetCreatedAt())
post := &pb.Posts{
Id: store.NextPost(),
AuthorId: in.GetAuthorId(),
AuthorRole: in.GetAuthorRole(),
Title: in.GetTitle(),
Content: in.GetContent(),
Images: append([]string(nil), in.GetImages()...),
Tags: append([]string(nil), in.GetTags()...),
LinkedOrderId: in.GetLinkedOrderId(),
QuotedPostId: in.GetQuotedPostId(),
LikeCount: 0,
CommentCount: 0,
Pinned: in.GetPinned(),
SearchText: in.GetTitle() + " " + in.GetContent(),
CreatedAt: now,
UpdatedAt: now,
authorRole := in.GetAuthorRole()
if authorRole == "" {
authorRole = "consumer"
}
if post.AuthorRole == "" {
post.AuthorRole = "consumer"
creator := l.svcCtx.CommunityModelRW.Posts.Create().
SetID(idResp.Id).
SetAuthorID(in.GetAuthorId()).
SetAuthorRole(authorRole).
SetTitle(in.GetTitle()).
SetContent(in.GetContent()).
SetImages(toTextArray(in.GetImages())).
SetTags(toTextArray(in.GetTags())).
SetPinned(in.GetPinned())
if in.GetLinkedOrderId() != 0 {
creator = creator.SetLinkedOrderID(in.GetLinkedOrderId())
}
if in.GetQuotedPostId() != 0 {
creator = creator.SetQuotedPostID(in.GetQuotedPostId())
}
_, err = creator.Save(l.ctx)
if err != nil {
logx.Errorf("addPosts err: %v", err)
return nil, errors.New("add post failed")
}
store.Posts[post.Id] = post
return &pb.AddPostsResp{}, nil
}
@@ -4,6 +4,8 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/commentlikes"
"juwan-backend/app/community/rpc/internal/models/comments"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,36 +31,33 @@ func (l *DelCommentLikesLogic) DelCommentLikes(in *pb.DelCommentLikesReq) (*pb.D
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
if in.UserId != nil && in.GetUserId() > 0 {
key := commentLikeKey(in.GetId(), in.GetUserId())
if _, ok := store.CommentLikes[key]; ok {
delete(store.CommentLikes, key)
if comment, ok := store.Comments[in.GetId()]; ok && comment.LikeCount > 0 {
comment.LikeCount--
}
n, err := l.svcCtx.CommunityModelRW.CommentLikes.Delete().
Where(commentlikes.CommentIDEQ(in.GetId()), commentlikes.UserIDEQ(in.GetUserId())).
Exec(l.ctx)
if err != nil {
logx.Errorf("delCommentLikes err: %v", err)
}
if n > 0 {
l.svcCtx.CommunityModelRW.Comments.Update().
Where(comments.IDEQ(in.GetId()), comments.LikeCountGT(0)).
AddLikeCount(-1).
Exec(l.ctx)
}
return &pb.DelCommentLikesResp{}, nil
}
removed := int64(0)
for key, like := range store.CommentLikes {
if like.GetCommentId() == in.GetId() {
delete(store.CommentLikes, key)
removed++
}
n, err := l.svcCtx.CommunityModelRW.CommentLikes.Delete().
Where(commentlikes.CommentIDEQ(in.GetId())).
Exec(l.ctx)
if err != nil {
logx.Errorf("delCommentLikes err: %v", err)
}
if removed > 0 {
if comment, ok := store.Comments[in.GetId()]; ok {
if comment.LikeCount >= removed {
comment.LikeCount -= removed
} else {
comment.LikeCount = 0
}
}
if n > 0 {
l.svcCtx.CommunityModelRW.Comments.Update().
Where(comments.IDEQ(in.GetId()), comments.LikeCountGTE(n)).
AddLikeCount(-n).
Exec(l.ctx)
}
return &pb.DelCommentLikesResp{}, nil
@@ -3,7 +3,10 @@ package logic
import (
"context"
"errors"
"time"
"juwan-backend/app/community/rpc/internal/models/comments"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,22 +32,26 @@ func (l *DelCommentsLogic) DelComments(in *pb.DelCommentsReq) (*pb.DelCommentsRe
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
comment, ok := store.Comments[in.GetId()]
if !ok {
comment, err := l.svcCtx.CommunityModelRO.Comments.Query().
Where(comments.IDEQ(in.GetId()), comments.DeletedAtIsNil()).
First(l.ctx)
if err != nil {
return &pb.DelCommentsResp{}, nil
}
if comment.GetDeletedAt() == 0 {
now := nowUnix(0)
comment.DeletedAt = now
if post, ok := store.Posts[comment.GetPostId()]; ok && post.GetDeletedAt() == 0 && post.CommentCount > 0 {
post.CommentCount--
post.UpdatedAt = now
}
now := time.Now()
_, err = l.svcCtx.CommunityModelRW.Comments.Update().
Where(comments.IDEQ(in.GetId()), comments.DeletedAtIsNil()).
SetDeletedAt(now).
Save(l.ctx)
if err != nil {
logx.Errorf("delComments err: %v", err)
}
l.svcCtx.CommunityModelRW.Posts.Update().
Where(posts.IDEQ(comment.PostID), posts.DeletedAtIsNil(), posts.CommentCountGT(0)).
AddCommentCount(-1).
Exec(l.ctx)
return &pb.DelCommentsResp{}, nil
}
@@ -4,6 +4,8 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/postlikes"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,36 +31,33 @@ func (l *DelPostLikesLogic) DelPostLikes(in *pb.DelPostLikesReq) (*pb.DelPostLik
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
if in.UserId != nil && in.GetUserId() > 0 {
key := postLikeKey(in.GetId(), in.GetUserId())
if _, ok := store.PostLikes[key]; ok {
delete(store.PostLikes, key)
if post, ok := store.Posts[in.GetId()]; ok && post.LikeCount > 0 {
post.LikeCount--
}
n, err := l.svcCtx.CommunityModelRW.PostLikes.Delete().
Where(postlikes.PostIDEQ(in.GetId()), postlikes.UserIDEQ(in.GetUserId())).
Exec(l.ctx)
if err != nil {
logx.Errorf("delPostLikes err: %v", err)
}
if n > 0 {
l.svcCtx.CommunityModelRW.Posts.Update().
Where(posts.IDEQ(in.GetId()), posts.LikeCountGT(0)).
AddLikeCount(-1).
Exec(l.ctx)
}
return &pb.DelPostLikesResp{}, nil
}
removed := int64(0)
for key, like := range store.PostLikes {
if like.GetPostId() == in.GetId() {
delete(store.PostLikes, key)
removed++
}
n, err := l.svcCtx.CommunityModelRW.PostLikes.Delete().
Where(postlikes.PostIDEQ(in.GetId())).
Exec(l.ctx)
if err != nil {
logx.Errorf("delPostLikes err: %v", err)
}
if removed > 0 {
if post, ok := store.Posts[in.GetId()]; ok {
if post.LikeCount >= removed {
post.LikeCount -= removed
} else {
post.LikeCount = 0
}
}
if n > 0 {
l.svcCtx.CommunityModelRW.Posts.Update().
Where(posts.IDEQ(in.GetId()), posts.LikeCountGTE(n)).
AddLikeCount(-n).
Exec(l.ctx)
}
return &pb.DelPostLikesResp{}, nil
@@ -3,7 +3,9 @@ package logic
import (
"context"
"errors"
"time"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,17 +31,15 @@ func (l *DelPostsLogic) DelPosts(in *pb.DelPostsReq) (*pb.DelPostsResp, error) {
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
post, ok := store.Posts[in.GetId()]
if !ok {
return &pb.DelPostsResp{}, nil
now := time.Now()
_, err := l.svcCtx.CommunityModelRW.Posts.Update().
Where(posts.IDEQ(in.GetId()), posts.DeletedAtIsNil()).
SetDeletedAt(now).
SetUpdatedAt(now).
Save(l.ctx)
if err != nil {
logx.Errorf("delPosts err: %v", err)
}
now := nowUnix(0)
post.DeletedAt = now
post.UpdatedAt = now
return &pb.DelPostsResp{}, nil
}
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/commentlikes"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,16 +30,12 @@ func (l *GetCommentLikesByIdLogic) GetCommentLikesById(in *pb.GetCommentLikesByI
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
for _, like := range store.CommentLikes {
if like.GetCommentId() == in.GetId() {
cp := *like
return &pb.GetCommentLikesByIdResp{CommentLikes: &cp}, nil
}
like, err := l.svcCtx.CommunityModelRO.CommentLikes.Query().
Where(commentlikes.CommentIDEQ(in.GetId())).
First(l.ctx)
if err != nil {
return nil, errors.New("comment like not found")
}
return nil, errors.New("comment like not found")
return &pb.GetCommentLikesByIdResp{CommentLikes: entCommentLikeToPb(like)}, nil
}
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/comments"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,15 +30,12 @@ func (l *GetCommentsByIdLogic) GetCommentsById(in *pb.GetCommentsByIdReq) (*pb.G
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
comment, ok := store.Comments[in.GetId()]
if !ok || comment.GetDeletedAt() > 0 {
comment, err := l.svcCtx.CommunityModelRO.Comments.Query().
Where(comments.IDEQ(in.GetId()), comments.DeletedAtIsNil()).
First(l.ctx)
if err != nil {
return nil, errors.New("comment not found")
}
out := *comment
return &pb.GetCommentsByIdResp{Comments: &out}, nil
return &pb.GetCommentsByIdResp{Comments: entCommentToPb(comment)}, nil
}
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/postlikes"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,16 +30,12 @@ func (l *GetPostLikesByIdLogic) GetPostLikesById(in *pb.GetPostLikesByIdReq) (*p
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
for _, like := range store.PostLikes {
if like.GetPostId() == in.GetId() {
cp := *like
return &pb.GetPostLikesByIdResp{PostLikes: &cp}, nil
}
like, err := l.svcCtx.CommunityModelRO.PostLikes.Query().
Where(postlikes.PostIDEQ(in.GetId())).
First(l.ctx)
if err != nil {
return nil, errors.New("post like not found")
}
return nil, errors.New("post like not found")
return &pb.GetPostLikesByIdResp{PostLikes: entPostLikeToPb(like)}, nil
}
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,18 +30,12 @@ func (l *GetPostsByIdLogic) GetPostsById(in *pb.GetPostsByIdReq) (*pb.GetPostsBy
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
post, ok := store.Posts[in.GetId()]
if !ok || post.GetDeletedAt() > 0 {
post, err := l.svcCtx.CommunityModelRO.Posts.Query().
Where(posts.IDEQ(in.GetId()), posts.DeletedAtIsNil()).
First(l.ctx)
if err != nil {
return nil, errors.New("post not found")
}
out := *post
out.Images = append([]string(nil), post.Images...)
out.Tags = append([]string(nil), post.Tags...)
return &pb.GetPostsByIdResp{Posts: &out}, nil
return &pb.GetPostsByIdResp{Posts: entPostToPb(post)}, nil
}
+62 -29
View File
@@ -1,45 +1,78 @@
package logic
import (
"sort"
"strconv"
"time"
"juwan-backend/app/community/rpc/internal/models"
"juwan-backend/app/community/rpc/pb"
"juwan-backend/pkg/types"
"github.com/jackc/pgx/v5/pgtype"
)
func nowUnix(in int64) int64 {
if in > 0 {
return in
func toTextArray(s []string) types.TextArray {
if len(s) == 0 {
return types.TextArray{Valid: true}
}
return types.TextArray{
Elements: s,
Dims: []pgtype.ArrayDimension{{Length: int32(len(s)), LowerBound: 1}},
Valid: true,
}
return time.Now().Unix()
}
func postLikeKey(postID, userID int64) string {
return strconv.FormatInt(postID, 10) + ":" + strconv.FormatInt(userID, 10)
func entPostToPb(p *models.Posts) *pb.Posts {
out := &pb.Posts{
Id: p.ID,
AuthorId: p.AuthorID,
AuthorRole: p.AuthorRole,
Title: p.Title,
Content: p.Content,
Images: p.Images.Elements,
Tags: p.Tags.Elements,
LikeCount: int64(p.LikeCount),
CommentCount: int64(p.CommentCount),
Pinned: p.Pinned,
CreatedAt: p.CreatedAt.Unix(),
UpdatedAt: p.UpdatedAt.Unix(),
}
if p.LinkedOrderID != nil {
out.LinkedOrderId = *p.LinkedOrderID
}
if p.QuotedPostID != nil {
out.QuotedPostId = *p.QuotedPostID
}
if p.DeletedAt != nil {
out.DeletedAt = p.DeletedAt.Unix()
}
return out
}
func commentLikeKey(commentID, userID int64) string {
return strconv.FormatInt(commentID, 10) + ":" + strconv.FormatInt(userID, 10)
func entCommentToPb(c *models.Comments) *pb.Comments {
out := &pb.Comments{
Id: c.ID,
PostId: c.PostID,
AuthorId: c.AuthorID,
Content: c.Content,
LikeCount: int64(c.LikeCount),
CreatedAt: c.CreatedAt.Unix(),
}
if c.DeletedAt != nil {
out.DeletedAt = c.DeletedAt.Unix()
}
return out
}
func sortPostsDesc(posts []*pb.Posts) {
sort.Slice(posts, func(i, j int) bool {
if posts[i].Pinned != posts[j].Pinned {
return posts[i].Pinned
}
if posts[i].CreatedAt == posts[j].CreatedAt {
return posts[i].Id > posts[j].Id
}
return posts[i].CreatedAt > posts[j].CreatedAt
})
func entPostLikeToPb(l *models.PostLikes) *pb.PostLikes {
return &pb.PostLikes{
PostId: l.PostID,
UserId: l.UserID,
CreatedAt: l.CreatedAt.Unix(),
}
}
func sortCommentsAsc(comments []*pb.Comments) {
sort.Slice(comments, func(i, j int) bool {
if comments[i].CreatedAt == comments[j].CreatedAt {
return comments[i].Id < comments[j].Id
}
return comments[i].CreatedAt < comments[j].CreatedAt
})
func entCommentLikeToPb(l *models.CommentLikes) *pb.CommentLikes {
return &pb.CommentLikes{
CommentId: l.CommentID,
UserId: l.UserID,
CreatedAt: l.CreatedAt.Unix(),
}
}
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/commentlikes"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -37,29 +38,27 @@ func (l *SearchCommentLikesLogic) SearchCommentLikes(in *pb.SearchCommentLikesRe
offset = 0
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
filtered := make([]*pb.CommentLikes, 0, len(store.CommentLikes))
for _, like := range store.CommentLikes {
if in.GetCommentId() > 0 && like.GetCommentId() != in.GetCommentId() {
continue
}
if in.GetUserId() > 0 && like.GetUserId() != in.GetUserId() {
continue
}
cp := *like
filtered = append(filtered, &cp)
query := l.svcCtx.CommunityModelRO.CommentLikes.Query()
if in.GetCommentId() > 0 {
query = query.Where(commentlikes.CommentIDEQ(in.GetCommentId()))
}
if in.GetUserId() > 0 {
query = query.Where(commentlikes.UserIDEQ(in.GetUserId()))
}
if offset >= int64(len(filtered)) {
return &pb.SearchCommentLikesResp{CommentLikes: []*pb.CommentLikes{}}, nil
}
end := offset + limit
if end > int64(len(filtered)) {
end = int64(len(filtered))
list, err := query.
Offset(int(offset)).
Limit(int(limit)).
All(l.ctx)
if err != nil {
logx.Errorf("searchCommentLikes err: %v", err)
return nil, errors.New("search comment likes failed")
}
return &pb.SearchCommentLikesResp{CommentLikes: filtered[offset:end]}, nil
out := make([]*pb.CommentLikes, len(list))
for i, like := range list {
out[i] = entCommentLikeToPb(like)
}
return &pb.SearchCommentLikesResp{CommentLikes: out}, nil
}
@@ -3,11 +3,12 @@ package logic
import (
"context"
"errors"
"strings"
"juwan-backend/app/community/rpc/internal/models/comments"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
"entgo.io/ent/dialect/sql"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -38,43 +39,36 @@ func (l *SearchCommentsLogic) SearchComments(in *pb.SearchCommentsReq) (*pb.Sear
offset = 0
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
query := l.svcCtx.CommunityModelRO.Comments.Query().
Where(comments.DeletedAtIsNil())
filtered := make([]*pb.Comments, 0, len(store.Comments))
for _, c := range store.Comments {
if c.GetDeletedAt() > 0 {
continue
}
if in.GetId() > 0 && c.GetId() != in.GetId() {
continue
}
if in.GetPostId() > 0 && c.GetPostId() != in.GetPostId() {
continue
}
if in.GetAuthorId() > 0 && c.GetAuthorId() != in.GetAuthorId() {
continue
}
if in.Content != nil && !strings.Contains(strings.ToLower(c.GetContent()), strings.ToLower(in.GetContent())) {
continue
}
if in.LikeCount != nil && c.GetLikeCount() != in.GetLikeCount() {
continue
}
cc := *c
filtered = append(filtered, &cc)
if in.GetId() > 0 {
query = query.Where(comments.IDEQ(in.GetId()))
}
if in.GetPostId() > 0 {
query = query.Where(comments.PostIDEQ(in.GetPostId()))
}
if in.GetAuthorId() > 0 {
query = query.Where(comments.AuthorIDEQ(in.GetAuthorId()))
}
if in.Content != nil {
query = query.Where(comments.ContentContainsFold(in.GetContent()))
}
sortCommentsAsc(filtered)
if offset >= int64(len(filtered)) {
return &pb.SearchCommentsResp{Comments: []*pb.Comments{}}, nil
}
end := offset + limit
if end > int64(len(filtered)) {
end = int64(len(filtered))
list, err := query.
Order(comments.ByCreatedAt(sql.OrderAsc()), comments.ByID(sql.OrderAsc())).
Offset(int(offset)).
Limit(int(limit)).
All(l.ctx)
if err != nil {
logx.Errorf("searchComments err: %v", err)
return nil, errors.New("search comments failed")
}
return &pb.SearchCommentsResp{Comments: filtered[offset:end]}, nil
out := make([]*pb.Comments, len(list))
for i, c := range list {
out[i] = entCommentToPb(c)
}
return &pb.SearchCommentsResp{Comments: out}, nil
}
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/postlikes"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -37,29 +38,27 @@ func (l *SearchPostLikesLogic) SearchPostLikes(in *pb.SearchPostLikesReq) (*pb.S
offset = 0
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
filtered := make([]*pb.PostLikes, 0, len(store.PostLikes))
for _, like := range store.PostLikes {
if in.PostId != nil && like.GetPostId() != in.GetPostId() {
continue
}
if in.UserId != nil && like.GetUserId() != in.GetUserId() {
continue
}
cp := *like
filtered = append(filtered, &cp)
query := l.svcCtx.CommunityModelRO.PostLikes.Query()
if in.PostId != nil {
query = query.Where(postlikes.PostIDEQ(in.GetPostId()))
}
if in.UserId != nil {
query = query.Where(postlikes.UserIDEQ(in.GetUserId()))
}
if offset >= int64(len(filtered)) {
return &pb.SearchPostLikesResp{PostLikes: []*pb.PostLikes{}}, nil
}
end := offset + limit
if end > int64(len(filtered)) {
end = int64(len(filtered))
list, err := query.
Offset(int(offset)).
Limit(int(limit)).
All(l.ctx)
if err != nil {
logx.Errorf("searchPostLikes err: %v", err)
return nil, errors.New("search post likes failed")
}
return &pb.SearchPostLikesResp{PostLikes: filtered[offset:end]}, nil
out := make([]*pb.PostLikes, len(list))
for i, like := range list {
out[i] = entPostLikeToPb(like)
}
return &pb.SearchPostLikesResp{PostLikes: out}, nil
}
@@ -3,11 +3,12 @@ package logic
import (
"context"
"errors"
"strings"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
"entgo.io/ent/dialect/sql"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -38,63 +39,39 @@ func (l *SearchPostsLogic) SearchPosts(in *pb.SearchPostsReq) (*pb.SearchPostsRe
offset = 0
}
store := l.svcCtx.Store
store.Mu.RLock()
defer store.Mu.RUnlock()
query := l.svcCtx.CommunityModelRO.Posts.Query().
Where(posts.DeletedAtIsNil())
filtered := make([]*pb.Posts, 0, len(store.Posts))
for _, p := range store.Posts {
if p.GetDeletedAt() > 0 {
continue
}
if in.GetId() > 0 && p.GetId() != in.GetId() {
continue
}
if in.AuthorId != nil && p.GetAuthorId() != in.GetAuthorId() {
continue
}
if in.AuthorRole != nil && p.GetAuthorRole() != in.GetAuthorRole() {
continue
}
if in.Title != nil && !strings.Contains(strings.ToLower(p.GetTitle()), strings.ToLower(in.GetTitle())) {
continue
}
if in.Content != nil && !strings.Contains(strings.ToLower(p.GetContent()), strings.ToLower(in.GetContent())) {
continue
}
if len(in.GetTags()) > 0 {
match := false
for _, t := range in.GetTags() {
for _, pt := range p.GetTags() {
if t == pt {
match = true
break
}
}
if match {
break
}
}
if !match {
continue
}
}
cp := *p
cp.Images = append([]string(nil), p.Images...)
cp.Tags = append([]string(nil), p.Tags...)
filtered = append(filtered, &cp)
if in.GetId() > 0 {
query = query.Where(posts.IDEQ(in.GetId()))
}
if in.AuthorId != nil {
query = query.Where(posts.AuthorIDEQ(in.GetAuthorId()))
}
if in.AuthorRole != nil {
query = query.Where(posts.AuthorRole(in.GetAuthorRole()))
}
if in.Title != nil {
query = query.Where(posts.TitleContainsFold(in.GetTitle()))
}
if in.Content != nil {
query = query.Where(posts.ContentContainsFold(in.GetContent()))
}
sortPostsDesc(filtered)
if offset >= int64(len(filtered)) {
return &pb.SearchPostsResp{Posts: []*pb.Posts{}}, nil
}
end := offset + limit
if end > int64(len(filtered)) {
end = int64(len(filtered))
list, err := query.
Order(posts.ByPinned(sql.OrderDesc()), posts.ByCreatedAt(sql.OrderDesc()), posts.ByID(sql.OrderDesc())).
Offset(int(offset)).
Limit(int(limit)).
All(l.ctx)
if err != nil {
logx.Errorf("searchPosts err: %v", err)
return nil, errors.New("search posts failed")
}
return &pb.SearchPostsResp{Posts: filtered[offset:end]}, nil
out := make([]*pb.Posts, len(list))
for i, p := range list {
out[i] = entPostToPb(p)
}
return &pb.SearchPostsResp{Posts: out}, nil
}
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/commentlikes"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,18 +30,19 @@ func (l *UpdateCommentLikesLogic) UpdateCommentLikes(in *pb.UpdateCommentLikesRe
return nil, errors.New("commentId and userId are required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
if _, ok := store.Comments[in.GetCommentId()]; !ok {
return nil, errors.New("comment not found")
_, err := l.svcCtx.CommunityModelRO.CommentLikes.Query().
Where(commentlikes.CommentIDEQ(in.GetCommentId()), commentlikes.UserIDEQ(in.GetUserId())).
First(l.ctx)
if err != nil {
return nil, errors.New("comment like not found")
}
key := commentLikeKey(in.GetCommentId(), in.GetUserId())
store.CommentLikes[key] = &pb.CommentLikes{
CommentId: in.GetCommentId(),
UserId: in.GetUserId(),
CreatedAt: nowUnix(in.GetCreatedAt()),
_, err = l.svcCtx.CommunityModelRW.CommentLikes.Update().
Where(commentlikes.CommentIDEQ(in.GetCommentId()), commentlikes.UserIDEQ(in.GetUserId())).
Save(l.ctx)
if err != nil {
logx.Errorf("updateCommentLikes err: %v", err)
return nil, errors.New("update comment like failed")
}
return &pb.UpdateCommentLikesResp{}, nil
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/comments"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,32 +30,23 @@ func (l *UpdateCommentsLogic) UpdateComments(in *pb.UpdateCommentsReq) (*pb.Upda
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
updater := l.svcCtx.CommunityModelRW.Comments.Update().
Where(comments.IDEQ(in.GetId()), comments.DeletedAtIsNil())
comment, ok := store.Comments[in.GetId()]
if !ok || comment.GetDeletedAt() > 0 {
return nil, errors.New("comment not found")
}
if in.GetPostId() > 0 {
comment.PostId = in.GetPostId()
}
if in.GetAuthorId() > 0 {
comment.AuthorId = in.GetAuthorId()
}
if in.GetContent() != "" {
comment.Content = in.GetContent()
updater = updater.SetContent(in.GetContent())
}
if in.GetLikeCount() > 0 {
comment.LikeCount = in.GetLikeCount()
updater = updater.SetLikeCount(int(in.GetLikeCount()))
}
if in.GetDeletedAt() > 0 {
comment.DeletedAt = in.GetDeletedAt()
n, err := updater.Save(l.ctx)
if err != nil {
logx.Errorf("updateComments err: %v", err)
return nil, errors.New("update comment failed")
}
if in.GetCreatedAt() > 0 {
comment.CreatedAt = in.GetCreatedAt()
if n == 0 {
return nil, errors.New("comment not found")
}
return &pb.UpdateCommentsResp{}, nil
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/postlikes"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -28,21 +29,20 @@ func (l *UpdatePostLikesLogic) UpdatePostLikes(in *pb.UpdatePostLikesReq) (*pb.U
if in.PostId == nil || in.UserId == nil {
return nil, errors.New("postId and userId are required")
}
postID := in.GetPostId()
userID := in.GetUserId()
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
if _, ok := store.Posts[postID]; !ok {
return nil, errors.New("post not found")
_, err := l.svcCtx.CommunityModelRO.PostLikes.Query().
Where(postlikes.PostIDEQ(in.GetPostId()), postlikes.UserIDEQ(in.GetUserId())).
First(l.ctx)
if err != nil {
return nil, errors.New("post like not found")
}
key := postLikeKey(postID, userID)
store.PostLikes[key] = &pb.PostLikes{
PostId: postID,
UserId: userID,
CreatedAt: nowUnix(in.GetCreatedAt()),
_, err = l.svcCtx.CommunityModelRW.PostLikes.Update().
Where(postlikes.PostIDEQ(in.GetPostId()), postlikes.UserIDEQ(in.GetUserId())).
Save(l.ctx)
if err != nil {
logx.Errorf("updatePostLikes err: %v", err)
return nil, errors.New("update post like failed")
}
return &pb.UpdatePostLikesResp{}, nil
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"juwan-backend/app/community/rpc/internal/models/posts"
"juwan-backend/app/community/rpc/internal/svc"
"juwan-backend/app/community/rpc/pb"
@@ -29,58 +30,51 @@ func (l *UpdatePostsLogic) UpdatePosts(in *pb.UpdatePostsReq) (*pb.UpdatePostsRe
return nil, errors.New("id is required")
}
store := l.svcCtx.Store
store.Mu.Lock()
defer store.Mu.Unlock()
updater := l.svcCtx.CommunityModelRW.Posts.Update().
Where(posts.IDEQ(in.GetId()), posts.DeletedAtIsNil())
post, ok := store.Posts[in.GetId()]
if !ok || post.GetDeletedAt() > 0 {
if in.AuthorId != nil {
updater = updater.SetAuthorID(in.GetAuthorId())
}
if in.AuthorRole != nil {
updater = updater.SetAuthorRole(in.GetAuthorRole())
}
if in.Title != nil {
updater = updater.SetTitle(in.GetTitle())
}
if in.Content != nil {
updater = updater.SetContent(in.GetContent())
}
if len(in.Images) > 0 {
updater = updater.SetImages(toTextArray(in.GetImages()))
}
if len(in.Tags) > 0 {
updater = updater.SetTags(toTextArray(in.GetTags()))
}
if in.LinkedOrderId != nil {
updater = updater.SetLinkedOrderID(in.GetLinkedOrderId())
}
if in.QuotedPostId != nil {
updater = updater.SetQuotedPostID(in.GetQuotedPostId())
}
if in.LikeCount != nil {
updater = updater.SetLikeCount(int(in.GetLikeCount()))
}
if in.CommentCount != nil {
updater = updater.SetCommentCount(int(in.GetCommentCount()))
}
if in.Pinned != nil {
updater = updater.SetPinned(in.GetPinned())
}
n, err := updater.Save(l.ctx)
if err != nil {
logx.Errorf("updatePosts err: %v", err)
return nil, errors.New("update post failed")
}
if n == 0 {
return nil, errors.New("post not found")
}
if in.AuthorId != nil {
post.AuthorId = in.GetAuthorId()
}
if in.AuthorRole != nil {
post.AuthorRole = in.GetAuthorRole()
}
if in.Title != nil {
post.Title = in.GetTitle()
}
if in.Content != nil {
post.Content = in.GetContent()
}
if len(in.Images) > 0 {
post.Images = append([]string(nil), in.GetImages()...)
}
if len(in.Tags) > 0 {
post.Tags = append([]string(nil), in.GetTags()...)
}
if in.LinkedOrderId != nil {
post.LinkedOrderId = in.GetLinkedOrderId()
}
if in.QuotedPostId != nil {
post.QuotedPostId = in.GetQuotedPostId()
}
if in.LikeCount != nil {
post.LikeCount = in.GetLikeCount()
}
if in.CommentCount != nil {
post.CommentCount = in.GetCommentCount()
}
if in.Pinned != nil {
post.Pinned = in.GetPinned()
}
if in.SearchText != nil {
post.SearchText = in.GetSearchText()
}
if in.DeletedAt != nil {
post.DeletedAt = in.GetDeletedAt()
}
if in.CreatedAt != nil {
post.CreatedAt = in.GetCreatedAt()
}
post.UpdatedAt = nowUnix(in.GetUpdatedAt())
return &pb.UpdatePostsResp{}, nil
}