schema_registry_lineage/lib.rs
1//! # Schema Registry Lineage Tracking
2//!
3//! This crate provides comprehensive lineage tracking capabilities for the LLM Schema Registry.
4//! It tracks dependencies between schemas, applications, data pipelines, and LLM models, enabling
5//! impact analysis and change propagation understanding.
6//!
7//! ## Features
8//!
9//! - **Dependency Graph**: Track schema-to-schema, schema-to-application, and schema-to-pipeline dependencies
10//! - **Transitive Dependencies**: Calculate all transitive dependencies with depth control
11//! - **Impact Analysis**: Analyze the impact of schema changes on downstream consumers
12//! - **Circular Dependency Detection**: Detect and report circular dependencies
13//! - **Graph Algorithms**: BFS, DFS, shortest path, topological sort
14//! - **Export Formats**: GraphML, DOT (Graphviz), and JSON for visualization
15//! - **Thread-Safe**: Concurrent access with Arc and RwLock
16//!
17//! ## Quick Start
18//!
19//! ```rust
20//! use schema_registry_lineage::{LineageEngine, LineageTracker, RelationType, SchemaChange};
21//! use uuid::Uuid;
22//!
23//! # #[tokio::main]
24//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
25//! // Create a new lineage engine
26//! let engine = LineageEngine::new();
27//!
28//! // Track dependencies
29//! let schema_a = Uuid::new_v4();
30//! let schema_b = Uuid::new_v4();
31//!
32//! engine.track_dependency(schema_a, schema_b, RelationType::DependsOn).await?;
33//!
34//! // Get upstream dependencies
35//! let upstream = engine.get_upstream(schema_a).await?;
36//! println!("Schema A depends on {} schemas", upstream.len());
37//!
38//! // Perform impact analysis
39//! let change = SchemaChange::FieldRemoved {
40//! name: "email".to_string(),
41//! };
42//!
43//! let impact = engine.impact_analysis(schema_b, change).await?;
44//! println!("Risk level: {:?}", impact.risk_level);
45//! println!("Affected schemas: {}", impact.affected_schemas.len());
46//!
47//! // Detect circular dependencies
48//! let circular = engine.detect_circular().await?;
49//! if !circular.is_empty() {
50//! println!("WARNING: {} circular dependencies detected", circular.len());
51//! }
52//!
53//! // Export for visualization
54//! let graphml = engine.export_graphml()?;
55//! std::fs::write("/tmp/lineage.graphml", graphml)?;
56//! # Ok(())
57//! # }
58//! ```
59//!
60//! ## Architecture
61//!
62//! The lineage tracking system consists of several key components:
63//!
64//! - **GraphStore**: In-memory graph storage using petgraph
65//! - **Algorithms**: Graph algorithms (BFS, DFS, cycles, etc.)
66//! - **Tracker**: Dependency tracking operations
67//! - **ImpactAnalyzer**: Schema change impact analysis
68//! - **Exporter**: Export to GraphML, DOT, and JSON formats
69//! - **LineageEngine**: Main orchestrator that combines all components
70//!
71//! ## Examples
72//!
73//! ### Tracking Schema Dependencies
74//!
75//! ```rust
76//! use schema_registry_lineage::{LineageEngine, SchemaNode, DependencyTarget, RelationType};
77//! use schema_registry_core::versioning::SemanticVersion;
78//! use uuid::Uuid;
79//!
80//! # #[tokio::main]
81//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
82//! let engine = LineageEngine::new();
83//!
84//! let user_schema = SchemaNode::new(
85//! Uuid::new_v4(),
86//! SemanticVersion::new(1, 0, 0),
87//! "com.example.User".to_string(),
88//! );
89//!
90//! let address_schema = SchemaNode::new(
91//! Uuid::new_v4(),
92//! SemanticVersion::new(1, 0, 0),
93//! "com.example.Address".to_string(),
94//! );
95//!
96//! // User composes Address
97//! engine.track_dependency(
98//! user_schema.clone(),
99//! DependencyTarget::Schema(address_schema),
100//! RelationType::Composes,
101//! ).await?;
102//! # Ok(())
103//! # }
104//! ```
105//!
106//! ### Impact Analysis
107//!
108//! ```rust
109//! use schema_registry_lineage::{LineageEngine, LineageTracker, SchemaChange};
110//! use uuid::Uuid;
111//!
112//! # #[tokio::main]
113//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
114//! let engine = LineageEngine::new();
115//! let schema_id = Uuid::new_v4();
116//!
117//! let change = SchemaChange::FieldTypeChanged {
118//! name: "age".to_string(),
119//! old_type: "int32".to_string(),
120//! new_type: "int64".to_string(),
121//! };
122//!
123//! let impact = engine.impact_analysis(schema_id, change).await?;
124//!
125//! println!("Impact Report:");
126//! println!(" Risk Level: {:?}", impact.risk_level);
127//! println!(" Affected Schemas: {}", impact.affected_schemas.len());
128//! println!(" Affected Apps: {}", impact.affected_applications.len());
129//! println!(" Migration Complexity: {:.2}", impact.migration_complexity);
130//! println!(" Estimated Effort: {:.1} hours", impact.estimated_effort_hours);
131//!
132//! for recommendation in &impact.recommendations {
133//! println!(" - {}", recommendation);
134//! }
135//! # Ok(())
136//! # }
137//! ```
138
139#![warn(missing_docs)]
140#![warn(clippy::all)]
141#![warn(clippy::pedantic)]
142#![allow(clippy::module_name_repetitions)]
143#![allow(clippy::missing_errors_doc)]
144#![allow(clippy::missing_panics_doc)]
145
146pub mod algorithms;
147pub mod engine;
148pub mod error;
149pub mod export;
150pub mod graph_store;
151pub mod impact;
152pub mod tracker;
153pub mod types;
154
155// Re-export main types and traits
156pub use engine::{LineageEngine, LineageTracker};
157pub use error::{LineageError, Result};
158pub use export::{JsonEdge, JsonGraph, JsonGraphMetadata, JsonNode, LineageExporter};
159pub use graph_store::{GraphStats, GraphStore};
160pub use impact::{ImpactAnalyzer, ImpactSummary};
161pub use tracker::{DependencyTracker, DependencyTrackerImpl};
162pub use types::{
163 CircularDependency, Dependency, DependencyGraph, DependencyTarget, Dependent, EntityType,
164 ExternalEntity, ImpactReport, LineageFilter, RelationType, RiskLevel, SchemaChange, SchemaId,
165 SchemaNode,
166};
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171
172 #[test]
173 fn test_crate_exports() {
174 // Verify all main types are exported
175 let _engine: Option<LineageEngine> = None;
176 let _error: Option<LineageError> = None;
177 let _report: Option<ImpactReport> = None;
178 let _graph: Option<DependencyGraph> = None;
179 }
180}