diff options
| author | soryu <soryu@soryu.co> | 2026-01-23 03:42:18 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-01-23 03:42:18 +0000 |
| commit | ad55b3b00ebbfd8023897d0f4bfffa9be438b9f2 (patch) | |
| tree | 8dbefc358bdeab6fd0c4a746c802314b7dfca332 /makima/src | |
| parent | 3230c8b729101ce227e10efcb181fafe83fc8d0a (diff) | |
| download | soryu-ad55b3b00ebbfd8023897d0f4bfffa9be438b9f2.tar.gz soryu-ad55b3b00ebbfd8023897d0f4bfffa9be438b9f2.zip | |
feat: Add client-side polling for CLI wait commandmakima/task-task-5c27b152-5c27b152
When contracts wait for tasks in makima, the CLI now polls and returns
once the task has changed state. This provides resilient task status
detection even if:
- Server's broadcast channels miss a notification
- Network connections are intermittent
- Long-polling HTTP requests timeout at load balancers
The implementation uses a hybrid approach:
1. First tries server-side wait with short timeout (30s)
2. Falls back to polling via supervisor_get_task endpoint
3. Configurable poll_interval (default 5s) via --poll-interval flag
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/src')
| -rw-r--r-- | makima/src/bin/makima.rs | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/makima/src/bin/makima.rs b/makima/src/bin/makima.rs index 67eefc6..e12463d 100644 --- a/makima/src/bin/makima.rs +++ b/makima/src/bin/makima.rs @@ -283,11 +283,62 @@ async fn run_supervisor( SupervisorCommand::Wait(args) => { let client = ApiClient::new(args.common.api_url, args.common.api_key)?; eprintln!( - "Waiting for task {} (timeout: {}s)...", - args.task_id, args.timeout + "Waiting for task {} (timeout: {}s, poll interval: {}s)...", + args.task_id, args.timeout, args.poll_interval ); - let result = client.supervisor_wait(args.task_id, args.timeout).await?; - println!("{}", serde_json::to_string(&result.0)?); + + let start_time = std::time::Instant::now(); + let timeout_duration = std::time::Duration::from_secs(args.timeout as u64); + let poll_interval = std::time::Duration::from_secs(args.poll_interval); + let server_wait_timeout = 30i32; // Short timeout for server-side wait + + loop { + // Check if we've exceeded the total timeout + let remaining = timeout_duration.saturating_sub(start_time.elapsed()); + if remaining.is_zero() { + eprintln!("Timeout reached after {}s", args.timeout); + let result = client.supervisor_get_task(args.task_id).await?; + println!("{}", serde_json::to_string(&result.0)?); + break; + } + + // Try server-side wait with short timeout + let wait_timeout = std::cmp::min(server_wait_timeout, remaining.as_secs() as i32); + + match client.supervisor_wait(args.task_id, wait_timeout).await { + Ok(result) => { + if let Some(completed) = result.0.get("completed").and_then(|c| c.as_bool()) { + if completed { + println!("{}", serde_json::to_string(&result.0)?); + break; + } + } + // Not completed yet, continue loop + eprintln!("Task still running (elapsed: {:?})", start_time.elapsed()); + } + Err(e) => { + eprintln!("Warning: Server wait failed: {}. Falling back to polling...", e); + // Fall back to simple status poll + if let Ok(result) = client.supervisor_get_task(args.task_id).await { + if let Some(status) = result.0.get("status").and_then(|s| s.as_str()) { + if status == "done" || status == "failed" || status == "merged" { + let wait_response = serde_json::json!({ + "taskId": args.task_id, + "status": status, + "completed": true, + "outputSummary": result.0.get("progressSummary") + }); + println!("{}", serde_json::to_string(&wait_response)?); + break; + } + } + } + } + } + + // Small delay before retrying + tokio::time::sleep(poll_interval).await; + } } SupervisorCommand::ReadFile(args) => { let client = ApiClient::new(args.common.api_url, args.common.api_key)?; |
