暂存一下,防止丢失
This commit is contained in:
92
internal/domain/cardobservation/traffic.go
Normal file
92
internal/domain/cardobservation/traffic.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package cardobservation
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
// TrafficObservation 是领域层接收的标准运营商流量读数。
|
||||
type TrafficObservation struct {
|
||||
CardID uint
|
||||
GatewayReadingMB float64
|
||||
ResetDay int
|
||||
Metadata ObservationMetadata
|
||||
}
|
||||
|
||||
// CardTrafficSnapshot 是流量规则需要的最小卡快照。
|
||||
type CardTrafficSnapshot struct {
|
||||
CardID uint
|
||||
DataUsageMB int64
|
||||
CurrentMonthUsageMB float64
|
||||
CurrentMonthStartDate *time.Time
|
||||
LastMonthTotalMB float64
|
||||
LastGatewayReadingMB float64
|
||||
}
|
||||
|
||||
// TrafficDecision 描述一次流量观测应持久化的最终值。
|
||||
type TrafficDecision struct {
|
||||
IncrementMB float64
|
||||
ReadingAccepted bool
|
||||
CrossMonth bool
|
||||
DataUsageMB int64
|
||||
CurrentMonthUsageMB float64
|
||||
CurrentMonthStartDate time.Time
|
||||
LastMonthTotalMB float64
|
||||
LastGatewayReadingMB float64
|
||||
}
|
||||
|
||||
// ApplyTraffic 应用运营商重置、跨月和异常下降保护规则。
|
||||
func ApplyTraffic(snapshot CardTrafficSnapshot, observation TrafficObservation) (TrafficDecision, error) {
|
||||
if err := validateObservationMetadata(observation.CardID, observation.Metadata); err != nil {
|
||||
return TrafficDecision{}, err
|
||||
}
|
||||
if math.IsNaN(observation.GatewayReadingMB) || math.IsInf(observation.GatewayReadingMB, 0) || observation.GatewayReadingMB < 0 {
|
||||
return TrafficDecision{}, errors.New(errors.CodeInvalidParam, "流量观测读数无效")
|
||||
}
|
||||
if observation.ResetDay < 1 || observation.ResetDay > 31 {
|
||||
return TrafficDecision{}, errors.New(errors.CodeInvalidParam, "运营商流量重置日无效")
|
||||
}
|
||||
now := observation.Metadata.ObservedAt
|
||||
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
decision := TrafficDecision{
|
||||
ReadingAccepted: true, DataUsageMB: snapshot.DataUsageMB,
|
||||
CurrentMonthUsageMB: snapshot.CurrentMonthUsageMB, CurrentMonthStartDate: monthStart,
|
||||
LastMonthTotalMB: snapshot.LastMonthTotalMB, LastGatewayReadingMB: observation.GatewayReadingMB,
|
||||
}
|
||||
increment := observation.GatewayReadingMB - snapshot.LastGatewayReadingMB
|
||||
if increment < 0 {
|
||||
if isTrafficResetWindow(now, observation.ResetDay) {
|
||||
increment = observation.GatewayReadingMB
|
||||
} else {
|
||||
increment = 0
|
||||
decision.ReadingAccepted = false
|
||||
decision.LastGatewayReadingMB = snapshot.LastGatewayReadingMB
|
||||
}
|
||||
}
|
||||
decision.IncrementMB = increment
|
||||
decision.CrossMonth = snapshot.CurrentMonthStartDate == nil || snapshot.CurrentMonthStartDate.Before(monthStart)
|
||||
if decision.CrossMonth {
|
||||
decision.LastMonthTotalMB = snapshot.CurrentMonthUsageMB
|
||||
decision.CurrentMonthUsageMB = increment
|
||||
} else if increment > 0 {
|
||||
decision.CurrentMonthUsageMB += increment
|
||||
}
|
||||
if increment > 0 {
|
||||
decision.DataUsageMB += int64(increment)
|
||||
}
|
||||
return decision, nil
|
||||
}
|
||||
|
||||
func validateObservationMetadata(cardID uint, metadata ObservationMetadata) error {
|
||||
return validateObservation(RealnameObservation{CardID: cardID, Verified: true, Metadata: metadata})
|
||||
}
|
||||
|
||||
func isTrafficResetWindow(now time.Time, resetDay int) bool {
|
||||
if now.Day() == resetDay {
|
||||
return true
|
||||
}
|
||||
resetDate := time.Date(now.Year(), now.Month(), resetDay, 0, 0, 0, 0, now.Location())
|
||||
return now.Day() == resetDate.AddDate(0, 0, -1).Day()
|
||||
}
|
||||
Reference in New Issue
Block a user