Files
OpenFlare/internal/repository/upload_stat.go
T
ryan 943818f7d4 refactor(repository): 收敛 model/repository 分层为唯一持久化入口
将 OpenFlare 与平台业务的数据访问从 model 与 apps 直连迁入 repository,
model 仅保留实体与无 IO 规则;补充 code-check 架构守卫与开发规范。
2026-07-24 17:00:17 +08:00

98 lines
2.8 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package repository
import (
"context"
"time"
"gorm.io/gorm"
"gorm.io/gorm/clause"
db "github.com/Rain-kl/Wavelet/internal/infra/persistence"
"github.com/Rain-kl/Wavelet/internal/model"
)
// ListUploadStats returns all upload statistics rows.
func ListUploadStats(ctx context.Context) ([]model.UploadStat, error) {
var stats []model.UploadStat
if err := db.DB(ctx).Find(&stats).Error; err != nil {
return nil, err
}
return stats, nil
}
// GetTotalUploadStat returns the aggregate total-dimension stats row.
func GetTotalUploadStat(ctx context.Context) (model.UploadStat, error) {
var total model.UploadStat
if err := db.DB(ctx).
Where("dimension = ? AND stat_key = ?", model.UploadStatDimensionTotal, "").
First(&total).Error; err != nil {
return model.UploadStat{}, err
}
return total, nil
}
// ListUploadStatsByDimension returns stats rows for a single dimension.
func ListUploadStatsByDimension(ctx context.Context, dimension string) ([]model.UploadStat, error) {
var rows []model.UploadStat
if err := db.DB(ctx).Where("dimension = ?", dimension).Find(&rows).Error; err != nil {
return nil, err
}
return rows, nil
}
// DeleteAllUploadStatsTx removes every row from w_upload_stats within a transaction.
func DeleteAllUploadStatsTx(tx *gorm.DB) error {
return tx.Where("1 = 1").Delete(&model.UploadStat{}).Error
}
// UpsertUploadStatDeltaTx applies an incremental count/size delta for one dimension key.
func UpsertUploadStatDeltaTx(tx *gorm.DB, dimension, key string, countDelta, sizeDelta int64) error {
return tx.Clauses(clause.OnConflict{
Columns: []clause.Column{
{Name: "dimension"},
{Name: "stat_key"},
},
DoUpdates: clause.Assignments(map[string]any{
"file_count": gorm.Expr(
"CASE WHEN w_upload_stats.file_count + ? < 0 THEN 0 ELSE w_upload_stats.file_count + ? END",
countDelta,
countDelta,
),
"file_size": gorm.Expr(
"CASE WHEN w_upload_stats.file_size + ? < 0 THEN 0 ELSE w_upload_stats.file_size + ? END",
sizeDelta,
sizeDelta,
),
"updated_at": time.Now(),
}),
}).Create(&model.UploadStat{
Dimension: dimension,
StatKey: key,
FileCount: countDelta,
FileSize: sizeDelta,
}).Error
}
// RebuildUploadStats clears w_upload_stats and re-applies deltas for every active upload
// inside a single transaction. applyDelta should apply +1 stats for one upload row.
func RebuildUploadStats(ctx context.Context, applyDelta func(tx *gorm.DB, upload *model.Upload) error) error {
return db.DB(ctx).Transaction(func(tx *gorm.DB) error {
if err := DeleteAllUploadStatsTx(tx); err != nil {
return err
}
uploads, err := ListActiveUploadsTx(tx)
if err != nil {
return err
}
for i := range uploads {
if err := applyDelta(tx, &uploads[i]); err != nil {
return err
}
}
return nil
})
}