pub mod graph;
pub mod metadata;
pub mod query;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct LineageNode {
pub id: String,
pub node_type: NodeType,
pub entity_id: String,
pub metadata: HashMap<String, String>,
pub created_at: DateTime<Utc>,
}
impl LineageNode {
pub fn new(node_type: NodeType, entity_id: String) -> Self {
Self {
id: Uuid::new_v4().to_string(),
node_type,
entity_id,
metadata: HashMap::new(),
created_at: Utc::now(),
}
}
pub fn with_metadata(mut self, key: String, value: String) -> Self {
self.metadata.insert(key, value);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum NodeType {
Dataset,
Operation,
Agent,
Model,
Parameters,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct LineageEdge {
pub id: String,
pub source_id: String,
pub target_id: String,
pub edge_type: EdgeType,
pub metadata: HashMap<String, String>,
pub created_at: DateTime<Utc>,
}
impl LineageEdge {
pub fn new(source_id: String, target_id: String, edge_type: EdgeType) -> Self {
Self {
id: Uuid::new_v4().to_string(),
source_id,
target_id,
edge_type,
metadata: HashMap::new(),
created_at: Utc::now(),
}
}
pub fn with_metadata(mut self, key: String, value: String) -> Self {
self.metadata.insert(key, value);
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum EdgeType {
DerivedFrom,
Used,
GeneratedBy,
AttributedTo,
AssociatedWith,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineageEvent {
pub id: String,
pub event_type: String,
pub timestamp: DateTime<Utc>,
pub inputs: Vec<String>,
pub outputs: Vec<String>,
pub operation: Option<String>,
pub agent: Option<String>,
pub metadata: HashMap<String, String>,
}
impl LineageEvent {
pub fn new(event_type: String) -> Self {
Self {
id: Uuid::new_v4().to_string(),
event_type,
timestamp: Utc::now(),
inputs: Vec::new(),
outputs: Vec::new(),
operation: None,
agent: None,
metadata: HashMap::new(),
}
}
pub fn with_input(mut self, input_id: String) -> Self {
self.inputs.push(input_id);
self
}
pub fn with_output(mut self, output_id: String) -> Self {
self.outputs.push(output_id);
self
}
pub fn with_operation(mut self, operation_id: String) -> Self {
self.operation = Some(operation_id);
self
}
pub fn with_agent(mut self, agent_id: String) -> Self {
self.agent = Some(agent_id);
self
}
pub fn with_metadata(mut self, key: String, value: String) -> Self {
self.metadata.insert(key, value);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lineage_node_creation() {
let node = LineageNode::new(NodeType::Dataset, "dataset-123".to_string())
.with_metadata("format".to_string(), "GeoTIFF".to_string());
assert_eq!(node.node_type, NodeType::Dataset);
assert_eq!(node.entity_id, "dataset-123");
assert_eq!(node.metadata.get("format"), Some(&"GeoTIFF".to_string()));
}
#[test]
fn test_lineage_edge_creation() {
let edge = LineageEdge::new(
"node-1".to_string(),
"node-2".to_string(),
EdgeType::DerivedFrom,
)
.with_metadata("operation".to_string(), "reproject".to_string());
assert_eq!(edge.source_id, "node-1");
assert_eq!(edge.target_id, "node-2");
assert_eq!(edge.edge_type, EdgeType::DerivedFrom);
}
#[test]
fn test_lineage_event() {
let event = LineageEvent::new("transform".to_string())
.with_input("input-1".to_string())
.with_output("output-1".to_string())
.with_operation("op-1".to_string())
.with_agent("user-123".to_string());
assert_eq!(event.event_type, "transform");
assert_eq!(event.inputs.len(), 1);
assert_eq!(event.outputs.len(), 1);
assert_eq!(event.operation, Some("op-1".to_string()));
assert_eq!(event.agent, Some("user-123".to_string()));
}
}