Files
kami_backend/internal/logic/camel_oil/prefetch_order_logs.go
danial 8495c453f3 feat(camel_oil): 添加骆驼模块设置和预拉取订单日志功能
- 增加骆驼模块设置接口支持获取和更新配置
- 使用Redis缓存设置数据,实现模块配置的持久化管理
- 引入预拉取订单日志功能,支持日志的保存和按时间范围查询
- 预拉取订单请求响应数据记录到Redis,方便问题追踪
- 根据模块设置动态调整账号登录、预拉取订单并发数量
- 调整账号登录逻辑以支持配置的并发控制
- 优化预拉取订单补充流程,支持多面额库存管理
- 修正集成API请求函数名及调用,记录详细调用日志数据
- 调整定时任务调度频率,增加预拉取订单补充任务的执行频率
- 升级golang版本到1.25.5,保持开发环境最新状态
2025-12-03 21:17:56 +08:00

165 lines
4.5 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 camel_oil
import (
"context"
"encoding/json"
"fmt"
"time"
v1 "kami/api/camel_oil/v1"
"kami/utility/cache"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime"
)
// GetPrefetchOrderLogs 获取预拉取订单日志
func (s *sCamelOil) GetPrefetchOrderLogs(ctx context.Context, req *v1.GetPrefetchOrderLogsReq) (res *v1.GetPrefetchOrderLogsRes, err error) {
// 计算时间范围跨度
duration := req.EndTime.Time.Sub(req.StartTime.Time)
if duration <= 0 {
return nil, gerror.New("结束时间必须大于开始时间")
}
// 限制查询时间范围不超过24小时
if duration.Hours() > 24 {
return nil, gerror.New("查询时间范围不能超过24小时")
}
glog.Infof(ctx, "获取预拉取订单日志,时间范围: %s - %s", req.StartTime.Format("Y-m-d H:i:s"), req.EndTime.Format("Y-m-d H:i:s"))
// Redis key 前缀
redisKeyPrefix := "camel_oil:prefetch:logs:"
var logs []v1.PrefetchOrderLogItem
// 遍历时间范围内的每一分钟
currentTime := req.StartTime.Time
for currentTime.Before(req.EndTime.Time) || currentTime.Equal(req.EndTime.Time) {
timeKey := currentTime.Format("2006-01-02_15:04")
redisKey := redisKeyPrefix + timeKey
// 从Redis获取日志数据
logData, err := cache.NewCache().Get(ctx, redisKey)
if err != nil {
glog.Warningf(ctx, "获取Redis日志失败key: %s, error: %v", redisKey, err)
currentTime = currentTime.Add(time.Minute)
continue
}
if logData.IsEmpty() {
currentTime = currentTime.Add(time.Minute)
continue
}
// 解析日志数据
var minuteLogs []map[string]interface{}
if err := json.Unmarshal([]byte(logData.String()), &minuteLogs); err != nil {
glog.Warningf(ctx, "解析日志数据失败key: %s, error: %v", redisKey, err)
currentTime = currentTime.Add(time.Minute)
continue
}
// 处理每条日志
for _, log := range minuteLogs {
// 提取面额
amount, ok := log["amount"].(float64)
if !ok {
continue
}
// 提取手机号
phone, ok := log["phone"].(string)
if !ok {
continue
}
// 提取时间戳
timestamp, ok := log["timestamp"].(string)
if !ok {
continue
}
// 提取响应数据
respStr, ok := log["resp_str"].(string)
if !ok {
respStr = ""
}
// 添加到结果列表,直接使用结构化字段
logs = append(logs, v1.PrefetchOrderLogItem{
Timestamp: timestamp,
Phone: phone,
Amount: amount,
ResponseData: respStr,
})
}
currentTime = currentTime.Add(time.Minute)
}
glog.Infof(ctx, "获取到预拉取订单日志 %d 条", len(logs))
// 返回结果
res = &v1.GetPrefetchOrderLogsRes{
Logs: logs,
}
return res, nil
}
// SavePrefetchOrderLog 保存预拉取订单请求日志到Redis
func (s *sCamelOil) SavePrefetchOrderLog(ctx context.Context, phone string, amount float64, respStr string) {
// 构建日志数据
logEntry := map[string]interface{}{
"timestamp": gtime.Now().Format("Y-m-d H:i:s"),
"phone": phone, // 实际使用时应该脱敏处理
"amount": amount,
"resp_str": respStr, // 保存响应数据
}
// 将日志数据序列化为JSON
logData, jsonErr := json.Marshal(logEntry)
if jsonErr != nil {
glog.Errorf(ctx, "序列化预拉取订单日志失败: %v", jsonErr)
return
}
// 生成Redis key (按分钟级别)
now := gtime.Now()
timeKey := now.Format("2006-01-02_15:04")
redisKey := fmt.Sprintf("camel_oil:prefetch:logs:%s", timeKey)
// 获取当前分钟已有的日志
var logs []map[string]interface{}
existingData, cacheErr := cache.NewCache().Get(ctx, redisKey)
if cacheErr == nil && !existingData.IsEmpty() {
if err := json.Unmarshal([]byte(existingData.String()), &logs); err != nil {
// 如果解析失败,创建新的日志数组
logs = []map[string]interface{}{}
}
}
// 添加新的日志
var newLog map[string]interface{}
if err := json.Unmarshal(logData, &newLog); err == nil {
logs = append(logs, newLog)
}
// 重新序列化并保存到Redis设置1小时过期时间
updatedLogData, marshalErr := json.Marshal(logs)
if marshalErr != nil {
glog.Errorf(ctx, "重新序列化日志失败: %v", marshalErr)
return
}
// 使用cache包保存到Redis
if cacheErr := cache.NewCache().Set(ctx, redisKey, string(updatedLogData), time.Hour); cacheErr != nil {
glog.Errorf(ctx, "保存预拉取订单日志到Redis失败: %v", cacheErr)
return
}
// 记录到应用日志
glog.Infof(ctx, "保存预拉取订单日志 - 手机号: %s, 金额: %.2f", phone, amount)
}