refactor(server): decouple services and improve architecture
- Introduce interfaces for all major services (JWT, PostAI, Comment, Message, Notification, QRCodeLogin, Upload, Vote, etc.) to support dependency inversion. - Move query parameters from `internal/dto` to a new `internal/query` package to separate request payloads from data transfer objects. - Refactor `internal/router` to use embedded `RouterDeps` for cleaner dependency management. - Decouple handlers from repositories by injecting services instead of direct repository access, ensuring proper layering. - Improve database initialization by moving it from `internal/model` to `internal/database`. - Optimize message decryption by implementing a more efficient `BatchDecrypt` method in `MessageEncryptor` using a worker pool. - Enhance error handling and security by implementing fail-fast checks for encryption key length during startup. - Clean up unused code, including the `avatar` package and several unused DTOs.
This commit is contained in:
@@ -6,9 +6,9 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
apperrors "with_you/internal/errors"
|
||||
"with_you/internal/cache"
|
||||
"with_you/internal/dto"
|
||||
apperrors "with_you/internal/errors"
|
||||
"with_you/internal/model"
|
||||
"with_you/internal/pkg/cursor"
|
||||
"with_you/internal/pkg/hook"
|
||||
@@ -17,18 +17,34 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type CommentService struct {
|
||||
// CommentService 评论服务接口
|
||||
type CommentService interface {
|
||||
Create(ctx context.Context, postID, userID, content string, segments model.MessageSegments, parentID *string, images string, imageURLs []string) (*model.Comment, error)
|
||||
GetByID(ctx context.Context, id string) (*model.Comment, error)
|
||||
GetByPostID(ctx context.Context, postID string, page, pageSize int) ([]*model.Comment, int64, error)
|
||||
GetRepliesByRootID(ctx context.Context, rootID string, page, pageSize int) ([]*model.Comment, int64, error)
|
||||
GetReplies(ctx context.Context, parentID string) ([]*model.Comment, error)
|
||||
Update(ctx context.Context, userID string, comment *model.Comment) error
|
||||
Delete(ctx context.Context, userID string, id string) error
|
||||
Like(ctx context.Context, commentID, userID string) error
|
||||
Unlike(ctx context.Context, commentID, userID string) error
|
||||
IsLiked(ctx context.Context, commentID, userID string) bool
|
||||
GetCommentsByCursor(ctx context.Context, postID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error)
|
||||
GetRepliesByCursor(ctx context.Context, rootID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error)
|
||||
}
|
||||
|
||||
type commentService struct {
|
||||
commentRepo repository.CommentRepository
|
||||
postRepo repository.PostRepository
|
||||
systemMessageService SystemMessageService
|
||||
cache cache.Cache
|
||||
postAIService *PostAIService
|
||||
postAIService PostAIService
|
||||
logService *LogService
|
||||
hookManager *hook.Manager
|
||||
}
|
||||
|
||||
func NewCommentService(commentRepo repository.CommentRepository, postRepo repository.PostRepository, systemMessageService SystemMessageService, postAIService *PostAIService, cacheBackend cache.Cache, hookManager *hook.Manager, logService *LogService) *CommentService {
|
||||
return &CommentService{
|
||||
func NewCommentService(commentRepo repository.CommentRepository, postRepo repository.PostRepository, systemMessageService SystemMessageService, postAIService PostAIService, cacheBackend cache.Cache, hookManager *hook.Manager, logService *LogService) CommentService {
|
||||
return &commentService{
|
||||
commentRepo: commentRepo,
|
||||
postRepo: postRepo,
|
||||
systemMessageService: systemMessageService,
|
||||
@@ -40,7 +56,7 @@ func NewCommentService(commentRepo repository.CommentRepository, postRepo reposi
|
||||
}
|
||||
|
||||
// Create 创建评论
|
||||
func (s *CommentService) Create(ctx context.Context, postID, userID, content string, segments model.MessageSegments, parentID *string, images string, imageURLs []string) (*model.Comment, error) {
|
||||
func (s *commentService) Create(ctx context.Context, postID, userID, content string, segments model.MessageSegments, parentID *string, images string, imageURLs []string) (*model.Comment, error) {
|
||||
if s.postAIService != nil {
|
||||
// 采用异步审核,前端先立即返回
|
||||
}
|
||||
@@ -110,7 +126,7 @@ func (s *CommentService) Create(ctx context.Context, postID, userID, content str
|
||||
}
|
||||
|
||||
// processCommentMentionNotifications 处理评论中 @提及的通知
|
||||
func (s *CommentService) processCommentMentionNotifications(ctx context.Context, authorID, postID, postTitle string, segments model.MessageSegments) {
|
||||
func (s *commentService) processCommentMentionNotifications(ctx context.Context, authorID, postID, postTitle string, segments model.MessageSegments) {
|
||||
if s.systemMessageService == nil {
|
||||
return
|
||||
}
|
||||
@@ -130,7 +146,7 @@ func (s *CommentService) processCommentMentionNotifications(ctx context.Context,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CommentService) reviewCommentAsync(
|
||||
func (s *commentService) reviewCommentAsync(
|
||||
commentID, userID, postID, content string,
|
||||
imageURLs []string,
|
||||
parentID *string,
|
||||
@@ -211,7 +227,7 @@ func (s *CommentService) reviewCommentAsync(
|
||||
s.afterCommentPublished(userID, postID, commentID, parentID, parentUserID, postOwnerID)
|
||||
}
|
||||
|
||||
func (s *CommentService) applyCommentPublishedStats(commentID string) error {
|
||||
func (s *commentService) applyCommentPublishedStats(commentID string) error {
|
||||
comment, err := s.commentRepo.GetByID(commentID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -219,12 +235,12 @@ func (s *CommentService) applyCommentPublishedStats(commentID string) error {
|
||||
return s.commentRepo.ApplyPublishedStats(comment)
|
||||
}
|
||||
|
||||
func (s *CommentService) invalidatePostCaches(postID string) {
|
||||
func (s *commentService) invalidatePostCaches(postID string) {
|
||||
cache.InvalidatePostDetail(s.cache, postID)
|
||||
cache.InvalidatePostList(s.cache)
|
||||
}
|
||||
|
||||
func (s *CommentService) afterCommentPublished(userID, postID, commentID string, parentID *string, parentUserID, postOwnerID string) {
|
||||
func (s *commentService) afterCommentPublished(userID, postID, commentID string, parentID *string, parentUserID, postOwnerID string) {
|
||||
// 发送系统消息通知
|
||||
if s.systemMessageService != nil {
|
||||
go func() {
|
||||
@@ -254,7 +270,7 @@ func (s *CommentService) afterCommentPublished(userID, postID, commentID string,
|
||||
|
||||
}
|
||||
|
||||
func (s *CommentService) notifyCommentModerationRejected(userID, reason string) {
|
||||
func (s *commentService) notifyCommentModerationRejected(userID, reason string) {
|
||||
if s.systemMessageService == nil || strings.TrimSpace(userID) == "" {
|
||||
return
|
||||
}
|
||||
@@ -279,28 +295,28 @@ func (s *CommentService) notifyCommentModerationRejected(userID, reason string)
|
||||
}
|
||||
|
||||
// GetByID 根据ID获取评论
|
||||
func (s *CommentService) GetByID(ctx context.Context, id string) (*model.Comment, error) {
|
||||
func (s *commentService) GetByID(ctx context.Context, id string) (*model.Comment, error) {
|
||||
return s.commentRepo.GetByID(id)
|
||||
}
|
||||
|
||||
// GetByPostID 获取帖子评论
|
||||
func (s *CommentService) GetByPostID(ctx context.Context, postID string, page, pageSize int) ([]*model.Comment, int64, error) {
|
||||
func (s *commentService) GetByPostID(ctx context.Context, postID string, page, pageSize int) ([]*model.Comment, int64, error) {
|
||||
// 使用带回复的查询,默认加载前3条回复
|
||||
return s.commentRepo.GetByPostIDWithReplies(postID, page, pageSize, 3)
|
||||
}
|
||||
|
||||
// GetRepliesByRootID 根据根评论ID分页获取回复
|
||||
func (s *CommentService) GetRepliesByRootID(ctx context.Context, rootID string, page, pageSize int) ([]*model.Comment, int64, error) {
|
||||
func (s *commentService) GetRepliesByRootID(ctx context.Context, rootID string, page, pageSize int) ([]*model.Comment, int64, error) {
|
||||
return s.commentRepo.GetRepliesByRootID(rootID, page, pageSize)
|
||||
}
|
||||
|
||||
// GetReplies 获取回复
|
||||
func (s *CommentService) GetReplies(ctx context.Context, parentID string) ([]*model.Comment, error) {
|
||||
func (s *commentService) GetReplies(ctx context.Context, parentID string) ([]*model.Comment, error) {
|
||||
return s.commentRepo.GetReplies(parentID)
|
||||
}
|
||||
|
||||
// Update 更新评论
|
||||
func (s *CommentService) Update(ctx context.Context, userID string, comment *model.Comment) error {
|
||||
func (s *commentService) Update(ctx context.Context, userID string, comment *model.Comment) error {
|
||||
if comment.UserID != userID {
|
||||
return apperrors.ErrForbidden
|
||||
}
|
||||
@@ -308,7 +324,7 @@ func (s *CommentService) Update(ctx context.Context, userID string, comment *mod
|
||||
}
|
||||
|
||||
// Delete 删除评论
|
||||
func (s *CommentService) Delete(ctx context.Context, userID string, id string) error {
|
||||
func (s *commentService) Delete(ctx context.Context, userID string, id string) error {
|
||||
comment, err := s.commentRepo.GetByID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -324,7 +340,7 @@ func (s *CommentService) Delete(ctx context.Context, userID string, id string) e
|
||||
}
|
||||
|
||||
// Like 点赞评论
|
||||
func (s *CommentService) Like(ctx context.Context, commentID, userID string) error {
|
||||
func (s *commentService) Like(ctx context.Context, commentID, userID string) error {
|
||||
// 获取评论信息用于发送通知
|
||||
comment, err := s.commentRepo.GetByID(commentID)
|
||||
if err != nil {
|
||||
@@ -371,21 +387,21 @@ func (s *CommentService) Like(ctx context.Context, commentID, userID string) err
|
||||
}
|
||||
|
||||
// Unlike 取消点赞评论
|
||||
func (s *CommentService) Unlike(ctx context.Context, commentID, userID string) error {
|
||||
func (s *commentService) Unlike(ctx context.Context, commentID, userID string) error {
|
||||
return s.commentRepo.Unlike(commentID, userID)
|
||||
}
|
||||
|
||||
// IsLiked 检查是否已点赞
|
||||
func (s *CommentService) IsLiked(ctx context.Context, commentID, userID string) bool {
|
||||
func (s *commentService) IsLiked(ctx context.Context, commentID, userID string) bool {
|
||||
return s.commentRepo.IsLiked(commentID, userID)
|
||||
}
|
||||
|
||||
// GetCommentsByCursor 游标分页获取帖子评论
|
||||
func (s *CommentService) GetCommentsByCursor(ctx context.Context, postID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error) {
|
||||
func (s *commentService) GetCommentsByCursor(ctx context.Context, postID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error) {
|
||||
return s.commentRepo.GetCommentsByCursor(ctx, postID, req)
|
||||
}
|
||||
|
||||
// GetRepliesByCursor 游标分页获取根评论的回复
|
||||
func (s *CommentService) GetRepliesByCursor(ctx context.Context, rootID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error) {
|
||||
func (s *commentService) GetRepliesByCursor(ctx context.Context, rootID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error) {
|
||||
return s.commentRepo.GetRepliesByCursor(ctx, rootID, req)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user