refactor(notification): migrate cursor pagination to use unified cursor package
- Add new GetByReceiverIDCursor method with context support and generic cursor types - Rename old implementation to GetByReceiverIDCursorLegacy for backward compatibility - Update handler to use legacy interface temporarily during migration - Use CursorBuilder pattern for consistent pagination across services
This commit is contained in:
@@ -82,8 +82,8 @@ func (h *SystemMessageHandler) GetSystemMessagesByCursor(c *gin.Context) {
|
|||||||
cursorStr := c.Query("cursor")
|
cursorStr := c.Query("cursor")
|
||||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||||
|
|
||||||
// 获取当前用户的系统通知
|
// 获取当前用户的系统通知(使用兼容旧版接口)
|
||||||
notifications, nextCursor, hasMore, err := h.notifyRepo.GetByReceiverIDCursor(userID, cursorStr, pageSize)
|
notifications, nextCursor, hasMore, err := h.notifyRepo.GetByReceiverIDCursorLegacy(userID, cursorStr, pageSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.InternalServerError(c, "failed to get system messages")
|
response.InternalServerError(c, "failed to get system messages")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"carrot_bbs/internal/model"
|
"carrot_bbs/internal/model"
|
||||||
|
"carrot_bbs/internal/pkg/cursor"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -114,13 +118,67 @@ func (r *SystemNotificationRepository) GetByType(receiverID string, notifyType m
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetByReceiverIDCursor 游标分页获取用户的通知列表
|
// GetByReceiverIDCursor 游标分页获取用户的通知列表
|
||||||
func (r *SystemNotificationRepository) GetByReceiverIDCursor(receiverID string, cursor string, pageSize int) ([]*model.SystemNotification, string, bool, error) {
|
// 使用统一的 cursor 包进行游标分页
|
||||||
|
func (r *SystemNotificationRepository) GetByReceiverIDCursor(ctx context.Context, receiverID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.SystemNotification], error) {
|
||||||
|
// 构建基础查询
|
||||||
|
query := r.db.WithContext(ctx).Model(&model.SystemNotification{}).Where("receiver_id = ?", receiverID)
|
||||||
|
|
||||||
|
// 使用 CursorBuilder 构建游标查询
|
||||||
|
builder := cursor.NewBuilder(query, cursor.SortByCreatedAtDesc).
|
||||||
|
WithCursor(req.Cursor, cursor.Direction(req.Direction)).
|
||||||
|
WithPageSize(req.PageSize)
|
||||||
|
|
||||||
|
if builder.Error() != nil {
|
||||||
|
return nil, builder.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
|
var notifications []*model.SystemNotification
|
||||||
|
if err := builder.Build().Find(¬ifications).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建响应
|
||||||
|
pageSize := builder.GetPageSize()
|
||||||
|
hasMore := cursor.HasMore(len(notifications), pageSize)
|
||||||
|
if hasMore {
|
||||||
|
notifications = notifications[:pageSize]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成下一页游标
|
||||||
|
var nextCursor string
|
||||||
|
if hasMore && len(notifications) > 0 {
|
||||||
|
lastNotification := notifications[len(notifications)-1]
|
||||||
|
nextCursor = cursor.NewCursor(
|
||||||
|
cursor.FormatTime(lastNotification.CreatedAt),
|
||||||
|
strconv.FormatInt(lastNotification.ID, 10),
|
||||||
|
cursor.SortByCreatedAtDesc,
|
||||||
|
).Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
return &cursor.CursorPageResult[*model.SystemNotification]{
|
||||||
|
Items: notifications,
|
||||||
|
NextCursor: nextCursor,
|
||||||
|
HasMore: hasMore,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByReceiverIDCursorLegacy 游标分页获取用户的通知列表(旧版兼容接口)
|
||||||
|
// 已废弃:请使用 GetByReceiverIDCursor
|
||||||
|
func (r *SystemNotificationRepository) GetByReceiverIDCursorLegacy(receiverID string, cursorStr string, pageSize int) ([]*model.SystemNotification, string, bool, error) {
|
||||||
|
// 构建基础查询
|
||||||
query := r.db.Model(&model.SystemNotification{}).Where("receiver_id = ?", receiverID)
|
query := r.db.Model(&model.SystemNotification{}).Where("receiver_id = ?", receiverID)
|
||||||
|
|
||||||
// 如果有游标,解析游标并添加条件
|
// 如果有游标,解析游标并添加条件
|
||||||
if cursor != "" {
|
if cursorStr != "" {
|
||||||
// 游标格式:createdAt_id
|
decodedCursor, err := cursor.DecodeCursor(cursorStr)
|
||||||
query = query.Where("created_at < ? OR (created_at = ? AND id < ?)", cursor, cursor, cursor)
|
if err != nil {
|
||||||
|
// 游标格式无效,返回空结果
|
||||||
|
return []*model.SystemNotification{}, "", false, nil
|
||||||
|
}
|
||||||
|
// 使用元组比较进行分页
|
||||||
|
condition := "(created_at, id) < (?, ?)"
|
||||||
|
query = query.Where(condition, decodedCursor.SortValue, decodedCursor.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 多取一条用于判断是否还有下一页
|
// 多取一条用于判断是否还有下一页
|
||||||
@@ -142,7 +200,11 @@ func (r *SystemNotificationRepository) GetByReceiverIDCursor(receiverID string,
|
|||||||
var nextCursor string
|
var nextCursor string
|
||||||
if hasMore && len(notifications) > 0 {
|
if hasMore && len(notifications) > 0 {
|
||||||
lastNotification := notifications[len(notifications)-1]
|
lastNotification := notifications[len(notifications)-1]
|
||||||
nextCursor = lastNotification.CreatedAt.Format("2006-01-02 15:04:05.999999999")
|
nextCursor = cursor.NewCursor(
|
||||||
|
cursor.FormatTime(lastNotification.CreatedAt),
|
||||||
|
strconv.FormatInt(lastNotification.ID, 10),
|
||||||
|
cursor.SortByCreatedAtDesc,
|
||||||
|
).Encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
return notifications, nextCursor, hasMore, nil
|
return notifications, nextCursor, hasMore, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user