Files
junhong_cmp_fiber/internal/bootstrap/worker_services.go
邹进 98017ac053
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m37s
feat: 分层轮询、重置日前加密与激活前流量结算
- 轮询配置新增套餐状态、资产状态、重置日前窗口与窗口内流量间隔(迁移 248),间隔三态:正数按间隔、0 不检查、空继承
- 配置按 priority, id 排序合并;在库与已销售无套餐未匹配时告警不入队
- 新增优先级整体重排、匹配预览、立即重算到期时间(异步只提前)、分层统计与重置日前加密统计接口
- 已切换日快照计量的卡流量按观测时间归属,激活前用量只记已结算
- 订单购买与实名激活补齐资产级激活锁,激活前对已切换卡结算一次流量,失败只告警不阻塞,结算不触发通道阈值判定
2026-10-24 17:06:38 +09:00

247 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package bootstrap
import (
"context"
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
"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"
employeecollectionApp "github.com/break/junhong_cmp_fiber/internal/application/employeecollection"
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
assetAutoRenewalInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/assetautorenewal"
auditInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/audit"
cardObservationInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/cardobservation"
carrierThresholdInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/carrierthreshold"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/integrationlog"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
prioritypollingInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/prioritypolling"
walletinfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/wallet"
assetAutoRenewalQuery "github.com/break/junhong_cmp_fiber/internal/query/assetautorenewal"
"github.com/break/junhong_cmp_fiber/internal/service/commission_calculation"
"github.com/break/junhong_cmp_fiber/internal/service/commission_stats"
deviceSvc "github.com/break/junhong_cmp_fiber/internal/service/device"
iotCardSvc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
orderSvc "github.com/break/junhong_cmp_fiber/internal/service/order"
packagepkg "github.com/break/junhong_cmp_fiber/internal/service/package"
pollingSvc "github.com/break/junhong_cmp_fiber/internal/service/polling"
purchaseValidationSvc "github.com/break/junhong_cmp_fiber/internal/service/purchase_validation"
"github.com/break/junhong_cmp_fiber/pkg/queue"
)
type workerServices struct {
CommissionCalculation *commission_calculation.Service
CommissionStats *commission_stats.Service
UsageService *packagepkg.UsageService
ActivationService *packagepkg.ActivationService
ResetService *packagepkg.ResetService
AlertService *pollingSvc.AlertService
CleanupService *pollingSvc.CleanupService
}
func initWorkerServices(stores *queue.WorkerStores, deps *WorkerDependencies) *queue.WorkerServices {
auditWriter := auditInfra.NewWriter(auditInfra.NewRegistry(), nil)
commissionStatsService := commission_stats.New(stores.ShopSeriesCommissionStats)
commissionCalculationService := commission_calculation.New(
deps.DB,
stores.CommissionRecord,
stores.Shop,
stores.ShopPackageAllocation,
stores.ShopSeriesAllocation,
stores.PackageSeries,
stores.IotCard,
stores.Device,
stores.AgentWallet,
stores.AgentWalletTransaction,
stores.Order,
stores.OrderItem,
stores.Package,
stores.ShopSeriesCommissionStats,
commissionStatsService,
deps.Logger,
)
commissionCalculationService.SetAuditWriter(auditWriter)
usageService := packagepkg.NewUsageService(
deps.DB,
deps.Redis,
stores.PackageUsage,
stores.PackageUsageDailyRecord,
stores.DeviceSimBinding,
deps.Logger,
)
activationService := packagepkg.NewActivationService(
deps.DB,
deps.Redis,
stores.PackageUsage,
stores.Package,
stores.PackageUsageDailyRecord,
deps.Logger,
)
resetService := packagepkg.NewResetService(
deps.DB,
deps.Redis,
stores.PackageUsage,
deps.Logger,
)
activationService.SetLifecycleAudit(auditWriter)
usageService.SetLifecycleAudit(auditWriter)
resetService.SetLifecycleAudit(auditWriter)
alertService := pollingSvc.NewAlertService(
stores.PollingAlertRule,
stores.PollingAlertHistory,
deps.Redis,
deps.Logger,
)
cleanupService := pollingSvc.NewCleanupService(
stores.DataCleanupConfig,
stores.DataCleanupLog,
deps.Logger,
)
cardObservationOutbox := outbox.NewRepository()
observationSeriesEvents := cardObservationInfra.NewSeriesEventWriter(cardObservationOutbox)
priorityEvents := prioritypollingInfra.NewPriorityEventWriter(cardObservationOutbox)
// 运营商通道流量阈值用例:达量判定嵌入流量观测事务,持锁判定注入停复机入口。
carrierThresholdService := carrierThresholdApp.NewService(deps.DB, cardObservationOutbox).SetLogger(deps.Logger)
cardObservationService := cardObservationApp.NewService(
deps.DB,
cardObservationInfra.NewEventWriter(cardObservationOutbox),
cardObservationInfra.NewCacheInvalidator(deps.Redis, deps.Logger),
)
iotCardAuditService := iotCardSvc.New(
deps.DB, stores.IotCard, stores.Shop, stores.AssetAllocationRecord,
stores.ShopPackageAllocation, stores.ShopSeriesAllocation, stores.PackageSeries,
deps.GatewayClient, deps.Logger,
)
iotCardAuditService.SetAccessAudit(auditWriter)
iotCardAuditService.SetPhoneAssetAssociationStore(stores.PhoneAssetAssociation)
cardObservationService.SetStateAuditWriter(iotCardAuditService)
// 运营商通道流量阈值达量判定嵌入流量观测事务:与卡流量事实同事务写周期锁与停机事件。
cardObservationService.SetChannelThresholdEvaluator(carrierThresholdService)
// 卡流量计量切换策略:启动时展开灰度名单为内存卡集合,API 与全部 Worker 必须使用一致配置。
if cfg := config.Get(); cfg != nil {
cardObservationService.SetTrafficCalcPolicy(
cardObservationApp.BuildTrafficCalcPolicy(context.Background(), deps.DB, cfg.TrafficCalc, deps.Logger), deps.Logger)
}
// 激活前流量结算:与 API 进程一致,注入激活服务与订单服务。
preActivationSettler := cardObservationInfra.NewPreActivationSettler(deps.DB, deps.GatewayClient, cardObservationService, postgres.NewCarrierStore(deps.DB), deps.Logger)
activationService.SetPreActivationSettler(preActivationSettler)
cardObservationIntegration := integrationlog.NewRepository(deps.DB)
cardObservationSeriesCoordinator := cardObservationInfra.NewSeriesCoordinator(deps.Redis)
cardObservationSeriesService := cardObservationApp.NewSeriesAttemptService(
cardObservationSeriesCoordinator,
cardObservationInfra.NewSeriesRunner(deps.DB, deps.GatewayClient, cardObservationService, cardObservationIntegration, auditWriter),
cardObservationInfra.NewSeriesAttemptLogger(cardObservationIntegration),
)
// 初始化订单服务,供超时取消和批量订购共同复用现有订单规则。
purchaseValidation := purchaseValidationSvc.New(deps.DB, stores.IotCard, stores.Device, stores.Package, stores.ShopPackageAllocation)
orderService := orderSvc.New(
deps.DB,
deps.Redis,
stores.Order,
stores.OrderItem,
stores.AgentWallet,
stores.AssetWallet,
nil, // paymentStore: 超时取消不需要
purchaseValidation,
stores.ShopPackageAllocation,
stores.ShopSeriesAllocation,
stores.IotCard,
stores.Device,
stores.PackageSeries,
stores.PackageUsage,
stores.Package,
nil, // wechatConfigService: 超时取消不需要
nil, // wechatPayment: 超时取消不需要
nil, // paymentLoader: 超时取消不需要
deps.QueueClient,
deps.Logger,
stores.AssetIdentifier,
stores.PersonalCustomer,
stores.PersonalCustomerPhone,
)
// 批量订购线下支付建单需在订单事务内生成员工代收款账单,与 API 进程保持一致。
orderService.SetEmployeeCollectionBillCreation(employeecollectionApp.NewBillCreationService(auditWriter))
orderService.SetPreActivationSettler(preActivationSettler)
orderService.SetLifecycleAudit(auditWriter)
orderService.SetPaymentIntegrationLog(integrationlog.NewRepository(deps.DB))
walletOutbox := outbox.NewRepository()
walletDebitEvents := walletinfra.NewDebitEventWriter(walletOutbox, auditWriter)
orderService.SetAgentWalletReservationService(walletapp.NewReservationService(walletinfra.NewReservationEventWriter(walletOutbox, auditWriter), walletDebitEvents, nil))
orderService.SetAgentWalletDebitService(walletapp.NewDebitService(walletDebitEvents, nil))
orderService.SetObservationSeriesEventWriter(observationSeriesEvents)
orderService.SetPriorityEventWriter(priorityEvents)
// 创建停复机服务并注入回调:流量耗尽自动停机、套餐激活/重置/支付后自动复机
stopResumeService := iotCardSvc.NewStopResumeService(
deps.Redis,
stores.IotCard,
stores.PackageUsage,
stores.DeviceSimBinding,
deps.GatewayClient,
deps.Logger,
)
stopResumeService.SetObservationSeriesEventWriter(deps.DB, observationSeriesEvents)
stopResumeService.SetPriorityEventWriter(priorityEvents)
stopResumeService.SetUnifiedAudit(auditWriter, integrationlog.NewRepository(deps.DB))
if deps.GatewayLimit != nil {
stopResumeService.SetStopResumeRecorder(deps.GatewayLimit.Recorder)
}
// 持通道阈值锁的卡在周期内拒绝一切复机(自动、手动、保护期强制、机卡分离)。
stopResumeService.SetChannelThresholdLockGuard(carrierThresholdService)
// 停复机执行端口复用既有停复机服务作为唯一事实源:消费者与两个计划任务共用同一用例实例。
carrierThresholdService.SetCommander(carrierThresholdInfra.NewCardCommander(stopResumeService))
// 资产钱包自动续费:复机执行同样复用既有停复机单一事实源,通知与复机都走公共 Outbox。
assetAutoRenewalService := assetAutoRenewalApp.NewService(assetAutoRenewalApp.Dependencies{
DB: deps.DB, Redis: deps.Redis, Logger: deps.Logger,
Outbox: cardObservationOutbox, AuditWriter: auditWriter,
PurchaseValidation: purchaseValidation,
Candidates: assetAutoRenewalQuery.NewQuery(deps.DB),
Resume: assetAutoRenewalInfra.NewCardCommander(stopResumeService),
ObservationEvents: observationSeriesEvents,
PriorityEvents: priorityEvents,
})
activationService.SetObservationSeriesEventWriter(observationSeriesEvents)
activationService.SetPriorityEventWriter(priorityEvents)
usageService.SetStopResumeCallback(stopResumeService)
activationService.SetResumeCallback(stopResumeService)
orderService.SetResumeCallback(stopResumeService)
resetService.SetResumeCallback(stopResumeService)
deviceBatchAllocator := deviceSvc.New(
deps.DB, deps.Redis, stores.Device, stores.DeviceSimBinding, stores.IotCard, stores.Shop,
stores.AssetAllocationRecord, stores.ShopPackageAllocation, stores.ShopSeriesAllocation,
stores.PackageSeries, deps.GatewayClient, stores.AssetIdentifier, nil, nil,
)
deviceBatchAllocator.SetPhoneAssetAssociationStore(stores.PhoneAssetAssociation)
return &queue.WorkerServices{
PaymentAudit: auditWriter,
RechargeAudit: auditWriter,
CardObservation: cardObservationService,
CardObservationSeries: cardObservationSeriesService,
ObservationSeriesEvents: observationSeriesEvents,
PriorityEvents: priorityEvents,
CommissionCalculation: commissionCalculationService,
CommissionStats: commissionStatsService,
UsageService: usageService,
ActivationService: activationService,
ResetService: resetService,
AlertService: alertService,
CleanupService: cleanupService,
StopResumeService: stopResumeService,
CarrierThreshold: carrierThresholdService,
AssetAutoRenewal: assetAutoRenewalService,
OrderExpirer: orderService,
AssetPackageOrderCreator: orderService,
DeviceBatchAllocator: deviceBatchAllocator,
}
}