feat(notif): 点赞通知延迟落库,短时取消不打扰作者
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,10 +1,16 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/freefire/jiang13-bbs/model"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// LikeNotifyDelay 点赞通知冷却:未满该时长即取消点赞则不通知作者
|
||||
const LikeNotifyDelay = time.Minute
|
||||
|
||||
// NotificationService 通知服务
|
||||
type NotificationService struct {
|
||||
db *gorm.DB
|
||||
@@ -16,6 +22,57 @@ func NewNotificationService(db *gorm.DB) *NotificationService {
|
||||
return &NotificationService{db: db}
|
||||
}
|
||||
|
||||
// FlushPendingLikeNotifications 将已冷却且仍有效的点赞落为通知(误赞撤回不会进入此处)。
|
||||
func (s *NotificationService) FlushPendingLikeNotifications(limit int) {
|
||||
if limit < 1 {
|
||||
limit = 50
|
||||
}
|
||||
cutoff := time.Now().Add(-LikeNotifyDelay)
|
||||
type pendingLike struct {
|
||||
PostID uint
|
||||
UserID uint
|
||||
AuthorID uint
|
||||
}
|
||||
var rows []pendingLike
|
||||
err := s.db.Raw(`
|
||||
SELECT l.post_id AS post_id, l.user_id AS user_id, p.user_id AS author_id
|
||||
FROM likes l
|
||||
INNER JOIN posts p ON p.id = l.post_id
|
||||
WHERE l.created_at <= ?
|
||||
AND p.deleted_at IS NULL
|
||||
AND p.status = ?
|
||||
AND l.user_id <> p.user_id
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM notifications n
|
||||
WHERE n.type = ?
|
||||
AND n.actor_id = l.user_id
|
||||
AND n.post_id = l.post_id
|
||||
AND n.user_id = p.user_id
|
||||
AND n.created_at >= l.created_at
|
||||
)
|
||||
ORDER BY l.created_at ASC
|
||||
LIMIT ?
|
||||
`, cutoff, model.ContentStatusPublished, model.NotificationTypeLike, limit).Scan(&rows).Error
|
||||
if err != nil {
|
||||
log.Printf("[notif] 扫描待发点赞通知失败: %v", err)
|
||||
return
|
||||
}
|
||||
for _, row := range rows {
|
||||
s.Create(row.AuthorID, row.UserID, model.NotificationTypeLike, row.PostID, 0, "")
|
||||
}
|
||||
}
|
||||
|
||||
// StartLikeNotifyFlusher 周期落库冷却后的点赞通知
|
||||
func StartLikeNotifyFlusher(s *NotificationService) {
|
||||
go func() {
|
||||
t := time.NewTicker(20 * time.Second)
|
||||
defer t.Stop()
|
||||
for range t.C {
|
||||
s.FlushPendingLikeNotifications(50)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Create 创建通知(actorID == userID 时跳过,不通知自己)
|
||||
func (s *NotificationService) Create(userID, actorID uint, notifType string, postID, commentID uint, content string) {
|
||||
if userID == 0 || actorID == 0 || userID == actorID {
|
||||
|
||||
Reference in New Issue
Block a user