refactor(repository): 收敛 model/repository 分层为唯一持久化入口

将 OpenFlare 与平台业务的数据访问从 model 与 apps 直连迁入 repository,
model 仅保留实体与无 IO 规则;补充 code-check 架构守卫与开发规范。
This commit is contained in:
ryan
2026-07-24 17:00:17 +08:00
parent 23a5488203
commit 943818f7d4
184 changed files with 5592 additions and 4364 deletions
@@ -8,6 +8,8 @@ import (
"strings"
"time"
"github.com/Rain-kl/Wavelet/internal/repository"
"github.com/Rain-kl/Wavelet/internal/model"
analyticsrepo "github.com/Rain-kl/Wavelet/internal/repository/analytics"
"github.com/Rain-kl/Wavelet/pkg/logger"
@@ -309,7 +311,7 @@ func GetAccessLogOverview(ctx context.Context, input AccessLogOverviewQuery) (*A
Until: now,
}
summaryRow, err := model.TrafficSummaryOpenFlareAccessLogs(ctx, query)
summaryRow, err := repository.TrafficSummaryOpenFlareAccessLogs(ctx, query)
if err != nil {
return nil, err
}
@@ -408,7 +410,7 @@ func valueCountDistribution(
column string,
limit int,
) []DistributionItem {
rows, err := model.ValueCountsOpenFlareAccessLogs(ctx, query, column, limit)
rows, err := repository.ValueCountsOpenFlareAccessLogs(ctx, query, column, limit)
if err != nil {
logger.ErrorF(ctx, "[AccessLog] ValueCountsOpenFlareAccessLogs failed for column %s: %v", column, err)
return []DistributionItem{}
@@ -496,7 +498,7 @@ func buildAccessLogOverviewTrends(
bandwidth[index].BucketStartedAt = bucketAt
}
buckets, err := model.ListOpenFlareAccessLogBuckets(ctx, model.OpenFlareAccessLogBucketQuery{
buckets, err := repository.ListOpenFlareAccessLogBuckets(ctx, model.OpenFlareAccessLogBucketQuery{
NodeID: query.NodeID,
Host: query.Host,
Hosts: query.Hosts,
@@ -532,11 +534,11 @@ func buildAccessLogOverviewTrends(
func ListAccessLogs(ctx context.Context, input AccessLogQuery) (*AccessLogList, error) {
normalized := normalizeAccessLogQuery(input)
modelQuery := buildModelAccessLogQuery(normalized)
logs, err := model.ListOpenFlareAccessLogs(ctx, modelQuery)
logs, err := repository.ListOpenFlareAccessLogs(ctx, modelQuery)
if err != nil {
return nil, err
}
totalRecords, totalIPs, _, err := model.CountOpenFlareAccessLogs(ctx, modelQuery)
totalRecords, totalIPs, _, err := repository.CountOpenFlareAccessLogs(ctx, modelQuery)
if err != nil {
return nil, err
}
@@ -597,15 +599,15 @@ func ListFoldedAccessLogs(ctx context.Context, input AccessLogQuery) (*FoldedAcc
SortOrder: normalized.SortOrder,
FoldMinutes: foldMinutes,
}
items, err := model.ListOpenFlareAccessLogBuckets(ctx, bucketQuery)
items, err := repository.ListOpenFlareAccessLogBuckets(ctx, bucketQuery)
if err != nil {
return nil, err
}
totalBuckets, err := model.CountOpenFlareAccessLogBuckets(ctx, bucketQuery)
totalBuckets, err := repository.CountOpenFlareAccessLogBuckets(ctx, bucketQuery)
if err != nil {
return nil, err
}
totalRecords, totalIPs, _, err := model.CountOpenFlareAccessLogs(ctx, modelQuery)
totalRecords, totalIPs, _, err := repository.CountOpenFlareAccessLogs(ctx, modelQuery)
if err != nil {
return nil, err
}
@@ -654,11 +656,11 @@ func ListFoldedAccessLogIPs(ctx context.Context, input FoldedAccessLogIPQuery) (
SortBy: normalized.SortBy,
SortOrder: normalized.SortOrder,
}
items, err := model.ListOpenFlareAccessLogBucketIPs(ctx, modelQuery)
items, err := repository.ListOpenFlareAccessLogBucketIPs(ctx, modelQuery)
if err != nil {
return nil, err
}
totalIP, err := model.CountOpenFlareAccessLogBucketIPs(ctx, modelQuery)
totalIP, err := repository.CountOpenFlareAccessLogBucketIPs(ctx, modelQuery)
if err != nil {
return nil, err
}
@@ -706,11 +708,11 @@ func ListAccessLogIPSummaries(ctx context.Context, input AccessLogIPSummaryQuery
SortBy: normalized.SortBy,
SortOrder: normalized.SortOrder,
}
items, err := model.ListOpenFlareAccessLogIPSummaries(ctx, query, time.Time{})
items, err := repository.ListOpenFlareAccessLogIPSummaries(ctx, query, time.Time{})
if err != nil {
return nil, err
}
totalIP, err := model.CountOpenFlareAccessLogIPSummaries(ctx, query)
totalIP, err := repository.CountOpenFlareAccessLogIPSummaries(ctx, query)
if err != nil {
return nil, err
}
@@ -751,7 +753,7 @@ func GetAccessLogIPTrend(ctx context.Context, input AccessLogIPTrendQuery) (*Acc
if err != nil {
return nil, err
}
points, err := model.ListOpenFlareAccessLogIPTrend(ctx, model.OpenFlareAccessLogIPTrendQuery{
points, err := repository.ListOpenFlareAccessLogIPTrend(ctx, model.OpenFlareAccessLogIPTrendQuery{
NodeID: strings.TrimSpace(normalized.NodeID),
RemoteAddr: strings.TrimSpace(normalized.RemoteAddr),
Host: strings.TrimSpace(normalized.Host),
@@ -802,7 +804,7 @@ func GetAccessLogIPAnalysis(ctx context.Context, input AccessLogIPAnalysisQuery)
Until: now,
}
summaryRow, err := model.TrafficSummaryOpenFlareAccessLogs(ctx, query)
summaryRow, err := repository.TrafficSummaryOpenFlareAccessLogs(ctx, query)
if err != nil {
return nil, err
}
@@ -868,7 +870,7 @@ func CleanupAccessLogs(ctx context.Context, input AccessLogCleanupInput) (*Acces
return nil, errors.New("retention_days 必须在 1 到 90 之间")
}
cutoff := time.Now().UTC().Add(-time.Duration(input.RetentionDays) * 24 * time.Hour)
deleted, err := model.DeleteOpenFlareAccessLogsBefore(ctx, cutoff)
deleted, err := repository.DeleteOpenFlareAccessLogsBefore(ctx, cutoff)
if err != nil {
return nil, err
}
@@ -913,7 +915,7 @@ func listNodeNameMap(ctx context.Context, logs []*model.OpenFlareAccessLog) (map
if len(nodeIDs) == 0 {
return map[string]string{}, nil
}
nodes, err := model.ListOpenFlareNodesByNodeIDs(ctx, nodeIDs)
nodes, err := repository.ListOpenFlareNodesByNodeIDs(ctx, nodeIDs)
if err != nil {
return nil, err
}
@@ -9,6 +9,8 @@ import (
"strings"
"time"
"github.com/Rain-kl/Wavelet/internal/repository"
"github.com/Rain-kl/Wavelet/internal/model"
)
@@ -135,7 +137,7 @@ func buildTrafficWindowSummaryFromAccessLogs(
nodeID string,
since, until time.Time,
) *TrafficWindowSummary {
row, err := model.TrafficSummaryOpenFlareAccessLogs(ctx, model.OpenFlareAccessLogQuery{
row, err := repository.TrafficSummaryOpenFlareAccessLogs(ctx, model.OpenFlareAccessLogQuery{
NodeID: nodeID,
Since: since,
Until: until,
@@ -203,7 +205,7 @@ func BuildTrafficDistributionsFromAccessLogs(
topDomains := make(distributionAccumulator)
query := model.OpenFlareAccessLogQuery{Since: since, Until: until}
if statusRows, err := model.ValueCountsOpenFlareAccessLogs(ctx, query, "status_code", limit); err == nil {
if statusRows, err := repository.ValueCountsOpenFlareAccessLogs(ctx, query, "status_code", limit); err == nil {
for _, row := range statusRows {
if strings.TrimSpace(row.Value) == "" || row.Count <= 0 {
continue
@@ -211,7 +213,7 @@ func BuildTrafficDistributionsFromAccessLogs(
statusCodes[row.Value] = row.Count
}
}
if hostRows, err := model.ValueCountsOpenFlareAccessLogs(ctx, query, "host", limit); err == nil {
if hostRows, err := repository.ValueCountsOpenFlareAccessLogs(ctx, query, "host", limit); err == nil {
for _, row := range hostRows {
if strings.TrimSpace(row.Value) == "" || row.Count <= 0 {
continue
@@ -287,7 +289,7 @@ func BuildNodeTrends(
applyAccessLogBytesToNetworkTrend(ctx, now, nodeID, trendSince, networkTrend)
diskIOTrend := BuildDiskIOTrendPoints(now, snapshots)
metricHourly, metricErr := model.ListOpenFlareMetricHourlySince(ctx, nodeID, trendSince)
metricHourly, metricErr := repository.ListOpenFlareMetricHourlySince(ctx, nodeID, trendSince)
if metricErr == nil && len(metricHourly) > 0 {
capacityTrend = BuildCapacityTrendPointsFromHourly(now, metricHourly)
diskIOTrend = BuildDiskIOTrendPointsFromHourly(now, metricHourly)
@@ -311,7 +313,7 @@ func BuildTrafficTrendPointsFromAccessLogs(ctx context.Context, now time.Time, n
points[index].BucketStartedAt = start.Add(time.Duration(index) * time.Hour)
}
if hourly, err := model.ListOpenFlareTrafficHourlySince(ctx, nodeID, since); err == nil && len(hourly) > 0 {
if hourly, err := repository.ListOpenFlareTrafficHourlySince(ctx, nodeID, since); err == nil && len(hourly) > 0 {
for _, row := range hourly {
if row == nil {
continue
@@ -327,7 +329,7 @@ func BuildTrafficTrendPointsFromAccessLogs(ctx context.Context, now time.Time, n
return points
}
buckets, err := model.ListOpenFlareAccessLogBuckets(ctx, model.OpenFlareAccessLogBucketQuery{
buckets, err := repository.ListOpenFlareAccessLogBuckets(ctx, model.OpenFlareAccessLogBucketQuery{
NodeID: nodeID,
Since: since,
Until: now,
@@ -373,7 +375,7 @@ func applyAccessLogBytesToNetworkTrend(ctx context.Context, now time.Time, nodeI
return
}
buckets, err := model.ListOpenFlareAccessLogBuckets(ctx, model.OpenFlareAccessLogBucketQuery{
buckets, err := repository.ListOpenFlareAccessLogBuckets(ctx, model.OpenFlareAccessLogBucketQuery{
NodeID: nodeID,
Since: since,
Until: now,
@@ -406,7 +408,7 @@ type accessLogHourBytes struct {
}
func analyticsListAccessLogHourlyBytes(ctx context.Context, nodeID string, since time.Time) (map[int64]accessLogHourBytes, error) {
rows, err := model.ListOpenFlareAccessLogHourlySince(ctx, nodeID, since)
rows, err := repository.ListOpenFlareAccessLogHourlySince(ctx, nodeID, since)
if err != nil {
return nil, err
}
@@ -10,6 +10,8 @@ import (
"sync"
"time"
"github.com/Rain-kl/Wavelet/internal/repository"
"github.com/Rain-kl/Wavelet/internal/model"
"gorm.io/gorm"
)
@@ -94,7 +96,7 @@ type HealthEventCleanupResult struct {
// GetNodeObservability returns observability details for a node.
func GetNodeObservability(ctx context.Context, id uint, query NodeQuery) (*NodeView, error) {
now := time.Now()
node, err := model.GetOpenFlareNodeByID(ctx, id)
node, err := repository.GetOpenFlareNodeByID(ctx, id)
if err != nil {
return nil, err
}
@@ -105,7 +107,7 @@ func GetNodeObservability(ctx context.Context, id uint, query NodeQuery) (*NodeV
limit := normalizeObservabilityLimit(query.Limit)
since := now.Add(-normalizeObservabilityWindow(query.Hours))
profile, err := model.GetOpenFlareNodeSystemProfile(ctx, node.NodeID)
profile, err := repository.GetOpenFlareNodeSystemProfile(ctx, node.NodeID)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
@@ -113,19 +115,19 @@ func GetNodeObservability(ctx context.Context, id uint, query NodeQuery) (*NodeV
profile = nil
}
snapshots, err := model.ListOpenFlareMetricSnapshotsSince(ctx, node.NodeID, since, limit)
snapshots, err := repository.ListOpenFlareMetricSnapshotsSince(ctx, node.NodeID, since, limit)
if err != nil {
return nil, err
}
edgeHealth, err := model.ListOpenFlareEdgeHealth(ctx, node.NodeID, since, limit)
edgeHealth, err := repository.ListOpenFlareEdgeHealth(ctx, node.NodeID, since, limit)
if err != nil {
return nil, err
}
accessLogRegions, err := model.ListOpenFlareAccessLogRegionCounts(ctx, node.NodeID, since, defaultTrafficDistributionLimit)
accessLogRegions, err := repository.ListOpenFlareAccessLogRegionCounts(ctx, node.NodeID, since, defaultTrafficDistributionLimit)
if err != nil {
return nil, err
}
events, err := model.ListOpenFlareHealthEvents(ctx, node.NodeID, false, limit)
events, err := repository.ListOpenFlareHealthEvents(ctx, node.NodeID, false, limit)
if err != nil {
return nil, err
}
@@ -146,7 +148,7 @@ func GetNodeObservability(ctx context.Context, id uint, query NodeQuery) (*NodeV
Trends: BuildNodeTrends(ctx, now, node.NodeID, snapshots),
}
if node.NodeType == "tunnel_relay" {
frpsObs, frpsErr := model.ListOpenFlareNodeObservationFrps(ctx, node.NodeID, time.Time{}, 1)
frpsObs, frpsErr := repository.ListOpenFlareNodeObservationFrps(ctx, node.NodeID, time.Time{}, 1)
if frpsErr != nil {
return nil, frpsErr
}
@@ -187,11 +189,11 @@ func setCachedNodeObservability(nodeID string, view *NodeView) {
// CleanupHealthEvents removes all health events for a node.
func CleanupHealthEvents(ctx context.Context, id uint) (*HealthEventCleanupResult, error) {
node, err := model.GetOpenFlareNodeByID(ctx, id)
node, err := repository.GetOpenFlareNodeByID(ctx, id)
if err != nil {
return nil, err
}
deletedCount, err := model.DeleteOpenFlareHealthEventsByNodeID(ctx, node.NodeID)
deletedCount, err := repository.DeleteOpenFlareHealthEventsByNodeID(ctx, node.NodeID)
if err != nil {
return nil, err
}