暂存一下,防止丢失

This commit is contained in:
2026-07-24 16:07:18 +08:00
parent 5d6e23f1a5
commit a18ed8bc8d
180 changed files with 13597 additions and 1986 deletions

View File

@@ -14,9 +14,14 @@ import (
"github.com/redis/go-redis/v9"
"go.uber.org/zap"
notificationApp "github.com/break/junhong_cmp_fiber/internal/application/notification"
"github.com/break/junhong_cmp_fiber/internal/bootstrap"
"github.com/break/junhong_cmp_fiber/internal/gateway"
cardObservationInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/cardobservation"
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
notificationInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/notification"
shopInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/shop"
walletInfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/wallet"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/break/junhong_cmp_fiber/internal/polling"
iot_card_svc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
@@ -274,7 +279,7 @@ func initWorkerRuntime(ctx context.Context, cfg *config.Config, appLogger *zap.L
stopResumeSvc.SetPollingCallback(lifecycleSvc)
}
return &workerRuntime{
runtime := &workerRuntime{
redisAddr: redisAddr,
redisClient: redisClient,
db: db,
@@ -291,6 +296,85 @@ func initWorkerRuntime(ctx context.Context, cfg *config.Config, appLogger *zap.L
pollingBase: pollingBase,
lifecycleSvc: lifecycleSvc,
}
registerNotificationOutboxConsumer(runtime, appLogger)
registerWalletOutboxConsumer(runtime, appLogger)
registerCardObservationOutboxConsumer(runtime, appLogger)
return runtime
}
// registerCardObservationOutboxConsumer 注册卡观测领域事件消费者。
func registerCardObservationOutboxConsumer(runtime *workerRuntime, appLogger *zap.Logger) {
stopResumeService, _ := runtime.workerResult.Services.StopResumeService.(iot_card_svc.StopResumeServiceInterface)
consumer := cardObservationInfra.NewRealnameChangedConsumer(
runtime.db,
runtime.workerResult.Services.ActivationService,
runtime.workerResult.Stores.DeviceSimBinding,
stopResumeService,
)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeCardRealnameChanged, consumer); err != nil {
appLogger.Fatal("注册卡实名状态变化 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeCardRealnameChanged), zap.Error(err))
}
trafficConsumer := cardObservationInfra.NewTrafficIncrementedConsumer(
runtime.db,
runtime.redisClient,
runtime.workerResult.Services.UsageService,
stopResumeService,
)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeCardTrafficIncremented, trafficConsumer); err != nil {
appLogger.Fatal("注册卡流量正增量 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeCardTrafficIncremented), zap.Error(err))
}
networkConsumer := cardObservationInfra.NewNetworkChangedConsumer(runtime.db, stopResumeService)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeCardNetworkChanged, networkConsumer); err != nil {
appLogger.Fatal("注册卡网络状态变化 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeCardNetworkChanged), zap.Error(err))
}
}
// registerWalletOutboxConsumer 注册代理主钱包资金事实消费者。
func registerWalletOutboxConsumer(runtime *workerRuntime, appLogger *zap.Logger) {
debitConsumer := walletInfra.NewDebitEventConsumer(runtime.db)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeAgentMainWalletDebited, debitConsumer); err != nil {
appLogger.Fatal("注册代理主钱包扣款 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeAgentMainWalletDebited), zap.Error(err))
}
reservationConsumer := walletInfra.NewReservationEventConsumer(runtime.db)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeAgentMainWalletReservationChanged, reservationConsumer); err != nil {
appLogger.Fatal("注册代理主钱包预占 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeAgentMainWalletReservationChanged), zap.Error(err))
}
creditConsumer := walletInfra.NewCreditEventConsumer(runtime.db)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeAgentMainWalletCredited, creditConsumer); err != nil {
appLogger.Fatal("注册代理主钱包入账 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeAgentMainWalletCredited), zap.Error(err))
}
refundConsumer := walletInfra.NewRefundEventConsumer(runtime.db)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeAgentMainWalletRefunded, refundConsumer); err != nil {
appLogger.Fatal("注册代理主钱包退款 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeAgentMainWalletRefunded), zap.Error(err))
}
}
// registerNotificationOutboxConsumer 注册明确、动态后台账号和个人客户通知的稳定 Outbox 消费者。
func registerNotificationOutboxConsumer(runtime *workerRuntime, appLogger *zap.Logger) {
repository := notificationInfra.NewRepository(runtime.db)
registry := notificationInfra.NewRegistry()
shopRecipientResolver := shopInfra.NewRecipientResolver(runtime.db)
dynamicRecipientResolver := notificationInfra.NewDynamicRecipientResolver(runtime.db, shopRecipientResolver)
consumer := notificationApp.NewDeliveryService(repository, registry, dynamicRecipientResolver, appLogger)
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeAdminDirectNotification, consumer); err != nil {
appLogger.Fatal("注册站内通知 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeAdminDirectNotification), zap.Error(err))
}
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypePersonalCustomerDirectNotification, consumer); err != nil {
appLogger.Fatal("注册个人客户站内通知 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypePersonalCustomerDirectNotification), zap.Error(err))
}
if err := runtime.outboxConsumers.Register(constants.OutboxEventTypeAdminDynamicNotification, consumer); err != nil {
appLogger.Fatal("注册后台动态接收人站内通知 Outbox 消费者失败",
zap.String("event_type", constants.OutboxEventTypeAdminDynamicNotification), zap.Error(err))
}
}
// close 在 Worker 退出时关闭共享客户端与数据库连接。
@@ -394,7 +478,7 @@ func startPollingScheduler(
appLogger,
)
// 注入套餐失效前流量同步器:最小化 iot_card.Service只需 gateway + store + redis + 流量扣减)
// 注入套餐失效前流量同步器:复用公共卡观测写入,不在旧 Service 内重复扣减套餐。
trafficSyncer := iot_card_svc.New(
runtime.db,
runtime.pollingIotCardStore,
@@ -404,7 +488,7 @@ func startPollingScheduler(
nil,
)
trafficSyncer.SetRedisClient(runtime.redisClient)
trafficSyncer.SetDataDeductor(runtime.workerResult.Services.UsageService)
trafficSyncer.SetCardObservationService(runtime.workerResult.Services.CardObservation)
activationHandler.SetTrafficSyncer(trafficSyncer)
pollingScheduler := polling.NewScheduler(
@@ -447,7 +531,7 @@ func startAsynqScheduler(cfg *config.Config, redisAddr string, appLogger *zap.Lo
}
}()
appLogger.Info("Asynq Scheduler 已启动(订单超时: @every 1m, 告警检查: @every 1m, 数据清理: 0 2 * * *, 每日流量落盘: 0 2 * * *")
appLogger.Info("Asynq Scheduler 已启动(订单超时: @every 1m, 告警检查: @every 1m, 数据清理: 0 2 * * *, 通知清理: 15 2 * * *, 每日流量落盘: 0 2 * * *")
return asynqScheduler
}
@@ -474,6 +558,14 @@ func registerAsynqScheduleTasks(asynqScheduler *asynq.Scheduler) error {
)); err != nil {
return fmt.Errorf("注册数据清理定时任务失败: %w", err)
}
if _, err := asynqScheduler.Register("15 2 * * *", asynq.NewTask(
constants.TaskTypeNotificationCleanup,
nil,
asynq.MaxRetry(3),
asynq.Queue(constants.QueueForTaskType(constants.TaskTypeNotificationCleanup)),
)); err != nil {
return fmt.Errorf("注册站内通知保留清理定时任务失败: %w", err)
}
if _, err := asynqScheduler.Register(
"0 2 * * *",
asynq.NewTask(