feat: 卡流量读数先过采集队列再入账,扣减按采集时刻确定套餐
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m27s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m27s
- 每卡 Redis 采集队列(默认 N=3、跨天清空、回退容差 1 MB),攒满且不下降才写最后一个点 - 测试环境全量切换日快照计量,下线灰度名单、切换水位与卡表基线扣费;全部卡置待建起点 - 读数区分没给值与 0;有套餐的卡读数 0 也写快照与日用量 0 行;重置日比较基准为 0 照常防旧值 - 新增采集记录(按月分区保留 90 天)、人工冲正流水与后台接口、采集告警 - 扣减按采集时刻有效套餐查找,只对生效中套餐做状态迁移,查不到套餐按成功跳过 - 换货新卡(新设备下的卡)打待建起点;采集间隔上限只校验启用中的轮询配置 Change: add-card-traffic-queue-and-observed-deduction Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
agentrechargeApp "github.com/break/junhong_cmp_fiber/internal/application/agentrecharge"
|
||||
businessUserGroupApp "github.com/break/junhong_cmp_fiber/internal/application/businessusergroup"
|
||||
cardObservationApp "github.com/break/junhong_cmp_fiber/internal/application/cardobservation"
|
||||
employeecollectionApp "github.com/break/junhong_cmp_fiber/internal/application/employeecollection"
|
||||
h5PopupApp "github.com/break/junhong_cmp_fiber/internal/application/h5popup"
|
||||
merchantPaymentApp "github.com/break/junhong_cmp_fiber/internal/application/merchantpayment"
|
||||
@@ -129,6 +131,7 @@ func initHandlers(svc *services, deps *Dependencies) *Handlers {
|
||||
gatewaylimit.RegisterConfigDefinitions(systemConfigRegistry, deps.Logger)
|
||||
carrierqueue.RegisterConfigDefinitions(systemConfigRegistry, deps.Logger)
|
||||
packagesilenceApp.RegisterConfigDefinitions(systemConfigRegistry, deps.Logger)
|
||||
registerTrafficQueueConfigDefinitions(systemConfigRegistry, deps)
|
||||
systemConfigAlerts := systemConfigInfra.NewLogAlertSink(deps.Logger)
|
||||
var systemConfigCache systemConfigInfra.Cache
|
||||
if deps.Redis != nil {
|
||||
@@ -437,5 +440,19 @@ func newAssetPollingService(svc *services, deps *Dependencies) *pollingSvcPkg.As
|
||||
)
|
||||
svc.Order.SetPollingRestorer(assetPollingSvc)
|
||||
svc.Asset.SetPollingRestorer(assetPollingSvc, svc.StopResumeService, deps.Logger)
|
||||
svc.Asset.SetTrafficAdjustmentEvaluator(svc.StopResumeService)
|
||||
return assetPollingSvc
|
||||
}
|
||||
|
||||
// registerTrafficQueueConfigDefinitions 注册卡流量采集队列配置:修改队列长度、跨天清空、最长点龄前
|
||||
// 校验全部启用中的轮询配置的流量采集间隔仍在上限内,否则拒绝修改。
|
||||
func registerTrafficQueueConfigDefinitions(registry *systemConfigInfra.Registry, deps *Dependencies) {
|
||||
settings := cardObservationApp.NewDefaultTrafficQueueSettingsProvider(deps.DB, deps.Redis, deps.Logger)
|
||||
current := func() cardObservationApp.TrafficQueueSettings { return settings.Current(context.Background()) }
|
||||
checker := func(next cardObservationApp.TrafficQueueSettings) error {
|
||||
return pollingSvcPkg.CheckEnabledTrafficIntervals(context.Background(), deps.DB, pollingSvcPkg.TrafficQueueLimits{
|
||||
Size: next.Size, ClearOnNewDay: next.ClearOnNewDay, MaxPointAgeHours: next.MaxPointAgeHours,
|
||||
})
|
||||
}
|
||||
cardObservationApp.RegisterTrafficQueueConfigDefinitions(registry, deps.Logger, current, checker)
|
||||
}
|
||||
|
||||
@@ -207,12 +207,9 @@ func initServices(s *stores, deps *Dependencies) *services {
|
||||
cardObservationService.SetStateAuditWriter(iotCard)
|
||||
// 运营商通道流量阈值达量判定嵌入流量观测事务:与卡流量事实同事务写周期锁与停机事件。
|
||||
cardObservationService.SetChannelThresholdEvaluator(carrierThresholdService)
|
||||
// 卡流量计量切换策略:启动时展开灰度名单为内存卡集合,API 与全部 Worker 必须使用一致配置。
|
||||
var trafficCalcPolicy *cardObservationApp.TrafficCalcPolicy
|
||||
if cfg := config.Get(); cfg != nil {
|
||||
trafficCalcPolicy = cardObservationApp.BuildTrafficCalcPolicy(context.Background(), deps.DB, cfg.TrafficCalc, deps.Logger)
|
||||
}
|
||||
cardObservationService.SetTrafficCalcPolicy(trafficCalcPolicy, deps.Logger)
|
||||
// 卡流量采集队列:读数先进每卡 Redis 队列,满足写入条件才写日快照;队列配置为受控系统配置。
|
||||
cardObservationService.SetTrafficQueue(cardObservationInfra.NewTrafficQueue(deps.Redis),
|
||||
cardObservationApp.NewDefaultTrafficQueueSettingsProvider(deps.DB, deps.Redis, deps.Logger), deps.Logger)
|
||||
cardObservationService.SetCommandGrace(commandGraceProvider(deps.DB, deps.Redis, deps.Logger))
|
||||
iotCard.SetCardObservationService(cardObservationService)
|
||||
iotCard.SetSpeedTierIntegrationLog(integrationlog.NewRepository(deps.DB))
|
||||
@@ -509,6 +506,11 @@ func initServices(s *stores, deps *Dependencies) *services {
|
||||
pollingConfigService := pollingSvc.NewConfigService(s.PollingConfig, deps.Redis, deps.Logger)
|
||||
pollingConfigService.SetAudit(deps.DB, auditWriter)
|
||||
pollingConfigService.SetTierDeps(pollingConfigMgr, deps.QueueClient)
|
||||
trafficQueueSettings := cardObservationApp.NewDefaultTrafficQueueSettingsProvider(deps.DB, deps.Redis, deps.Logger)
|
||||
pollingConfigService.SetTrafficQueueLimits(func(ctx context.Context) pollingSvc.TrafficQueueLimits {
|
||||
current := trafficQueueSettings.Current(ctx)
|
||||
return pollingSvc.TrafficQueueLimits{Size: current.Size, ClearOnNewDay: current.ClearOnNewDay, MaxPointAgeHours: current.MaxPointAgeHours}
|
||||
})
|
||||
pollingConcurrencyService := pollingSvc.NewConcurrencyService(s.PollingConcurrencyConfig, deps.Redis)
|
||||
pollingConcurrencyService.SetAudit(deps.DB, auditWriter)
|
||||
pollingAlertService := pollingSvc.NewAlertService(s.PollingAlertRule, s.PollingAlertHistory, deps.Redis, deps.Logger)
|
||||
@@ -604,7 +606,7 @@ func initServices(s *stores, deps *Dependencies) *services {
|
||||
AgentRechargePaymentConfirm: agentRechargePaymentConfirm,
|
||||
AgentRechargeVoucherOCR: agentRechargeVoucherOCR,
|
||||
PackageActivation: packageActivation,
|
||||
TrafficQuery: trafficSvc.NewQueryService(deps.Redis, s.CardDailyUsage).WithFlowSnapshots(trafficCalcPolicy.Switched, postgres.NewCardFlowDayStore(deps.DB)),
|
||||
TrafficQuery: trafficSvc.NewQueryService(deps.Redis, s.CardDailyUsage).WithFlowSnapshots(func(uint) bool { return true }, postgres.NewCardFlowDayStore(deps.DB)),
|
||||
OperationPassword: operationPassword,
|
||||
AgentOpenAPI: agentOpenAPI,
|
||||
Refund: refundService,
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
pollingPkg "github.com/break/junhong_cmp_fiber/internal/polling"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/config"
|
||||
|
||||
assetAutoRenewalApp "github.com/break/junhong_cmp_fiber/internal/application/assetautorenewal"
|
||||
cardObservationApp "github.com/break/junhong_cmp_fiber/internal/application/cardobservation"
|
||||
carrierThresholdApp "github.com/break/junhong_cmp_fiber/internal/application/carrierthreshold"
|
||||
@@ -140,11 +137,9 @@ func initWorkerServices(stores *queue.WorkerStores, deps *WorkerDependencies) *q
|
||||
// 运营商通道流量阈值达量判定嵌入流量观测事务:与卡流量事实同事务写周期锁与停机事件。
|
||||
cardObservationService.SetChannelThresholdEvaluator(carrierThresholdService)
|
||||
cardObservationService.SetCommandGrace(commandGraceProvider(deps.DB, deps.Redis, deps.Logger))
|
||||
// 卡流量计量切换策略:启动时展开灰度名单为内存卡集合,API 与全部 Worker 必须使用一致配置。
|
||||
if cfg := config.Get(); cfg != nil {
|
||||
cardObservationService.SetTrafficCalcPolicy(
|
||||
cardObservationApp.BuildTrafficCalcPolicy(context.Background(), deps.DB, cfg.TrafficCalc, deps.Logger), deps.Logger)
|
||||
}
|
||||
// 卡流量采集队列:读数先进每卡 Redis 队列,满足写入条件才写日快照;队列配置为受控系统配置。
|
||||
cardObservationService.SetTrafficQueue(cardObservationInfra.NewTrafficQueue(deps.Redis),
|
||||
cardObservationApp.NewDefaultTrafficQueueSettingsProvider(deps.DB, deps.Redis, deps.Logger), deps.Logger)
|
||||
// 激活前流量结算:与 API 进程一致,注入激活服务与订单服务。
|
||||
preActivationSettler := cardObservationInfra.NewPreActivationSettler(deps.DB, deps.GatewayClient, cardObservationService, postgres.NewCarrierStore(deps.DB), deps.Logger)
|
||||
activationService.SetPreActivationSettler(preActivationSettler)
|
||||
|
||||
Reference in New Issue
Block a user