merge: P6 对账守护并入(七job装配/退款自愈/孤儿发现/Notifier硬化/真实用量源)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u # Conflicts: # main.go
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"strings"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
"github.com/wangjia/pay/internal/gateway"
|
||||
"github.com/wangjia/pay/internal/model"
|
||||
"github.com/wangjia/pay/internal/providerbuild"
|
||||
"github.com/wangjia/pay/internal/reconcile"
|
||||
"github.com/wangjia/pay/internal/router"
|
||||
"github.com/wangjia/pay/internal/store"
|
||||
"github.com/wangjia/pay/internal/webhook"
|
||||
@@ -54,11 +56,41 @@ func main() {
|
||||
acctReg := accounts.New(config.C.Accounts)
|
||||
pReg := providerbuild.BuildRegistry(acctReg) // 配置驱动:有 enabled 账户才注册对应渠道(P3)
|
||||
// P5 多账户路由:按 config.routing.<channel> 选策略(缺省 round_robin)。
|
||||
// limit_aware 用量数据源 P6 对账就绪前用空源(NopUsage,退化为 round_robin)。
|
||||
acctPicker := accounts.NewRouter(acctReg, config.C.Routing, accounts.NopUsage{})
|
||||
// limit_aware 用量数据源:P6 对账 Runner 周期 Refresh 的真实用量源(替 NopUsage)。
|
||||
usage := reconcile.NewUsageSource(orderStore, time.Now)
|
||||
acctPicker := accounts.NewRouter(acctReg, config.C.Routing, usage)
|
||||
gw := gateway.New(orderStore, refundStore, pReg, acctPicker, productResolver, notifier, "cn")
|
||||
router.SetupV2(r, gw)
|
||||
|
||||
// P6 后台守护 / 对账:订单过期清理 + 用量刷新 + 查单对账收敛 + 已付抽查 +
|
||||
// 退款修复扫描/卡滞告警(P4 T3 review 追加义务,归到本任务一起装配)+
|
||||
// crypto 预留冷启动 Warm + 孤儿扫描(Task 6,AddCryptoJobs)。
|
||||
if config.C.Reconcile.Enabled {
|
||||
rc := config.C.Reconcile
|
||||
runner := reconcile.NewRunner()
|
||||
// 纯本地(DB-only)任务用 AddLocal:会被启动预热 RunOnceLocal 同步跑一遍。
|
||||
runner.AddLocal("order-expire", time.Duration(rc.ExpireEverySec)*time.Second,
|
||||
reconcile.OrderExpirerTask(orderStore, time.Duration(rc.OrderTTLMin)*time.Minute, time.Now))
|
||||
runner.AddLocal("usage-refresh", time.Duration(rc.UsageEverySec)*time.Second,
|
||||
reconcile.RefreshUsageTask(usage))
|
||||
runner.AddLocal("refund-apply-sweep", time.Duration(rc.RefundApplyEverySec)*time.Second,
|
||||
reconcile.RefundApplyTask(orderStore, refundStore, time.Duration(rc.RefundApplyLookbackMin)*time.Minute, time.Now, 200))
|
||||
runner.AddLocal("refund-stuck-alert", time.Duration(rc.RefundApplyEverySec)*time.Second,
|
||||
reconcile.RefundStuckAlertTask(refundStore, time.Duration(rc.RefundStuckWarnMin)*time.Minute, time.Now))
|
||||
// 网络型(出网 HTTP,10-15s 超时)任务用 Add:启动预热不跑,交各自 ticker 首跳。
|
||||
runner.Add("sync-pending", time.Duration(rc.SyncEverySec)*time.Second,
|
||||
reconcile.SyncPendingTask(gw, 100))
|
||||
runner.Add("paid-spotcheck", time.Duration(rc.SpotCheckEverySec)*time.Second,
|
||||
reconcile.PaidSpotCheckTask(orderStore, pReg, time.Duration(rc.SpotCheckWindowMin)*time.Minute, time.Now))
|
||||
orphanStore := store.NewOrphanStore(db)
|
||||
reconcile.AddCryptoJobs(runner, pReg, acctReg, orderStore, orphanStore, rc) // crypto 预留冷启动 Warm(直跑,不受影响)+ 孤儿扫描(网络型,交 ticker 首跳)
|
||||
|
||||
ctx := context.Background()
|
||||
runner.RunOnceLocal(ctx) // 启动预热:只跑本地任务(usage 快照/过期清理/退款自愈立即生效);网络型任务(sync-pending/paid-spotcheck/crypto-orphan-scan)交各自 ticker 首跳,避免上游慢拖住 r.Run(addr) 前的启动
|
||||
runner.Start(ctx)
|
||||
log.Printf("[reconcile] 后台守护已启动(过期清理/用量刷新/查单对账/已付抽查/退款修复扫描/退款卡滞告警/crypto 孤儿扫描)")
|
||||
}
|
||||
|
||||
if config.C.QuerySync.Enabled {
|
||||
orderSvc.StartQuerySync(
|
||||
time.Duration(config.C.QuerySync.IntervalSec)*time.Second,
|
||||
@@ -121,7 +153,7 @@ func autoMigrate(db *gorm.DB) {
|
||||
&model.Order{},
|
||||
&model.NotifyLog{},
|
||||
&model.BizNotifyLog{},
|
||||
&model.OrderV2{}, &model.Attempt{}, &model.Account{}, &model.Refund{}, &model.WebhookDelivery{}, // v2
|
||||
&model.OrderV2{}, &model.Attempt{}, &model.Account{}, &model.Refund{}, &model.WebhookDelivery{}, &model.OrphanPayment{}, // v2
|
||||
); err != nil {
|
||||
log.Fatalf("自动迁移失败: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user