Summary
Ersetze den 50ms-Polling-Dispatcher durch einen event-driven Channel-basierten Dispatcher. Wenn ein Task fertig ist, werden sofort (innerhalb von Mikrosekunden, nicht 50ms) alle abhängigen Tasks geprüft und gestartet.
Ist-Stand
cmd/sin-code/internal/orchestrator/dispatcher.go:72-77:
// AKTUELL: 50ms Polling
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(50 * time.Millisecond): // ← WARTET 50ms bevor er erneut prüft
}
continue
Bei 10 Tasks in einer DAG mit 4 Ebenen = 400ms reine Polling-Latenz. Bei 50 Tasks = 2 Sekunden Verschwendung.
SOLL-Stand: Event-Driven
// NEU: Channel-basiert, sofortige Reaktion
notifyCh := make(chan string, len(tasks)) // Task ID bei completion
go func() {
// Task läuft...
notifyCh <- task.ID // ← SOFORT bei completion
}()
for {
select {
case completedID := <-notifyCh:
// SOFORT ready tasks prüfen und starten
readyTasks := findReadyTasks(completedID)
for _, t := range readyTasks {
go launchTask(t, notifyCh)
}
case <-ctx.Done():
return ctx.Err()
}
}
Research-Daten
Go Concurrency Best Practices
- Channels sind der idiomatic Go way für event-driven systems
sync.WaitGroup für completion tracking
context.Context für cancellation propagation
- Race-free (M7): mutex auf shared state, channels für communication
LangGraph Event System
- Jeder Node feuert Events bei State-Änderung
- Conditional edges reagieren sofort auf Node-Completion
- Kein Polling — reine Event-Driven Architecture
Codex CLI (Rust)
- WebSocket-basiert für real-time updates
- PostToolUse hooks feuern bei Tool-Completion
- Smart Approvals: auto-approve feuert sofort wenn Conditions met
Requirements
- NotifyChannel — Jeder Task sendet
taskID auf completion
- Instant Ready-Check — Bei jedem completion-Event: sofort ready dependents prüfen
- Backpressure —
MaxParallel Semaphore bleibt, aber ohne polling
- Graceful Shutdown —
ctx.Done() bricht alle laufenden Tasks ab
- Progress Events —
task.started, task.completed, task.failed Events für TUI Dashboard
Technische Umsetzung
internal/orchestrator/event_dispatch.go (neu) — ersetzt polling loop
- Channel:
chan TaskEvent mit buffer = len(tasks)
TaskEvent{Type: "completed"|"failed", TaskID: string, Result: string}
- Integration mit hooks system:
task.complete, task.abort events
- TUI Dashboard: subscribes auf TaskEvents für live updates
Benchmark-Ziele
- Task-to-Task Latenz: <1ms (aktuell 50ms)
- 10-Task DAG 4-Ebenen: <50ms dispatch overhead (aktuell ~400ms)
- 50-Task DAG: <200ms dispatch overhead (aktuell ~2s)
Referenzen
Summary
Ersetze den 50ms-Polling-Dispatcher durch einen event-driven Channel-basierten Dispatcher. Wenn ein Task fertig ist, werden sofort (innerhalb von Mikrosekunden, nicht 50ms) alle abhängigen Tasks geprüft und gestartet.
Ist-Stand
cmd/sin-code/internal/orchestrator/dispatcher.go:72-77:Bei 10 Tasks in einer DAG mit 4 Ebenen = 400ms reine Polling-Latenz. Bei 50 Tasks = 2 Sekunden Verschwendung.
SOLL-Stand: Event-Driven
Research-Daten
Go Concurrency Best Practices
sync.WaitGroupfür completion trackingcontext.Contextfür cancellation propagationLangGraph Event System
Codex CLI (Rust)
Requirements
taskIDauf completionMaxParallelSemaphore bleibt, aber ohne pollingctx.Done()bricht alle laufenden Tasks abtask.started,task.completed,task.failedEvents für TUI DashboardTechnische Umsetzung
internal/orchestrator/event_dispatch.go(neu) — ersetzt polling loopchan TaskEventmit buffer = len(tasks)TaskEvent{Type: "completed"|"failed", TaskID: string, Result: string}task.complete,task.aborteventsBenchmark-Ziele
Referenzen