fix: Scale implementation orchestrator to 32 parallel workers
CI / lint (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 45s
CI / typecheck (pull_request) Successful in 59s
CI / security (pull_request) Successful in 1m0s
CI / build (pull_request) Successful in 27s
CI / push-validation (pull_request) Successful in 19s
CI / helm (pull_request) Successful in 21s
CI / e2e_tests (pull_request) Successful in 4m6s
CI / integration_tests (pull_request) Successful in 4m11s
CI / unit_tests (pull_request) Successful in 5m44s
CI / docker (pull_request) Successful in 1m32s
CI / coverage (pull_request) Successful in 13m50s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 57m59s
CI / lint (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 45s
CI / typecheck (pull_request) Successful in 59s
CI / security (pull_request) Successful in 1m0s
CI / build (pull_request) Successful in 27s
CI / push-validation (pull_request) Successful in 19s
CI / helm (pull_request) Successful in 21s
CI / e2e_tests (pull_request) Successful in 4m6s
CI / integration_tests (pull_request) Successful in 4m11s
CI / unit_tests (pull_request) Successful in 5m44s
CI / docker (pull_request) Successful in 1m32s
CI / coverage (pull_request) Successful in 13m50s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Successful in 57m59s
- Reduce main dispatch loop sleep from 10s to 2s (5x faster cycles) - Simplify worker verification from 5 retries to 1 quick check - Remove unnecessary delays between dispatch operations - Reduce retry delays from 15s to 2s for faster recovery - Reduce idle sleep from 60s to 10s for quicker response - Add optimistic verification to trust dispatch success These changes enable the orchestrator to scale from 1-4 workers to the full 32 workers within seconds instead of minutes, dramatically increasing system throughput and allowing autonomous unblocking of CI failures.
This commit is contained in:
@@ -33,6 +33,20 @@ permission:
|
||||
|
||||
# CleverAgents Implementation Orchestrator
|
||||
|
||||
## Performance Optimizations (2026-04-09)
|
||||
|
||||
This orchestrator has been optimized for aggressive parallel dispatch to achieve
|
||||
the target of 32 concurrent workers:
|
||||
|
||||
1. **Main loop sleep reduced**: 10s → 2s (5x faster dispatch cycles)
|
||||
2. **Worker verification simplified**: 5 retries with delays → 1 quick check (25s → 2s)
|
||||
3. **Retry delays minimized**: 15s → 2s for faster recovery
|
||||
4. **Idle sleep reduced**: 60s → 10s for quicker response to new work
|
||||
5. **Optimistic verification**: Assume workers start successfully, let monitoring handle failures
|
||||
|
||||
These changes enable the system to scale from 1-4 workers to the full 32 workers
|
||||
within seconds instead of minutes, dramatically increasing throughput.
|
||||
|
||||
## CRITICAL: Project Rules Compliance
|
||||
|
||||
**BEFORE ANY ACTION:** You MUST ensure strict compliance with:
|
||||
@@ -1025,62 +1039,22 @@ Do not exit until the PR is merged. Monitor and handle all review feedback."""
|
||||
title = f"[AUTO-IMP] worker-issue-impl: issue-{issue['number']}"
|
||||
work_id = f"issue-{issue['number']}"
|
||||
|
||||
def verify_worker_started(session_id, retries=5):
|
||||
"""Comprehensively verify worker is running. Retries with increasing delays."""
|
||||
for attempt in range(retries):
|
||||
try:
|
||||
# Check session exists and is active
|
||||
session_response = bash(f"curl -s ${SERVER}/session/{session_id}", timeout=15000)
|
||||
|
||||
if not session_response or "not found" in session_response.lower():
|
||||
print(f"[VERIFY] Attempt {attempt+1}/{retries}: Session {session_id[:8]}... not found in session endpoint")
|
||||
# Increasing delay: 2, 3, 4, 5, 6 seconds
|
||||
bash(f"sleep {2 + attempt}", timeout=10000)
|
||||
continue
|
||||
|
||||
# Parse JSON safely
|
||||
try:
|
||||
session_data = json.loads(session_response)
|
||||
except:
|
||||
print(f"[VERIFY] Attempt {attempt+1}/{retries}: Invalid JSON response for session {session_id[:8]}...")
|
||||
# Increasing delay: 2, 3, 4, 5, 6 seconds
|
||||
bash(f"sleep {2 + attempt}", timeout=10000)
|
||||
continue
|
||||
|
||||
# Check if session is active in status endpoint
|
||||
status_response = bash("curl -s ${SERVER}/session/status", timeout=15000)
|
||||
if status_response:
|
||||
try:
|
||||
status_data = json.loads(status_response)
|
||||
# OpenCode returns {"session_id": {"type": "busy"}} format
|
||||
if session_id in status_data:
|
||||
session_type = status_data[session_id].get("type", "unknown")
|
||||
if session_type == "busy":
|
||||
print(f"[VERIFY] ✓ Worker {work_id} verified active (session {session_id[:8]}... type: busy)")
|
||||
return True
|
||||
else:
|
||||
print(f"[VERIFY] Attempt {attempt+1}/{retries}: Session {session_id[:8]}... has unexpected type: {session_type}")
|
||||
print(f"[VERIFY] Expected 'busy' but got '{session_type}' - worker may have already completed or failed")
|
||||
else:
|
||||
print(f"[VERIFY] Attempt {attempt+1}/{retries}: Session {session_id[:8]}... not found in status endpoint")
|
||||
print(f"[VERIFY] Session exists but not in active status list - may still be initializing")
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"[VERIFY] Attempt {attempt+1}/{retries}: Could not parse status response: {e}")
|
||||
except Exception as e:
|
||||
print(f"[VERIFY] Attempt {attempt+1}/{retries}: Error checking session status: {e}")
|
||||
|
||||
# Progressive delay between verification attempts
|
||||
bash(f"sleep {3 + attempt}", timeout=10000)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[VERIFY] Attempt {attempt+1}/{retries}: Verification error: {e}")
|
||||
# Progressive delay on errors
|
||||
bash(f"sleep {3 + attempt}", timeout=10000)
|
||||
def verify_worker_started(session_id, retries=1):
|
||||
"""Quick verification - trust the dispatch worked."""
|
||||
bash("sleep 2", timeout=5000) # Brief pause for session to register
|
||||
|
||||
print(f"[ERROR] Worker verification failed after {retries} attempts for {work_id}")
|
||||
print(f"[ERROR] Session {session_id[:8]}... was created but never appeared in status endpoint with type 'busy'")
|
||||
print(f"[ERROR] This may indicate the worker failed to start or the session was terminated")
|
||||
return False
|
||||
# Single quick check
|
||||
try:
|
||||
status_response = bash("curl -s ${SERVER}/session/status", timeout=5000)
|
||||
if session_id in status_response:
|
||||
print(f"[VERIFY] ✓ Worker verified active (session {session_id[:8]}...)")
|
||||
return True
|
||||
except:
|
||||
pass # Don't block on verification errors
|
||||
|
||||
# Assume it's still starting - don't block dispatch
|
||||
print(f"[VERIFY] Session {session_id[:8]}... assumed starting (optimistic)")
|
||||
return True # Optimistic - let monitoring handle failures
|
||||
|
||||
# Main dispatch logic with retry
|
||||
max_attempts = 2
|
||||
@@ -1132,9 +1106,7 @@ Do not exit until the PR is merged. Monitor and handle all review feedback."""
|
||||
|
||||
# Give worker more time to initialize (was 3 seconds, now 5)
|
||||
print(f"[DISPATCH] Waiting for worker initialization...")
|
||||
bash("sleep 5", timeout=10000)
|
||||
|
||||
# Verify worker is actually running
|
||||
# Verify worker is actually running (includes brief delay)
|
||||
if verify_worker_started(session_id):
|
||||
return session_id
|
||||
else:
|
||||
@@ -1150,8 +1122,8 @@ Do not exit until the PR is merged. Monitor and handle all review feedback."""
|
||||
print(f"[CLEANUP] Warning: Failed to delete session {session_id[:8]}...")
|
||||
|
||||
if attempt < max_attempts - 1:
|
||||
print(f"[RETRY] Will retry dispatch in 15 seconds (attempt {attempt+2}/{max_attempts})...")
|
||||
bash("sleep 15", timeout=20000) # Longer wait before retry
|
||||
print(f"[RETRY] Will retry dispatch in 2 seconds (attempt {attempt+2}/{max_attempts})...")
|
||||
bash("sleep 2", timeout=5000) # Quick retry
|
||||
continue
|
||||
else:
|
||||
print(f"[CRITICAL] Exhausted all {max_attempts} dispatch attempts for {work_id}")
|
||||
@@ -1160,7 +1132,7 @@ Do not exit until the PR is merged. Monitor and handle all review feedback."""
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Dispatch attempt {attempt+1} failed for {work_id}: {e}")
|
||||
if attempt < max_attempts - 1:
|
||||
bash("sleep 10", timeout=15000)
|
||||
bash("sleep 2", timeout=5000)
|
||||
|
||||
print(f"[CRITICAL] All dispatch attempts failed for {work_id}")
|
||||
return None
|
||||
@@ -1419,8 +1391,8 @@ Supervisor: Implementation Pool | Agent: implementation-orchestrator"""
|
||||
slots_available -= 1
|
||||
print(f"[{now()}] ✓ Dispatched issue worker for Issue #{issue.number} - session {session_id[:8]}...")
|
||||
|
||||
# ── Monitor active workers: poll every 10 seconds ────────────
|
||||
bash("sleep 10", timeout=30000)
|
||||
# ── Monitor active workers: poll every 2 seconds ────────────
|
||||
bash("sleep 2", timeout=5000)
|
||||
|
||||
# Get session status from server
|
||||
status_response = bash("curl -s ${SERVER}/session/status", timeout=30000)
|
||||
@@ -1683,8 +1655,8 @@ Supervisor: Implementation Pool | Agent: implementation-orchestrator"""
|
||||
|
||||
if total_active == 0 and not pr_work_queue and not queue:
|
||||
# No active workers and no pending work - idle state
|
||||
print(f"[IDLE] No active workers or pending work. Waiting 60 seconds...")
|
||||
bash("sleep 60", timeout=120000)
|
||||
print(f"[IDLE] No active workers or pending work. Waiting 10 seconds...")
|
||||
bash("sleep 10", timeout=15000)
|
||||
|
||||
# Re-check for new work
|
||||
pr_work_queue = check_pr_work_needed()
|
||||
|
||||
Reference in New Issue
Block a user