fix(engine): resolve parallel execution races and improve max steps semantics

- Fix data race in runParallelBranches where first error could be masked
- Improve MaxSteps to allow exactly N steps
- Consolidate Resume validation logic and fix silent overwrite in Graph AddNode/AddEdge
- Add sync.RWMutex to Engine for thread-safe configuration
- Fix P2 issues: Add immediate check for router output, add mutex to hooks example, add context timeout to translation example, and update docs for Checkpointer.Delete
This commit is contained in:
unclesam committed 2026-07-04 20:46:36 +08:00
1 parent d2d8eb5a3a
commit 5782504351
10 files changed
+287 -47

No files matched your search

+10 -2
View File
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
"sync"
"time"
GopherGraph "github.com/unclesam-ly/GopherGraph"
@@ -82,7 +83,10 @@ func main() {
// ============================================================
// 使用 Engine 包装器,挂载所有增强能力
// ============================================================
var nodeTimings = make(map[string]time.Time)
var (
nodeTimings = make(map[string]time.Time)
nodeTimingsMu sync.Mutex
)
engine := GopherGraph.NewEngine(cg).
// 1. 注册深拷贝函数,消除并发分支对 Messages 切片的数据竞争
@@ -91,13 +95,17 @@ func main() {
WithMaxSteps(50).
// 3. Pre Hook:记录节点开始时间 + 向控制台推送"流式进度"
WithPreNodeHook(func(ctx context.Context, name string, s AgentState) {
nodeTimingsMu.Lock()
nodeTimings[name] = time.Now()
nodeTimingsMu.Unlock()
fmt.Printf(" ⏳ [PRE ] %-15s | 消息数: %d\n", name, len(s.Messages))
}).
// 4. Post Hook:计算并打印节点耗时
WithPostNodeHook(func(ctx context.Context, name string, s AgentState) {
nodeTimingsMu.Lock()
elapsed := time.Since(nodeTimings[name])
fmt.Printf(" ✅ [POST] %-15s | 耗时: %v | 消息数: %d\n", name, elapsed.Round(time.Millisecond), len(s.Messages))
nodeTimingsMu.Unlock()
fmt.Printf(" [POST] %-15s | 耗时: %v | 消息数: %d\n", name, elapsed.Round(time.Millisecond), len(s.Messages))
})
fmt.Println("🚀 启动工作流...")
+3 -1
View File
@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"strings"
"time"
GopherGraph "github.com/unclesam-ly/GopherGraph"
)
@@ -122,7 +123,8 @@ func main() {
// 包含敏感词“秘密”,会触发人工审核中断:
inputText := "这是一个秘密你好"
fmt.Printf("🚀 启动工作流,输入原文: %q\n", inputText)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
thread, err := cg.Start(ctx, "translator", TranslationState{InputText: inputText})
if err != nil {
fmt.Printf("运行失败: %v\n", err)