Files
backend/internal/repository/push_repo.go
lafay 2f584c1f2c
All checks were successful
Build Backend / build (push) Successful in 5m10s
Build Backend / build-docker (push) Successful in 2m22s
This is a breaking change that renames the entire project from "Carrot BBS" to "WithYou".
The Go module name has been changed from `carrot_bbs` to `with_you`, which requires
all import paths to be updated throughout the codebase and by external consumers.

BREAKING CHANGE: Module name changed from carrot_bbs to with_you. All imports
and dependencies must be updated from carrot_bbs/* to with_you/*.
2026-04-22 16:01:59 +08:00

191 lines
5.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package repository
import (
"time"
"with_you/internal/model"
"gorm.io/gorm"
)
// PushRecordRepository 推送记录仓储接口
type PushRecordRepository interface {
Create(record *model.PushRecord) error
GetByID(id int64) (*model.PushRecord, error)
Update(record *model.PushRecord) error
GetPendingPushes(limit int) ([]*model.PushRecord, error)
GetByUserID(userID string, limit, offset int) ([]*model.PushRecord, error)
GetByMessageID(messageID int64) ([]*model.PushRecord, error)
GetFailedPushesForRetry(limit int) ([]*model.PushRecord, error)
BatchCreate(records []*model.PushRecord) error
BatchUpdateStatus(ids []int64, status model.PushStatus) error
UpdateStatus(id int64, status model.PushStatus) error
MarkAsFailed(id int64, errMsg string) error
MarkAsDelivered(id int64) error
DeleteExpiredRecords() error
GetStatsByUserID(userID int64) (map[model.PushStatus]int64, error)
}
// pushRecordRepository 推送记录仓储实现
type pushRecordRepository struct {
db *gorm.DB
}
// NewPushRecordRepository 创建推送记录仓储
func NewPushRecordRepository(db *gorm.DB) PushRecordRepository {
return &pushRecordRepository{db: db}
}
// Create 创建推送记录
func (r *pushRecordRepository) Create(record *model.PushRecord) error {
return r.db.Create(record).Error
}
// GetByID 根据ID获取推送记录
func (r *pushRecordRepository) GetByID(id int64) (*model.PushRecord, error) {
var record model.PushRecord
err := r.db.First(&record, "id = ?", id).Error
if err != nil {
return nil, err
}
return &record, nil
}
// Update 更新推送记录
func (r *pushRecordRepository) Update(record *model.PushRecord) error {
return r.db.Save(record).Error
}
// GetPendingPushes 获取待推送记录
func (r *pushRecordRepository) GetPendingPushes(limit int) ([]*model.PushRecord, error) {
var records []*model.PushRecord
err := r.db.Where("push_status = ?", model.PushStatusPending).
Where("expired_at IS NULL OR expired_at > ?", time.Now()).
Order("created_at ASC").
Limit(limit).
Find(&records).Error
return records, err
}
// GetByUserID 根据用户ID获取推送记录
// userID 参数为 string 类型UUID格式与JWT中user_id保持一致
func (r *pushRecordRepository) GetByUserID(userID string, limit, offset int) ([]*model.PushRecord, error) {
var records []*model.PushRecord
err := r.db.Where("user_id = ?", userID).
Order("created_at DESC").
Offset(offset).
Limit(limit).
Find(&records).Error
return records, err
}
// GetByMessageID 根据消息ID获取推送记录
func (r *pushRecordRepository) GetByMessageID(messageID int64) ([]*model.PushRecord, error) {
var records []*model.PushRecord
err := r.db.Where("message_id = ?", messageID).
Order("created_at DESC").
Find(&records).Error
return records, err
}
// GetFailedPushesForRetry 获取失败待重试的推送
func (r *pushRecordRepository) GetFailedPushesForRetry(limit int) ([]*model.PushRecord, error) {
var records []*model.PushRecord
err := r.db.Where("push_status = ?", model.PushStatusFailed).
Where("retry_count < max_retry").
Where("expired_at IS NULL OR expired_at > ?", time.Now()).
Order("created_at ASC").
Limit(limit).
Find(&records).Error
return records, err
}
// BatchCreate 批量创建推送记录
func (r *pushRecordRepository) BatchCreate(records []*model.PushRecord) error {
if len(records) == 0 {
return nil
}
return r.db.Create(&records).Error
}
// BatchUpdateStatus 批量更新推送状态
func (r *pushRecordRepository) BatchUpdateStatus(ids []int64, status model.PushStatus) error {
if len(ids) == 0 {
return nil
}
updates := map[string]any{
"push_status": status,
}
if status == model.PushStatusPushed {
updates["pushed_at"] = time.Now()
}
return r.db.Model(&model.PushRecord{}).
Where("id IN ?", ids).
Updates(updates).Error
}
// UpdateStatus 更新单条记录状态
func (r *pushRecordRepository) UpdateStatus(id int64, status model.PushStatus) error {
updates := map[string]any{
"push_status": status,
}
if status == model.PushStatusPushed {
updates["pushed_at"] = time.Now()
}
return r.db.Model(&model.PushRecord{}).
Where("id = ?", id).
Updates(updates).Error
}
// MarkAsFailed 标记为失败
func (r *pushRecordRepository) MarkAsFailed(id int64, errMsg string) error {
return r.db.Model(&model.PushRecord{}).
Where("id = ?", id).
Updates(map[string]any{
"push_status": model.PushStatusFailed,
"error_message": errMsg,
"retry_count": gorm.Expr("retry_count + 1"),
}).Error
}
// MarkAsDelivered 标记为已送达
func (r *pushRecordRepository) MarkAsDelivered(id int64) error {
return r.db.Model(&model.PushRecord{}).
Where("id = ?", id).
Updates(map[string]any{
"push_status": model.PushStatusDelivered,
"delivered_at": time.Now(),
}).Error
}
// DeleteExpiredRecords 删除过期的推送记录(软删除)
func (r *pushRecordRepository) DeleteExpiredRecords() error {
return r.db.Where("expired_at IS NOT NULL AND expired_at < ?", time.Now()).
Delete(&model.PushRecord{}).Error
}
// GetStatsByUserID 获取用户推送统计
func (r *pushRecordRepository) GetStatsByUserID(userID int64) (map[model.PushStatus]int64, error) {
type statusCount struct {
Status model.PushStatus
Count int64
}
var results []statusCount
err := r.db.Model(&model.PushRecord{}).
Select("push_status as status, count(*) as count").
Where("user_id = ?", userID).
Group("push_status").
Scan(&results).Error
if err != nil {
return nil, err
}
stats := make(map[model.PushStatus]int64)
for _, r := range results {
stats[r.Status] = r.Count
}
return stats, nil
}