Skip to content

feat(orchestrator): Event-Driven DAG Dispatcher — 50ms Polling → Channel-basierte sofortige Ausführung #283

@Delqhi

Description

@Delqhi

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

  1. NotifyChannel — Jeder Task sendet taskID auf completion
  2. Instant Ready-Check — Bei jedem completion-Event: sofort ready dependents prüfen
  3. BackpressureMaxParallel Semaphore bleibt, aber ohne polling
  4. Graceful Shutdownctx.Done() bricht alle laufenden Tasks ab
  5. Progress Eventstask.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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestloop-systemAgent loop core: budget, gates, delegation

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions