summaryrefslogtreecommitdiff
path: root/makima/src/bin/makima.rs
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-23 03:42:18 +0000
committersoryu <soryu@soryu.co>2026-01-23 03:42:18 +0000
commitad55b3b00ebbfd8023897d0f4bfffa9be438b9f2 (patch)
tree8dbefc358bdeab6fd0c4a746c802314b7dfca332 /makima/src/bin/makima.rs
parent3230c8b729101ce227e10efcb181fafe83fc8d0a (diff)
downloadsoryu-makima/task-task-5c27b152-5c27b152.tar.gz
soryu-makima/task-task-5c27b152-5c27b152.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/bin/makima.rs')
-rw-r--r--makima/src/bin/makima.rs59
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)?;