use crate::storage::tiering::{
IntelligentTieringManager, TieringAnalysis, TieringPolicy, TieringRecommendation,
TieringTransition,
};
use crate::AppState;
use axum::{
extract::{Path, State},
http::StatusCode,
response::{IntoResponse, Json, Response},
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Debug, Serialize, Deserialize)]
pub struct PolicyResponse {
pub bucket: String,
pub policy: Option<TieringPolicy>,
pub status: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AnalysisResponse {
pub analysis: TieringAnalysis,
pub timestamp: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ApplyResponse {
pub bucket: String,
pub transitions_applied: usize,
pub transitions: Vec<TieringTransition>,
pub status: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HistoryResponse {
pub bucket: Option<String>,
pub transitions: Vec<TieringTransition>,
pub total_count: usize,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct TieringStats {
pub bucket: String,
pub total_objects: usize,
pub objects_by_tier: std::collections::HashMap<String, usize>,
pub potential_savings: f64,
pub last_analysis: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ErrorResponse {
pub error: String,
pub details: Option<String>,
}
impl IntoResponse for ErrorResponse {
fn into_response(self) -> Response {
let body = Json(self);
(StatusCode::BAD_REQUEST, body).into_response()
}
}
pub async fn get_tiering_policy(
State(state): State<AppState>,
Path(bucket): Path<String>,
) -> Result<Json<PolicyResponse>, ErrorResponse> {
let manager = IntelligentTieringManager::new(state.config.storage_root.clone())
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
let policy = manager.get_policy(&bucket).await;
Ok(Json(PolicyResponse {
bucket,
policy,
status: "success".to_string(),
}))
}
pub async fn set_tiering_policy(
State(state): State<AppState>,
Path(bucket): Path<String>,
Json(policy): Json<TieringPolicy>,
) -> Result<Json<PolicyResponse>, ErrorResponse> {
let manager = IntelligentTieringManager::new(state.config.storage_root.clone())
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
manager
.set_policy(&bucket, policy.clone())
.await
.map_err(|e| ErrorResponse {
error: "Failed to set tiering policy".to_string(),
details: Some(e.to_string()),
})?;
Ok(Json(PolicyResponse {
bucket,
policy: Some(policy),
status: "success".to_string(),
}))
}
pub async fn delete_tiering_policy(
State(_state): State<AppState>,
Path(bucket): Path<String>,
) -> Result<Json<PolicyResponse>, ErrorResponse> {
Ok(Json(PolicyResponse {
bucket,
policy: None,
status: "deleted".to_string(),
}))
}
pub async fn analyze_tiering(
State(state): State<AppState>,
Path(bucket): Path<String>,
) -> Result<Json<AnalysisResponse>, ErrorResponse> {
let manager = IntelligentTieringManager::new(state.config.storage_root.clone())
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
let policy = manager
.get_policy(&bucket)
.await
.unwrap_or_else(TieringPolicy::balanced);
let analysis = manager
.analyze_tiering(&bucket, &policy)
.await
.map_err(|e| ErrorResponse {
error: "Failed to analyze tiering".to_string(),
details: Some(e.to_string()),
})?;
Ok(Json(AnalysisResponse {
analysis,
timestamp: chrono::Utc::now().to_rfc3339(),
}))
}
pub async fn analyze_tiering_predictive(
State(state): State<AppState>,
Path(bucket): Path<String>,
) -> Result<Json<AnalysisResponse>, ErrorResponse> {
let cache_config = crate::storage::ml_cache::MlCacheConfig::default();
let cache_manager = Arc::new(
crate::storage::ml_cache::SmartCacheManager::new(cache_config).map_err(|e| {
ErrorResponse {
error: "Failed to create cache manager".to_string(),
details: Some(e.to_string()),
}
})?,
);
let manager = IntelligentTieringManager::with_analytics(
state.config.storage_root.clone(),
cache_manager,
state.predictive_analytics.clone(),
)
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
let policy = manager
.get_policy(&bucket)
.await
.unwrap_or_else(TieringPolicy::balanced);
let analysis = manager
.analyze_tiering_predictive(&bucket, &policy)
.await
.map_err(|e| ErrorResponse {
error: "Failed to analyze tiering with predictions".to_string(),
details: Some(e.to_string()),
})?;
Ok(Json(AnalysisResponse {
analysis,
timestamp: chrono::Utc::now().to_rfc3339(),
}))
}
pub async fn get_capacity_recommendations(
State(state): State<AppState>,
Path(bucket): Path<String>,
) -> Result<Json<Vec<TieringRecommendation>>, ErrorResponse> {
let cache_config = crate::storage::ml_cache::MlCacheConfig::default();
let cache_manager = Arc::new(
crate::storage::ml_cache::SmartCacheManager::new(cache_config).map_err(|e| {
ErrorResponse {
error: "Failed to create cache manager".to_string(),
details: Some(e.to_string()),
}
})?,
);
let manager = IntelligentTieringManager::with_analytics(
state.config.storage_root.clone(),
cache_manager,
state.predictive_analytics.clone(),
)
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
let recommendations = manager
.get_capacity_aware_recommendations(&bucket)
.await
.map_err(|e| ErrorResponse {
error: "Failed to get capacity-aware recommendations".to_string(),
details: Some(e.to_string()),
})?;
Ok(Json(recommendations))
}
pub async fn apply_tiering_recommendations(
State(state): State<AppState>,
Path(bucket): Path<String>,
Json(analysis): Json<TieringAnalysis>,
) -> Result<Json<ApplyResponse>, ErrorResponse> {
let manager = IntelligentTieringManager::new(state.config.storage_root.clone())
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
let transitions = manager
.apply_recommendations(&analysis)
.await
.map_err(|e| ErrorResponse {
error: "Failed to apply recommendations".to_string(),
details: Some(e.to_string()),
})?;
let count = transitions.len();
Ok(Json(ApplyResponse {
bucket,
transitions_applied: count,
transitions,
status: "success".to_string(),
}))
}
pub async fn get_transition_history(
State(state): State<AppState>,
) -> Result<Json<HistoryResponse>, ErrorResponse> {
let manager = IntelligentTieringManager::new(state.config.storage_root.clone())
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
let transitions = manager.get_transition_history().await;
let count = transitions.len();
Ok(Json(HistoryResponse {
bucket: None,
transitions,
total_count: count,
}))
}
pub async fn get_bucket_transition_history(
State(state): State<AppState>,
Path(bucket): Path<String>,
) -> Result<Json<HistoryResponse>, ErrorResponse> {
let manager = IntelligentTieringManager::new(state.config.storage_root.clone())
.await
.map_err(|e| ErrorResponse {
error: "Failed to create tiering manager".to_string(),
details: Some(e.to_string()),
})?;
let transitions = manager.get_bucket_transition_history(&bucket).await;
let count = transitions.len();
Ok(Json(HistoryResponse {
bucket: Some(bucket),
transitions,
total_count: count,
}))
}