detect rate-limit errors; park serve loop instead of crashing

This commit is contained in:
damocles 2026-05-20 12:54:07 +02:00
parent 6f7cc6e77d
commit 03db764101
3 changed files with 98 additions and 7 deletions

View file

@ -222,6 +222,21 @@ async fn serve(
if matches!(outcome, turn::TurnOutcome::Ok) {
ack_turn(socket).await;
}
// Rate-limited: park until the quota resets, then requeue
// the unacked message so it resurfaces in the same session.
if matches!(outcome, turn::TurnOutcome::RateLimited) {
let secs = turn::rate_limit_sleep_secs();
bus.emit_status("rate_limited");
bus.emit(LiveEvent::Note {
text: format!(
"API rate-limited — sleeping {secs}s before retry"
),
});
tracing::warn!(sleep_secs = secs, "rate-limited; parking");
tokio::time::sleep(Duration::from_secs(secs)).await;
requeue_inflight(socket).await;
bus.emit_status("online");
}
// Failures are unhandled by definition — PromptTooLong is
// absorbed inside drive_turn via compaction, so anything
// that reaches Failed here is a real crash. Notify the
@ -442,6 +457,7 @@ fn build_row(
let (result_kind, note) = match outcome {
turn::TurnOutcome::Ok => ("ok", None),
turn::TurnOutcome::PromptTooLong => ("prompt_too_long", None),
turn::TurnOutcome::RateLimited => ("rate_limited", None),
turn::TurnOutcome::Failed(e) => ("failed", Some(format!("{e:#}"))),
};
TurnStatRow {