use serde::{Deserialize, Serialize};
pub const MAX_OPTIMIZATION_DIAGNOSTICS: usize = 8;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct OptimizationPolicy {
pub key_schema_version: u32,
pub cache_namespace_version: u64,
pub admission: OptimizationAdmission,
pub expiry: ExpiryBasis,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub batch: Option<BatchPolicy>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub memory_cache: Option<MemoryCachePolicy>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum OptimizationAdmission {
Refuse,
ExecuteIndependent,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ExpiryBasis {
InjectedRuntimeTime,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct BatchPolicy {
pub max_members: u32,
pub max_canonical_bytes: u64,
pub max_members_per_scope: u32,
pub max_queue_delay_ms: u64,
pub max_backend_work: u64,
pub allocation: BatchChargeAllocation,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum BatchChargeAllocation {
EvenRemainderByMemberIndex,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct MemoryCachePolicy {
#[serde(
default,
skip_serializing_if = "std::ops::Not::not",
deserialize_with = "acquisition_pages"
)]
#[schemars(schema_with = "crate::acquisition_record::constructed_schema")]
pub acquisition_pages: bool,
pub max_bytes: u64,
pub max_entries: u64,
pub max_entry_bytes: u64,
pub max_scope_bytes: u64,
pub ttl_ms: u64,
pub eviction: EvictionOrder,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum EvictionOrder {
Fifo,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum OptimizationMechanism {
Independent,
Batch,
MemoryCache,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum OptimizationOutcome {
Bypassed,
Miss,
Hit,
Batched,
Refused,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct OptimizationRecord {
pub mechanism: OptimizationMechanism,
pub key_schema_version: u32,
pub outcome: OptimizationOutcome,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub entry_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub batch_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub batch_member: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_attempt_id: Option<String>,
pub age_ms: u64,
pub invalidation_generation: u64,
pub charge_owner: bool,
pub allocated_charge_units: u64,
pub shared_liability_units: u64,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub diagnostics: Vec<String>,
}
impl OptimizationRecord {
pub fn diagnose(&mut self, diagnostic: impl Into<String>) {
match self.diagnostics.len() {
n if n + 1 < MAX_OPTIMIZATION_DIAGNOSTICS => self.diagnostics.push(diagnostic.into()),
n if n + 1 == MAX_OPTIMIZATION_DIAGNOSTICS => {
self.diagnostics.push("further diagnostics dropped".into());
}
_ => {}
}
}
}
fn acquisition_pages<'de, D: serde::Deserializer<'de>>(d: D) -> Result<bool, D::Error> {
if !bool::deserialize(d)? {
return Err(serde::de::Error::custom(
"omit acquisition_pages when disabled",
));
}
Ok(true)
}