This commit is contained in:
@@ -46,6 +46,9 @@ const (
|
||||
TaskTypeCommission = "commission:calculate" // 分佣计算
|
||||
TaskTypeIotCardImport = "iot_card:import" // IoT 卡批量导入
|
||||
TaskTypeDeviceImport = "device:import" // 设备批量导入
|
||||
TaskTypeExportDispatch = "export:dispatch" // 导出任务分发
|
||||
TaskTypeExportShard = "export:shard" // 导出任务分片执行
|
||||
TaskTypeExportFinalize = "export:finalize" // 导出任务收尾汇总
|
||||
TaskTypeCommissionStatsUpdate = "commission:stats:update" // 佣金统计更新
|
||||
TaskTypeCommissionStatsSync = "commission:stats:sync" // 佣金统计同步
|
||||
TaskTypeCommissionStatsArchive = "commission:stats:archive" // 佣金统计归档
|
||||
@@ -175,6 +178,48 @@ const (
|
||||
DefaultConcurrency = 10
|
||||
)
|
||||
|
||||
// 导出任务相关常量
|
||||
const (
|
||||
ExportTaskSceneDevice = "device" // 导出场景:设备
|
||||
ExportTaskSceneIotCard = "iot_card" // 导出场景:IoT 卡
|
||||
)
|
||||
|
||||
// 导出文件格式常量
|
||||
const (
|
||||
ExportTaskFormatXLSX = "xlsx" // 导出格式:Excel
|
||||
ExportTaskFormatCSV = "csv" // 导出格式:CSV
|
||||
)
|
||||
|
||||
// 导出主任务状态常量
|
||||
const (
|
||||
ExportTaskStatusPending = 1 // 待处理
|
||||
ExportTaskStatusProcessing = 2 // 处理中
|
||||
ExportTaskStatusCompleted = 3 // 已完成
|
||||
ExportTaskStatusFailed = 4 // 已失败
|
||||
ExportTaskStatusCancelled = 5 // 已取消
|
||||
)
|
||||
|
||||
// 导出分片任务状态常量
|
||||
const (
|
||||
ExportShardStatusPending = 1 // 待处理
|
||||
ExportShardStatusProcessing = 2 // 处理中
|
||||
ExportShardStatusSuccess = 3 // 已成功
|
||||
ExportShardStatusFailed = 4 // 已失败
|
||||
ExportShardStatusCancelled = 5 // 已取消
|
||||
)
|
||||
|
||||
// 导出任务执行配置常量
|
||||
const (
|
||||
ExportDefaultShardSize = 2000 // 默认分片大小
|
||||
ExportDownloadURLExpire = 24 * time.Hour // 下载链接固定有效期
|
||||
ExportDispatchTaskTimeout = 10 * time.Minute // dispatch 任务超时
|
||||
ExportShardTaskTimeout = 15 * time.Minute // shard 任务超时
|
||||
ExportFinalizeTaskTimeout = 10 * time.Minute // finalize 任务超时
|
||||
ExportFinalizeRetryMax = 30 // finalize 最大重试次数
|
||||
ExportShardRetryMax = 3 // shard 最大重试次数
|
||||
ExportDispatchRetryMax = 5 // dispatch 最大重试次数
|
||||
)
|
||||
|
||||
// 店铺配置常量
|
||||
const (
|
||||
MaxShopLevel = 7 // 店铺最大层级
|
||||
@@ -260,6 +305,42 @@ func GetShelfStatusName(status int) string {
|
||||
}
|
||||
}
|
||||
|
||||
// GetExportTaskStatusName 获取导出主任务状态名称
|
||||
func GetExportTaskStatusName(status int) string {
|
||||
switch status {
|
||||
case ExportTaskStatusPending:
|
||||
return "待处理"
|
||||
case ExportTaskStatusProcessing:
|
||||
return "处理中"
|
||||
case ExportTaskStatusCompleted:
|
||||
return "已完成"
|
||||
case ExportTaskStatusFailed:
|
||||
return "已失败"
|
||||
case ExportTaskStatusCancelled:
|
||||
return "已取消"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// GetExportShardStatusName 获取导出分片任务状态名称
|
||||
func GetExportShardStatusName(status int) string {
|
||||
switch status {
|
||||
case ExportShardStatusPending:
|
||||
return "待处理"
|
||||
case ExportShardStatusProcessing:
|
||||
return "处理中"
|
||||
case ExportShardStatusSuccess:
|
||||
return "已成功"
|
||||
case ExportShardStatusFailed:
|
||||
return "已失败"
|
||||
case ExportShardStatusCancelled:
|
||||
return "已取消"
|
||||
default:
|
||||
return "未知"
|
||||
}
|
||||
}
|
||||
|
||||
// GetExchangeStatusName 获取换货单状态名称
|
||||
// 用于 exchange_status 字段
|
||||
func GetExchangeStatusName(status int) string {
|
||||
|
||||
@@ -46,6 +46,27 @@ func RedisTaskStatusKey(taskID string) string {
|
||||
return fmt.Sprintf("task:status:%s", taskID)
|
||||
}
|
||||
|
||||
// RedisExportDispatchLockKey 生成导出 dispatch 执行锁的 Redis 键
|
||||
// 用途:防止同一导出任务并发执行 dispatch
|
||||
// 过期时间:5 分钟
|
||||
func RedisExportDispatchLockKey(taskID uint) string {
|
||||
return fmt.Sprintf("export:dispatch:lock:%d", taskID)
|
||||
}
|
||||
|
||||
// RedisExportShardLockKey 生成导出分片执行锁的 Redis 键
|
||||
// 用途:防止同一分片被多个 Worker 并发处理
|
||||
// 过期时间:10 分钟
|
||||
func RedisExportShardLockKey(taskID, shardID uint) string {
|
||||
return fmt.Sprintf("export:shard:lock:%d:%d", taskID, shardID)
|
||||
}
|
||||
|
||||
// RedisExportFinalizeLockKey 生成导出 finalize 执行锁的 Redis 键
|
||||
// 用途:防止同一导出任务并发执行 finalize
|
||||
// 过期时间:2 分钟
|
||||
func RedisExportFinalizeLockKey(taskID uint) string {
|
||||
return fmt.Sprintf("export:finalize:lock:%d", taskID)
|
||||
}
|
||||
|
||||
// RedisShopSubordinatesKey 生成店铺下级 ID 列表的 Redis 键
|
||||
// 用途:缓存递归查询的下级店铺 ID 列表
|
||||
// 过期时间:30 分钟
|
||||
|
||||
@@ -36,6 +36,7 @@ func BuildDocHandlers() *bootstrap.Handlers {
|
||||
Authorization: admin.NewAuthorizationHandler(nil),
|
||||
IotCard: admin.NewIotCardHandler(nil),
|
||||
IotCardImport: admin.NewIotCardImportHandler(nil),
|
||||
ExportTask: admin.NewExportTaskHandler(nil),
|
||||
Device: admin.NewDeviceHandler(nil),
|
||||
DeviceImport: admin.NewDeviceImportHandler(nil),
|
||||
AssetAllocationRecord: admin.NewAssetAllocationRecordHandler(nil),
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/exporter"
|
||||
"github.com/break/junhong_cmp_fiber/internal/gateway"
|
||||
"github.com/break/junhong_cmp_fiber/internal/polling"
|
||||
iot_card_svc "github.com/break/junhong_cmp_fiber/internal/service/iot_card"
|
||||
@@ -64,6 +65,7 @@ func (h *Handler) RegisterHandlers() *asynq.ServeMux {
|
||||
|
||||
h.registerIotCardImportHandler()
|
||||
h.registerDeviceImportHandler()
|
||||
h.registerExportHandlers()
|
||||
h.registerCommissionStatsHandlers()
|
||||
h.registerCommissionCalculationHandler()
|
||||
h.registerPollingHandlers()
|
||||
@@ -113,6 +115,46 @@ func (h *Handler) registerDeviceImportHandler() {
|
||||
h.logger.Info("注册设备导入任务处理器", zap.String("task_type", constants.TaskTypeDeviceImport))
|
||||
}
|
||||
|
||||
func (h *Handler) registerExportHandlers() {
|
||||
sceneRegistry := exporter.NewDefaultRegistry(h.db)
|
||||
|
||||
dispatchHandler := task.NewExportDispatchHandler(
|
||||
h.db,
|
||||
h.redis,
|
||||
h.workerResult.Stores.ExportTask,
|
||||
h.workerResult.Stores.ExportShardTask,
|
||||
h.asynqClient,
|
||||
sceneRegistry,
|
||||
h.logger,
|
||||
)
|
||||
shardHandler := task.NewExportShardHandler(
|
||||
h.redis,
|
||||
h.workerResult.Stores.ExportTask,
|
||||
h.workerResult.Stores.ExportShardTask,
|
||||
h.asynqClient,
|
||||
h.storage,
|
||||
sceneRegistry,
|
||||
h.logger,
|
||||
)
|
||||
finalizeHandler := task.NewExportFinalizeHandler(
|
||||
h.redis,
|
||||
h.workerResult.Stores.ExportTask,
|
||||
h.workerResult.Stores.ExportShardTask,
|
||||
h.storage,
|
||||
sceneRegistry,
|
||||
h.logger,
|
||||
)
|
||||
|
||||
h.mux.HandleFunc(constants.TaskTypeExportDispatch, dispatchHandler.HandleExportDispatch)
|
||||
h.logger.Info("注册导出 dispatch 任务处理器", zap.String("task_type", constants.TaskTypeExportDispatch))
|
||||
|
||||
h.mux.HandleFunc(constants.TaskTypeExportShard, shardHandler.HandleExportShard)
|
||||
h.logger.Info("注册导出 shard 任务处理器", zap.String("task_type", constants.TaskTypeExportShard))
|
||||
|
||||
h.mux.HandleFunc(constants.TaskTypeExportFinalize, finalizeHandler.HandleExportFinalize)
|
||||
h.logger.Info("注册导出 finalize 任务处理器", zap.String("task_type", constants.TaskTypeExportFinalize))
|
||||
}
|
||||
|
||||
func (h *Handler) registerCommissionStatsHandlers() {
|
||||
updateHandler := task.NewCommissionStatsUpdateHandler(
|
||||
h.redis,
|
||||
|
||||
@@ -22,6 +22,8 @@ type WorkerStores struct {
|
||||
IotCardImportTask *postgres.IotCardImportTaskStore
|
||||
IotCard *postgres.IotCardStore
|
||||
DeviceImportTask *postgres.DeviceImportTaskStore
|
||||
ExportTask *postgres.ExportTaskStore
|
||||
ExportShardTask *postgres.ExportShardTaskStore
|
||||
Device *postgres.DeviceStore
|
||||
DeviceSimBinding *postgres.DeviceSimBindingStore
|
||||
ShopSeriesCommissionStats *postgres.ShopSeriesCommissionStatsStore
|
||||
|
||||
Reference in New Issue
Block a user