Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 8m39s
- 迁移 000259~000265:套餐记录沉默期字段与扫描索引、套餐默认沉默期、延期政策/流水/订单/批次/明细 5 张表、默认政策与系统配置(总开关默认关闭)、企微审批白名单、卡与设备出库时间及出库记录 - 沉默期设置(订单发放、自动购包、钱包续费)、后台购买时调整(超默认值按政策免审或企微审批)、统一判定与激活闸门、排队与孤儿扫描跳过过期套餐、过期套餐禁止退款、每 10 分钟扫描 - 总开关专用接口与打开前 4 项检查;延期政策;延期资格与计费;H5 自助与后台二维码在线支付(商户池路由)、支付回调与查单恢复、线下登记、特殊/批量延期、异常重试与原路退款;沉默期审批场景与终态处理 - 换货沉默期流水与出库时间;卡/设备列表、详情、导出与出库记录接口;延期订单与即将过期套餐列表及导出;财务流水纳入延期支付 - 沉默期与出库时间回填工具 cmd/silence-backfill;前端接口变更说明 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
278 lines
14 KiB
Go
278 lines
14 KiB
Go
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"
|
||
employeecollectionApp "github.com/break/junhong_cmp_fiber/internal/application/employeecollection"
|
||
"github.com/break/junhong_cmp_fiber/internal/application/merchantpayment"
|
||
packagesilenceApp "github.com/break/junhong_cmp_fiber/internal/application/packagesilence"
|
||
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"
|
||
paymentInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/payment"
|
||
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"
|
||
"github.com/break/junhong_cmp_fiber/pkg/wechat"
|
||
)
|
||
|
||
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)
|
||
packageSilence := newPackageSilenceBundle(deps.DB, deps.Redis, deps.Logger, auditWriter, activationService)
|
||
// Worker 内延期用例只承担审批通过后的执行、查单恢复与异常原路退款,不创建新申请。
|
||
silencePaymentLog := integrationlog.NewRepository(deps.DB)
|
||
packageSilence.Extensions.SetPayment(merchantpayment.NewRuntimeLoader(deps.DB, deps.Redis), packagesilenceApp.PaymentPorts{
|
||
Wechat: paymentInfra.NewWechatWebAdapter(wechat.NewRedisCache(deps.Redis), silencePaymentLog, deps.Logger),
|
||
Alipay: paymentInfra.NewAlipayWapAdapter(silencePaymentLog, deps.Logger),
|
||
Fuiou: paymentInfra.NewFuiouScanAdapter(silencePaymentLog, deps.Logger),
|
||
}, paymentInfra.NewRefundAdapter(wechat.NewRedisCache(deps.Redis), deps.Logger))
|
||
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)
|
||
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)
|
||
}
|
||
// 激活前流量结算:与 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)
|
||
// 资产轮询开关服务:轮询开关文件导入与订单套餐生效后自动恢复轮询(批量下单在 Worker 内执行)。
|
||
assetPollingService := pollingSvc.NewAssetPollingService(deps.DB, stores.Device, stores.DeviceSimBinding, iotCardAuditService,
|
||
pollingPkg.NewPollingQueueManager(deps.Redis, constants.PollingShardCount, deps.Logger), deps.Logger, auditWriter)
|
||
orderService.SetPollingRestorer(assetPollingService)
|
||
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)
|
||
orderService.SetSilenceSetter(packageSilence.Setter)
|
||
orderService.SetOutboundRecorder(packageSilence.Outbound)
|
||
|
||
// 创建停复机服务并注入回调:流量耗尽自动停机、套餐激活/重置/支付后自动复机
|
||
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)
|
||
deps.GatewayLimit.TerminalPolling.SetAuditWriter(auditWriter)
|
||
stopResumeService.SetTerminalPollingDisabler(deps.GatewayLimit.TerminalPolling)
|
||
}
|
||
// 持通道阈值锁的卡在周期内拒绝一切复机(自动、手动、机卡分离)。
|
||
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,
|
||
})
|
||
assetAutoRenewalService.SetSilenceRecorder(packagesilenceApp.PurchaseRecorder{Setter: packageSilence.Setter, Outbound: packageSilence.Outbound})
|
||
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,
|
||
AssetPolling: assetPollingService,
|
||
IotCardPolling: iotCardAuditService,
|
||
SilenceSwitch: packageSilence.Switch,
|
||
SilenceResolver: packageSilence.Resolver,
|
||
SilenceSetter: packageSilence.Setter,
|
||
SilenceOutbound: packageSilence.Outbound,
|
||
SilenceExtensions: packageSilence.Extensions,
|
||
}
|
||
}
|