mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
943818f7d4
将 OpenFlare 与平台业务的数据访问从 model 与 apps 直连迁入 repository, model 仅保留实体与无 IO 规则;补充 code-check 架构守卫与开发规范。
98 lines
2.8 KiB
Go
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
|
|
})
|
|
}
|