Publish harness and TUI open-source
initial sync from the monorepo
This commit is contained in:
commit
c68e39f604
2734 changed files with 1437016 additions and 0 deletions
104
crates/common/xai-circuit-breaker/src/retry_policy.rs
Normal file
104
crates/common/xai-circuit-breaker/src/retry_policy.rs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
//! [`RetryPolicy`] — maps a non-2xx HTTP status code to a [`Disposition`],
|
||||
//! consolidating the scattered "what should I do with this response" logic.
|
||||
//!
|
||||
//! Two named presets:
|
||||
//! - [`RetryPolicy::server`] — server-side preset: retry on 429 or any 5xx;
|
||||
//! all other non-2xx are terminal.
|
||||
//! - [`RetryPolicy::client_storage`] — client upload/storage preset:
|
||||
//! 400/403/404 terminal-drop, 401 auth-refresh-once, everything else retried.
|
||||
|
||||
/// What a caller should do with a non-2xx HTTP response, by status code.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Disposition {
|
||||
/// transient: retry with backoff (5xx, 429, etc.)
|
||||
Retryable,
|
||||
/// refresh credentials once, then give up (e.g. 401)
|
||||
AuthRefresh,
|
||||
/// permanent: drop immediately, never retry (e.g. 400/403/404)
|
||||
Terminal,
|
||||
}
|
||||
|
||||
/// Maps an HTTP status code to a [`Disposition`].
|
||||
pub struct RetryPolicy {
|
||||
retryable: &'static [u16],
|
||||
auth_refresh: &'static [u16],
|
||||
terminal: &'static [u16],
|
||||
default: Disposition,
|
||||
}
|
||||
|
||||
impl RetryPolicy {
|
||||
/// Classify `status`. Returns `None` for 2xx (success, not an error).
|
||||
pub fn classify(&self, status: u16) -> Option<Disposition> {
|
||||
if (200..300).contains(&status) {
|
||||
return None;
|
||||
}
|
||||
if self.auth_refresh.contains(&status) {
|
||||
return Some(Disposition::AuthRefresh);
|
||||
}
|
||||
if self.terminal.contains(&status) {
|
||||
return Some(Disposition::Terminal);
|
||||
}
|
||||
if self.retryable.contains(&status) || (500..600).contains(&status) {
|
||||
return Some(Disposition::Retryable);
|
||||
}
|
||||
Some(self.default)
|
||||
}
|
||||
|
||||
/// `true` iff `status` classifies as `Retryable`. This is what an HTTP
|
||||
/// server emits in an `x-should-retry` header.
|
||||
pub fn should_retry(&self, status: u16) -> bool {
|
||||
matches!(self.classify(status), Some(Disposition::Retryable))
|
||||
}
|
||||
|
||||
/// Server preset: 429 and any 5xx are retryable, everything else is
|
||||
/// terminal.
|
||||
pub const fn server() -> Self {
|
||||
Self {
|
||||
retryable: &[429],
|
||||
auth_refresh: &[],
|
||||
terminal: &[],
|
||||
default: Disposition::Terminal,
|
||||
}
|
||||
}
|
||||
|
||||
/// Client storage/upload preset: 400/403/404 terminal-drop, 401
|
||||
/// auth-refresh-once, everything else (429, 5xx, unlisted 4xx) retried.
|
||||
pub const fn client_storage() -> Self {
|
||||
Self {
|
||||
retryable: &[],
|
||||
auth_refresh: &[401],
|
||||
terminal: &[400, 403, 404],
|
||||
default: Disposition::Retryable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn server_should_retry() {
|
||||
let policy = RetryPolicy::server();
|
||||
for code in [429, 500, 502, 503, 504, 501, 520] {
|
||||
assert!(policy.should_retry(code), "expected {code} to retry");
|
||||
}
|
||||
for code in [400, 401, 403, 404, 200] {
|
||||
assert!(!policy.should_retry(code), "expected {code} to NOT retry");
|
||||
}
|
||||
assert_eq!(policy.classify(200), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_storage_classify() {
|
||||
let policy = RetryPolicy::client_storage();
|
||||
for code in [400, 403, 404] {
|
||||
assert_eq!(policy.classify(code), Some(Disposition::Terminal));
|
||||
}
|
||||
assert_eq!(policy.classify(401), Some(Disposition::AuthRefresh));
|
||||
for code in [429, 500, 503, 409, 422] {
|
||||
assert_eq!(policy.classify(code), Some(Disposition::Retryable));
|
||||
}
|
||||
assert_eq!(policy.classify(200), None);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue