Legg til retry med backoff for Claude API-feil (500/529)
Maskinrommet prøver nå opptil 3 ganger med eksponentiell backoff (2, 4, 8 sek) ved 500/529-feil fra Anthropic. Etter alle forsøk vises en vennlig melding i chatten i stedet for rå feilmeldinger. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d4715831bf
commit
244da69110
1 changed files with 50 additions and 21 deletions
|
|
@ -155,35 +155,64 @@ Svar KUN med meldingsteksten.
|
||||||
{conversation}--- Svar ---"#
|
{conversation}--- Svar ---"#
|
||||||
);
|
);
|
||||||
|
|
||||||
// Kall claude CLI direkte
|
// Kall claude CLI med retry ved API-feil (500/529)
|
||||||
let claude_path = std::env::var("CLAUDE_PATH").unwrap_or_else(|_| "claude".to_string());
|
let claude_path = std::env::var("CLAUDE_PATH").unwrap_or_else(|_| "claude".to_string());
|
||||||
let project_dir = std::env::var("PROJECT_DIR").unwrap_or_else(|_| "/home/vegard/synops".to_string());
|
let project_dir = std::env::var("PROJECT_DIR").unwrap_or_else(|_| "/home/vegard/synops".to_string());
|
||||||
|
|
||||||
tracing::info!(prompt_len = prompt.len(), "Kaller claude CLI");
|
tracing::info!(prompt_len = prompt.len(), "Kaller claude CLI");
|
||||||
|
|
||||||
let output = tokio::process::Command::new(&claude_path)
|
let max_retries = 3u32;
|
||||||
.arg("-p")
|
let mut response_text = String::new();
|
||||||
.arg(&prompt)
|
|
||||||
.arg("--output-format")
|
|
||||||
.arg("json")
|
|
||||||
.arg("--dangerously-skip-permissions")
|
|
||||||
.env("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC", "1")
|
|
||||||
.current_dir(&project_dir)
|
|
||||||
.output()
|
|
||||||
.await
|
|
||||||
.map_err(|e| format!("Kunne ikke starte claude: {e}"))?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
for attempt in 0..=max_retries {
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
let output = tokio::process::Command::new(&claude_path)
|
||||||
return Err(format!("claude feilet ({}): {}", output.status, &stderr[..stderr.len().min(500)]));
|
.arg("-p")
|
||||||
|
.arg(&prompt)
|
||||||
|
.arg("--output-format")
|
||||||
|
.arg("json")
|
||||||
|
.arg("--dangerously-skip-permissions")
|
||||||
|
.env("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC", "1")
|
||||||
|
.current_dir(&project_dir)
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.map_err(|e| format!("Kunne ikke starte claude: {e}"))?;
|
||||||
|
|
||||||
|
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
|
|
||||||
|
// Sjekk om dette er en retrybar API-feil (500/529)
|
||||||
|
let is_api_error = !output.status.success()
|
||||||
|
&& (stderr.contains("500") || stderr.contains("529")
|
||||||
|
|| stderr.contains("overloaded") || stderr.contains("Internal Server Error"));
|
||||||
|
|
||||||
|
if is_api_error && attempt < max_retries {
|
||||||
|
let delay = std::time::Duration::from_secs(2u64.pow(attempt + 1)); // 2, 4, 8 sek
|
||||||
|
tracing::warn!(
|
||||||
|
attempt = attempt + 1,
|
||||||
|
delay_secs = delay.as_secs(),
|
||||||
|
"Claude API-feil, prøver igjen"
|
||||||
|
);
|
||||||
|
tokio::time::sleep(delay).await;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
if is_api_error {
|
||||||
|
// Alle retries brukt opp — gi vennlig melding i stedet for rå feil
|
||||||
|
tracing::error!(attempts = max_retries + 1, "Claude API utilgjengelig etter alle forsøk");
|
||||||
|
response_text = "Beklager, jeg er midlertidig utilgjengelig — Anthropic sitt API svarer ikke akkurat nå. Prøv igjen om litt.".to_string();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Err(format!("claude feilet ({}): {}", output.status, &stderr[..stderr.len().min(500)]));
|
||||||
|
}
|
||||||
|
|
||||||
|
response_text = match serde_json::from_str::<serde_json::Value>(&stdout) {
|
||||||
|
Ok(json) => json["result"].as_str().unwrap_or("").to_string(),
|
||||||
|
Err(_) => stdout.trim().to_string(),
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
||||||
let response_text = match serde_json::from_str::<serde_json::Value>(&stdout) {
|
|
||||||
Ok(json) => json["result"].as_str().unwrap_or("").to_string(),
|
|
||||||
Err(_) => stdout.trim().to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if response_text.is_empty() {
|
if response_text.is_empty() {
|
||||||
return Err("Tom respons fra claude".to_string());
|
return Err("Tom respons fra claude".to_string());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue