#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
serde::Serialize,
serde::Deserialize,
specta::Type,
)]
#[serde(rename_all = "snake_case")]
pub enum IngestionKind {
Memory,
Knowledge,
GraphSnapshot,
EvalVerdict,
Insight,
Cost,
Health,
Session,
Config,
Checkpoint,
Round,
Finding,
}
impl IngestionKind {
pub const ALL: &'static [Self] = &[
Self::Memory,
Self::Knowledge,
Self::GraphSnapshot,
Self::EvalVerdict,
Self::Insight,
Self::Cost,
Self::Health,
Self::Session,
Self::Config,
Self::Checkpoint,
Self::Round,
Self::Finding,
];
pub const fn as_str(self) -> &'static str {
match self {
Self::Memory => "memory",
Self::Knowledge => "knowledge",
Self::GraphSnapshot => "graph_snapshot",
Self::EvalVerdict => "eval_verdict",
Self::Insight => "insight",
Self::Cost => "cost",
Self::Health => "health",
Self::Session => "session",
Self::Config => "config",
Self::Checkpoint => "checkpoint",
Self::Round => "round",
Self::Finding => "finding",
}
}
pub fn parse(value: &str) -> Option<Self> {
Self::ALL.iter().copied().find(|k| k.as_str() == value)
}
}
impl std::fmt::Display for IngestionKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn as_str_agrees_with_serde_for_every_kind() {
for kind in IngestionKind::ALL {
let wire = serde_json::to_value(kind).expect("serialize");
assert_eq!(wire, serde_json::json!(kind.as_str()));
assert_eq!(IngestionKind::parse(kind.as_str()), Some(*kind));
}
assert_eq!(IngestionKind::ALL.len(), 12);
}
#[test]
fn there_is_no_import_path_into_a_fresh_epoch() {
for forbidden in ["import", "migrate", "migration", "backfill", "legacy"] {
assert!(
IngestionKind::parse(forbidden).is_none(),
"ingestion kind {forbidden} exists"
);
assert!(
serde_json::from_value::<IngestionKind>(serde_json::json!(forbidden)).is_err(),
"ingestion kind {forbidden} decodes off the wire"
);
}
}
}