feat(通道流量阈值): AUG26-011 运营商通道流量阈值达量停机与周期复机
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 12m59s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 12m59s
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
domain "github.com/break/junhong_cmp_fiber/internal/domain/cardobservation"
|
||||
carrierthresholddomain "github.com/break/junhong_cmp_fiber/internal/domain/carrierthreshold"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
@@ -42,6 +43,12 @@ type CacheInvalidator interface {
|
||||
Invalidate(ctx context.Context, cardID uint)
|
||||
}
|
||||
|
||||
// ChannelThresholdEvaluator 在卡流量事务内判定运营商通道流量阈值。
|
||||
// 实现必须在调用方事务内写周期锁与停机事件,使锁事实与流量事实同事务提交。
|
||||
type ChannelThresholdEvaluator interface {
|
||||
EvaluateInTx(ctx context.Context, tx *gorm.DB, evaluation carrierthresholddomain.Evaluation) error
|
||||
}
|
||||
|
||||
// StateAudit 描述一次需要与卡事实关联保存的状态操作。
|
||||
type StateAudit struct {
|
||||
ActionCode string
|
||||
@@ -64,6 +71,8 @@ type Service struct {
|
||||
eventWriter EventWriter
|
||||
cache CacheInvalidator
|
||||
auditWriter StateAuditWriter
|
||||
// channelThreshold 为可选的通道阈值判定能力;未注入时流量观测不做阈值判定。
|
||||
channelThreshold ChannelThresholdEvaluator
|
||||
}
|
||||
|
||||
// NewService 创建卡实名观测应用服务。
|
||||
@@ -71,6 +80,11 @@ func NewService(db *gorm.DB, eventWriter EventWriter, cache CacheInvalidator) *S
|
||||
return &Service{db: db, eventWriter: eventWriter, cache: cache}
|
||||
}
|
||||
|
||||
// SetChannelThresholdEvaluator 注入运营商通道流量阈值达量判定能力。
|
||||
func (s *Service) SetChannelThresholdEvaluator(evaluator ChannelThresholdEvaluator) {
|
||||
s.channelThreshold = evaluator
|
||||
}
|
||||
|
||||
// SetStateAuditWriter 注入卡状态统一审计 Writer。
|
||||
func (s *Service) SetStateAuditWriter(writer StateAuditWriter) {
|
||||
s.auditWriter = writer
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
domain "github.com/break/junhong_cmp_fiber/internal/domain/cardobservation"
|
||||
carrierthresholddomain "github.com/break/junhong_cmp_fiber/internal/domain/carrierthreshold"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
@@ -80,6 +81,16 @@ func (s *Service) ApplyTrafficObservation(ctx context.Context, observation domai
|
||||
return err
|
||||
}
|
||||
}
|
||||
if decision.ReadingAccepted && s.channelThreshold != nil {
|
||||
// 达量判定只使用本次已接受的网关累计读数,异常下降保护命中的观测不参与判定;
|
||||
// 判定失败必须回滚整个流量事务,与既有流量事实保持同事务语义。
|
||||
if err := s.channelThreshold.EvaluateInTx(ctx, tx, carrierthresholddomain.Evaluation{
|
||||
CardID: card.ID, CarrierID: card.CarrierID,
|
||||
ReadingMB: decision.LastGatewayReadingMB, ObservedAt: observation.Metadata.ObservedAt,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
stateChanged := decision.IncrementMB != 0 || decision.CrossMonth || decision.LastGatewayReadingMB != card.LastGatewayReadingMB
|
||||
if actionCode, audited := manualRefreshAuditAction(ctx); observation.Metadata.Source == constants.CardObservationSourceManualSync && stateChanged && audited {
|
||||
if s.auditWriter == nil {
|
||||
|
||||
Reference in New Issue
Block a user