use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct ModelPoolSpec {
pub id: String,
pub members: Vec<PoolMemberSpec>,
#[serde(default)]
pub routing: PoolRoutingPolicy,
#[serde(default)]
pub switch: PoolSwitchPolicy,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct PoolMemberSpec {
pub model_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub weight: Option<u32>,
#[serde(default)]
pub role: PoolMemberRole,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, schemars::JsonSchema,
)]
#[serde(rename_all = "snake_case")]
pub enum PoolMemberRole {
#[default]
Member,
FailoverOnly,
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct PoolRoutingPolicy {
#[serde(default)]
pub home: HomeStrategy,
#[serde(default)]
pub sticky_scope: StickyScope,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, schemars::JsonSchema,
)]
#[serde(rename_all = "snake_case")]
pub enum HomeStrategy {
#[default]
Deterministic,
RoundRobin,
FirstHealthy,
}
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, schemars::JsonSchema,
)]
#[serde(rename_all = "snake_case")]
pub enum StickyScope {
#[default]
Thread,
Run,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct PoolSwitchPolicy {
#[serde(default = "default_true")]
pub on_circuit_open: bool,
#[serde(default = "default_true")]
pub on_quota: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub quota_retry_after_threshold_secs: Option<u64>,
#[serde(default = "default_true")]
pub on_permanent: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_switches_per_session: Option<u32>,
}
impl Default for PoolSwitchPolicy {
fn default() -> Self {
Self {
on_circuit_open: true,
on_quota: true,
quota_retry_after_threshold_secs: None,
on_permanent: true,
max_switches_per_session: None,
}
}
}
fn default_true() -> bool {
true
}
impl ModelPoolSpec {
pub fn new<I, S>(id: impl Into<String>, member_model_ids: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
Self {
id: id.into(),
members: member_model_ids
.into_iter()
.map(|model_id| PoolMemberSpec {
model_id: model_id.into(),
weight: None,
role: PoolMemberRole::Member,
})
.collect(),
routing: PoolRoutingPolicy::default(),
switch: PoolSwitchPolicy::default(),
}
}
}