use async_graphql::Schema;
use std::sync::Arc;
use crate::graphql::{
query::Query,
mutation::Mutation,
subscription::Subscription,
optimized_queries::OptimizedQuery,
optimized_mutations::OptimizedMutation,
cache::{GraphQLCacheManager, CacheConfig},
performance::{PerformanceMonitor, QueryAnalyzer, ResourceMonitor},
types::PaginationInput,
};
pub struct EnhancedGraphQLSchema {
pub schema: Schema<OptimizedQuery, OptimizedMutation, Subscription>,
pub cache_manager: Arc<GraphQLCacheManager>,
pub performance_monitor: Arc<PerformanceMonitor>,
pub query_analyzer: QueryAnalyzer,
pub resource_monitor: Arc<ResourceMonitor>,
}
impl EnhancedGraphQLSchema {
pub fn new() -> Self {
let cache_config = CacheConfig::default();
let cache_manager = Arc::new(GraphQLCacheManager::new(cache_config));
let cache_manager_clone = cache_manager.clone();
tokio::spawn(async move {
cache_manager_clone.start_cleanup_task().await;
});
let performance_monitor = Arc::new(PerformanceMonitor::new(
10_000, tokio::time::Duration::from_secs(300), ));
let perf_monitor_clone = performance_monitor.clone();
tokio::spawn(async move {
perf_monitor_clone.start_cleanup_task().await;
});
let query_analyzer = QueryAnalyzer::new(
tokio::time::Duration::from_millis(1000), 100, );
let resource_monitor = Arc::new(ResourceMonitor::new());
let optimized_query = OptimizedQuery::new(cache_manager.clone());
let optimized_mutation = OptimizedMutation::new(cache_manager.clone());
let schema = Schema::build(optimized_query, optimized_mutation, Subscription)
.finish();
Self {
schema,
cache_manager,
performance_monitor,
query_analyzer,
resource_monitor,
}
}
pub fn schema(&self) -> &Schema<OptimizedQuery, OptimizedMutation, Subscription> {
&self.schema
}
pub async fn get_cache_stats(&self) -> crate::graphql::cache::CacheManagerStats {
self.cache_manager.get_stats().await
}
pub async fn get_performance_stats(&self) -> crate::graphql::performance::PerformanceStats {
self.performance_monitor.get_stats().await
}
pub async fn get_slow_operations(&self, threshold_ms: u64) -> Vec<crate::graphql::performance::SerializableOperationMetrics> {
self.performance_monitor.get_slow_operations(threshold_ms).await
}
pub fn analyze_query(&self, query: &str) -> crate::graphql::performance::QueryAnalysis {
self.query_analyzer.analyze_query(query)
}
pub async fn get_resource_usage(&self) -> ResourceUsage {
ResourceUsage {
memory_usage: self.resource_monitor.get_total_memory_usage().await,
cpu_usage: self.resource_monitor.get_cpu_usage().await,
}
}
}
#[derive(async_graphql::SimpleObject, Clone, Debug)]
pub struct ResourceUsage {
pub memory_usage: u64,
pub cpu_usage: f64,
}
#[async_graphql::Object]
impl OptimizedQuery {
async fn cache_stats(&self) -> async_graphql::Result<crate::graphql::cache::CacheManagerStats> {
Err(async_graphql::Error::new("Not implemented"))
}
async fn performance_metrics(&self) -> async_graphql::Result<crate::graphql::performance::PerformanceStats> {
Err(async_graphql::Error::new("Not implemented"))
}
async fn slow_operations(&self, _threshold_ms: u64) -> async_graphql::Result<Vec<crate::graphql::performance::SerializableOperationMetrics>> {
Err(async_graphql::Error::new("Not implemented"))
}
async fn resource_usage(&self) -> async_graphql::Result<ResourceUsage> {
Err(async_graphql::Error::new("Not implemented"))
}
}
#[async_graphql::Object]
impl OptimizedMutation {
async fn clear_cache(&self, _cache_type: Option<String>) -> async_graphql::Result<bool> {
Err(async_graphql::Error::new("Not implemented"))
}
async fn warm_cache(&self, _queries: Vec<String>) -> async_graphql::Result<bool> {
Err(async_graphql::Error::new("Not implemented"))
}
}
pub fn create_enhanced_schema() -> EnhancedGraphQLSchema {
EnhancedGraphQLSchema::new()
}
pub fn create_schema() -> Schema<Query, Mutation, Subscription> {
Schema::build(Query, Mutation, Subscription)
.finish()
}
pub type FortressSchema = Schema<Query, Mutation, Subscription>;
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_enhanced_schema_creation() {
let enhanced_schema = create_enhanced_schema();
assert!(enhanced_schema.schema().execute("{ version }").await.errors.is_empty());
}
#[tokio::test]
async fn test_cache_stats() {
let enhanced_schema = create_enhanced_schema();
let stats = enhanced_schema.get_cache_stats().await;
assert_eq!(stats.database.total_entries, 0);
assert_eq!(stats.table.total_entries, 0);
assert_eq!(stats.query.total_entries, 0);
}
#[tokio::test]
async fn test_performance_stats() {
let enhanced_schema = create_enhanced_schema();
let stats = enhanced_schema.get_performance_stats().await;
assert_eq!(stats.total_operations, 0);
assert_eq!(stats.successful_operations, 0);
assert_eq!(stats.failed_operations, 0);
}
#[tokio::test]
async fn test_query_analysis() {
let enhanced_schema = create_enhanced_schema();
let query = "{ databases { id name } }";
let analysis = enhanced_schema.analyze_query(query);
assert!(analysis.complexity > 0);
assert!(analysis.estimated_duration.as_millis() > 0);
}
#[tokio::test]
async fn test_resource_usage() {
let enhanced_schema = create_enhanced_schema();
let usage = enhanced_schema.get_resource_usage().await;
assert!(usage.memory_usage >= 0);
assert!(usage.cpu_usage >= 0.0);
}
#[tokio::test]
async fn test_optimized_query_performance() {
let enhanced_schema = create_enhanced_schema();
let query = r#"
{
databases {
id
name
status
encryptionAlgorithm
createdAt
tableCount
storageSizeBytes
}
}
"#;
let start_time = std::time::Instant::now();
let result = enhanced_schema.schema().execute(query).await;
let duration = start_time.elapsed();
assert!(result.errors.is_empty());
assert!(duration.as_millis() < 100);
}
#[tokio::test]
async fn test_backward_compatibility() {
let old_schema = create_schema();
let query = "{ version }";
let result = old_schema.execute(query).await;
assert!(result.errors.is_empty());
let enhanced_schema = create_enhanced_schema();
let result = enhanced_schema.schema().execute(query).await;
assert!(result.errors.is_empty());
}
}