95 lines
3.4 KiB
Go
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)
|
|
}
|