use std::any::Any;
pub type Permit = Box<dyn Any + Send>;
pub struct RequestMeta<'a> {
pub request_id: &'a str,
pub tenant: &'a str,
pub model: &'a str,
pub route: &'static str,
pub lane: &'static str,
pub stream: bool,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct UsageCounts {
pub prompt_tokens: u64,
pub cached_prompt_tokens: u64,
pub completion_tokens: u64,
}
#[derive(Debug, PartialEq, Eq)]
pub enum AdmitError {
Insufficient,
Blocked,
Unenrolled,
Unavailable(String),
}
#[derive(Debug, Clone, Copy)]
pub struct LimitsHealth {
pub source_reload_failed: u64,
pub source_reload_consecutive: u32,
pub source_available: bool,
}
pub trait Metering: Send + Sync {
fn enforces_limits(&self) -> bool;
fn is_limited(&self, tenant: &str) -> Result<bool, AdmitError>;
fn reserve(
&self,
tenant: &str,
model: &str,
prompt_tokens: u64,
completion_bound: u64,
) -> Result<Option<Permit>, AdmitError>;
fn open(&self, meta: &RequestMeta<'_>, permit: Option<Permit>) -> Box<dyn Receipt>;
fn captures(&self, _tenant: &str) -> bool {
false
}
fn limits_health(&self) -> Option<LimitsHealth>;
fn drain_kill(&self) {}
}
pub trait Receipt: Send {
fn wants_capture(&self) -> bool {
false
}
fn arm_capture(&mut self, prompt: serde_json::Value);
fn capture_completion_delta(&mut self, text: &str);
fn record_prompt_usage(
&mut self,
prompt_tokens: u64,
cached_prompt_tokens: u64,
) -> Result<(), String>;
fn record_completion_token(&mut self) -> Result<(), String>;
fn complete(&mut self, usage: UsageCounts, worker_elapsed_s: f64) -> Result<(), String>;
fn complete_deadline_partial(
&mut self,
usage: UsageCounts,
worker_elapsed_s: f64,
) -> Result<(), String>;
fn reject(&mut self, status: u16, error_code: &str) -> Result<(), String>;
fn settle_unbilled(
&mut self,
outcome: &'static str,
status: u16,
error_code: &str,
) -> Result<(), String>;
}
pub struct MeteringInit<'a> {
pub models: &'a [String],
}
pub type MeteringFactory = Box<
dyn FnOnce(&MeteringInit<'_>) -> Result<Option<std::sync::Arc<dyn Metering>>, String> + Send,
>;