mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 02:47:45 +08:00
Retry pre-response transport failures across candidates with an explicit stop policy, and propagate end-to-end timing into usage records and UI diagnostics. Remove legacy body, import, cookie, PII, and tunnel replay caps while preserving optional operator-configured gateway limits.
78 lines
2.3 KiB
Rust
78 lines
2.3 KiB
Rust
use crate::{ResourceBudget, ResourceClass};
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct AdmissionRequest<'a> {
|
|
pub trace_id: &'a str,
|
|
pub class: ResourceClass,
|
|
pub body_bytes: usize,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum AdmissionDecision {
|
|
Admit(ResourceBudget),
|
|
Reject(AdmissionRejectReason),
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum AdmissionRejectReason {
|
|
InvalidRequest,
|
|
BodyTooLarge,
|
|
ResourceSaturated,
|
|
QueueDeadlineExceeded,
|
|
}
|
|
|
|
pub trait AdmissionPolicy: Send + Sync {
|
|
fn decide(&self, request: AdmissionRequest<'_>) -> AdmissionDecision;
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Default)]
|
|
pub struct DefaultAdmissionPolicy;
|
|
|
|
impl AdmissionPolicy for DefaultAdmissionPolicy {
|
|
fn decide(&self, request: AdmissionRequest<'_>) -> AdmissionDecision {
|
|
if request.trace_id.trim().is_empty() {
|
|
return AdmissionDecision::Reject(AdmissionRejectReason::InvalidRequest);
|
|
}
|
|
let budget = ResourceBudget::for_class(request.class);
|
|
if budget.body_bytes > 0 && request.body_bytes > budget.body_bytes {
|
|
return AdmissionDecision::Reject(AdmissionRejectReason::BodyTooLarge);
|
|
}
|
|
AdmissionDecision::Admit(budget)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{
|
|
AdmissionDecision, AdmissionPolicy, AdmissionRejectReason, AdmissionRequest,
|
|
DefaultAdmissionPolicy,
|
|
};
|
|
use crate::ResourceClass;
|
|
|
|
#[test]
|
|
fn default_policy_rejects_empty_trace_ids() {
|
|
let decision = DefaultAdmissionPolicy.decide(AdmissionRequest {
|
|
trace_id: " ",
|
|
class: ResourceClass::Interactive,
|
|
body_bytes: 0,
|
|
});
|
|
assert_eq!(
|
|
decision,
|
|
AdmissionDecision::Reject(AdmissionRejectReason::InvalidRequest)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn default_policy_admits_uploads_above_the_legacy_body_limit() {
|
|
let decision = DefaultAdmissionPolicy.decide(AdmissionRequest {
|
|
trace_id: "trace-upload",
|
|
class: ResourceClass::Upload,
|
|
body_bytes: 64 * 1024 * 1024 + 1,
|
|
});
|
|
let AdmissionDecision::Admit(budget) = decision else {
|
|
panic!("upload body should be admitted without a size limit");
|
|
};
|
|
assert_eq!(budget.body_bytes, 0);
|
|
}
|
|
}
|