Version: 0.7.2.dev.260322
feat(schedule-plan): ✨ 重构智能排程链路并修复粗排双节对齐问题 - ✨ 新增“对话级排程状态持久化”能力:引入 `agent_schedule_states` 模型/DAO,并接入启动迁移 - ✨ 智能排程图升级:补齐小幅微调(quick refine)分支,完善预算/并发/状态字段流转 - ✨ 预览链路增强:完善排程预览服务读写与桥接逻辑,新增本地预览页 `infra/schedule_preview_viewer.html` - ♻️ 缓存治理统一:将相关缓存处理收口到 DAO + `cache_deleter` 联动清理,移除旧散落逻辑 - 🐛 修复粗排核心 bug:禁止单节降级,强制双节并按 `1-2/3-4/...` 对齐;修复结束日扫描边界问题 - ✅ 新增粗排回归测试:覆盖孤立单节、偶数起点双节、Filler 对齐等关键场景
This commit is contained in:
@@ -7,7 +7,6 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/LoveLosita/smartflow/backend/model"
|
||||
"github.com/cloudwego/eino/schema"
|
||||
"github.com/go-redis/redis/v8"
|
||||
)
|
||||
@@ -41,10 +40,6 @@ func (m *AgentCache) historyWindowKey(sessionID string) string {
|
||||
return fmt.Sprintf("smartflow:history_window:%s", sessionID)
|
||||
}
|
||||
|
||||
func (m *AgentCache) schedulePreviewKey(userID int, sessionID string) string {
|
||||
return fmt.Sprintf("smartflow:schedule_preview:u:%d:c:%s", userID, sessionID)
|
||||
}
|
||||
|
||||
func (m *AgentCache) normalizeWindowSize(size int) int {
|
||||
if size < minHistoryWindowSize {
|
||||
return minHistoryWindowSize
|
||||
@@ -193,55 +188,3 @@ func (m *AgentCache) DeleteConversationStatus(ctx context.Context, sessionID str
|
||||
key := fmt.Sprintf("smartflow:conversation_status:%s", sessionID)
|
||||
return m.client.Del(ctx, key).Err()
|
||||
}
|
||||
|
||||
// SetSchedulePlanPreview 写入“排程预览”缓存。
|
||||
//
|
||||
// 步骤化说明:
|
||||
// 1. 先把结构化预览序列化成 JSON,避免缓存层结构漂移。
|
||||
// 2. 再按 user_id + conversation_id 写入,确保用户间数据隔离。
|
||||
// 3. 最后带 TTL 写入,保证预览是短期临时态而非长期状态。
|
||||
//
|
||||
// 失败处理:
|
||||
// 1. preview 为空时直接返回错误,避免写入无意义空值。
|
||||
// 2. 序列化失败或 Redis 写入失败都返回 error,由上层决定是否降级。
|
||||
func (m *AgentCache) SetSchedulePlanPreview(ctx context.Context, userID int, sessionID string, preview *model.SchedulePlanPreviewCache) error {
|
||||
if preview == nil {
|
||||
return fmt.Errorf("schedule preview is nil")
|
||||
}
|
||||
data, err := json.Marshal(preview)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal schedule preview failed: %w", err)
|
||||
}
|
||||
return m.client.Set(ctx, m.schedulePreviewKey(userID, sessionID), data, m.expiration).Err()
|
||||
}
|
||||
|
||||
// GetSchedulePlanPreview 读取“排程预览”缓存。
|
||||
//
|
||||
// 语义约定:
|
||||
// 1. 未命中返回 (nil, nil),上层可区分“未生成”与“已过期”。
|
||||
// 2. 反序列化失败返回 error,避免把脏缓存当成正常结果。
|
||||
// 3. 不做 DB 回源,预览缓存失效后由业务侧重新生成。
|
||||
func (m *AgentCache) GetSchedulePlanPreview(ctx context.Context, userID int, sessionID string) (*model.SchedulePlanPreviewCache, error) {
|
||||
raw, err := m.client.Get(ctx, m.schedulePreviewKey(userID, sessionID)).Result()
|
||||
if err == redis.Nil {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var preview model.SchedulePlanPreviewCache
|
||||
if err = json.Unmarshal([]byte(raw), &preview); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal schedule preview failed: %w", err)
|
||||
}
|
||||
return &preview, nil
|
||||
}
|
||||
|
||||
// DeleteSchedulePlanPreview 删除“排程预览”缓存。
|
||||
//
|
||||
// 说明:
|
||||
// 1. 删除是幂等操作,key 不存在也视为成功。
|
||||
// 2. 用于新一轮排程前清理旧快照,避免前端读到过期结果。
|
||||
func (m *AgentCache) DeleteSchedulePlanPreview(ctx context.Context, userID int, sessionID string) error {
|
||||
return m.client.Del(ctx, m.schedulePreviewKey(userID, sessionID)).Err()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user