Files
ai-agent/workflow/dao/flow/flow_async_task_dao_test.go
T

95 lines
3.4 KiB
Go

package flow
import (
"context"
"os"
"testing"
"ai-agent/workflow/consts/public"
"gitea.redpowerfuture.com/red-future/common/beans"
"gitea.redpowerfuture.com/red-future/common/db/gfdb"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
)
// resultJSONB 是 JSONB 读回的规范化形式:PG 对 {"taskId":2026} 做 JSONB 归一化后输出
// {"taskId": 2026}(冒号后带空格),直接比较字面量会失配,以实际读回为准。
const resultJSONB = `{"taskId": 2026}`
func TestFlowAsyncTaskDaoRoundTrip(t *testing.T) {
if os.Getenv("AI_AGENT_TEST_DB") != "1" {
t.Skip("skip: AI_AGENT_TEST_DB not set")
}
// gfdb 的 Hook 依赖 ctx 中注入用户信息(租户/创建人),否则 Insert/Select 报 "token 数据为空"
ctx := context.WithValue(context.Background(), "user", &beans.User{
UserName: "test-async", TenantId: 1,
})
const execId, nodeId, seg = 900001, "node-x", 3
// 清理可能残留
if err := FlowAsyncTaskDao.DeleteByKey(ctx, execId, nodeId, seg); err != nil {
t.Fatalf("cleanup: %v", err)
}
if err := FlowAsyncTaskDao.Upsert(ctx, execId, nodeId, seg, 1001, 2026, "model-call-test"); err != nil {
t.Fatalf("upsert: %v", err)
}
rec, err := FlowAsyncTaskDao.Get(ctx, execId, nodeId, seg)
if err != nil || rec == nil {
t.Fatalf("get: %v", err)
}
if rec.TaskId != 2026 || rec.MsgTopic != "model-call-test" || rec.State != FlowAsyncStateInflight {
t.Fatalf("upsert state wrong: %+v", rec)
}
if err := FlowAsyncTaskDao.UpdateByKey(ctx, execId, nodeId, seg, FlowAsyncStateDone, `{"taskId":2026}`); err != nil {
t.Fatalf("update result: %v", err)
}
rec, err = FlowAsyncTaskDao.Get(ctx, execId, nodeId, seg)
if err != nil || rec == nil {
t.Fatalf("get: %v", err)
}
if rec.State != FlowAsyncStateDone || rec.Result != resultJSONB {
t.Fatalf("result not persisted: %+v", rec)
}
// 唯一键 upsert:同 (exec,node,seg) 再次写入应更新而非新建
if err := FlowAsyncTaskDao.Upsert(ctx, execId, nodeId, seg, 1001, 9999, "model-call-test2"); err != nil {
t.Fatalf("re-upsert: %v", err)
}
rec, err = FlowAsyncTaskDao.Get(ctx, execId, nodeId, seg)
if err != nil || rec == nil {
t.Fatalf("get: %v", err)
}
if rec.TaskId != 9999 {
t.Fatalf("re-upsert should update task_id, got %d", rec.TaskId)
}
// OnDuplicate 限定了冲突更新列,已缓存结果不应被覆盖
if rec.Result != resultJSONB {
t.Fatalf("re-upsert should preserve cached result, got %q", rec.Result)
}
// 物理删除验证:DeleteByKey 后 Get 为 nil(软删会留下 deleted_at 行且 Get 仍返回)
if err := FlowAsyncTaskDao.DeleteByKey(ctx, execId, nodeId, seg); err != nil {
t.Fatalf("delete: %v", err)
}
rec, err = FlowAsyncTaskDao.Get(ctx, execId, nodeId, seg)
if err != nil {
t.Fatalf("get after delete: %v", err)
}
if rec != nil {
t.Fatalf("物理删除后不应查到残留: %+v", rec)
}
// DeleteByExecution
if err := FlowAsyncTaskDao.Upsert(ctx, execId, nodeId, seg, 1001, 1, "t"); err != nil {
t.Fatalf("upsert: %v", err)
}
if err := FlowAsyncTaskDao.DeleteByExecution(ctx, execId); err != nil {
t.Fatalf("delete by exec: %v", err)
}
if rec, _ := FlowAsyncTaskDao.Get(ctx, execId, nodeId, seg); rec != nil {
t.Fatalf("DeleteByExecution 后不应查到残留")
}
// 清理表残留(跨测试)
gfdb.DB(ctx, public.DbNameBlackDeacon).Exec(ctx, "DELETE FROM black_deacon_flow_async_task WHERE execution_id = ?", execId)
}