feat(webdav): add validation statuses to sources

This commit is contained in:
perf3ct 2025-07-03 14:03:26 +00:00
parent 459b8622bb
commit 7074a8d868
3 changed files with 59 additions and 13 deletions

View File

@ -68,7 +68,6 @@ import {
TextSnippet as DocumentIcon, TextSnippet as DocumentIcon,
Visibility as OcrIcon, Visibility as OcrIcon,
Block as BlockIcon, Block as BlockIcon,
FindInPage as DeepScanIcon,
HealthAndSafety as HealthIcon, HealthAndSafety as HealthIcon,
Warning as WarningIcon, Warning as WarningIcon,
Error as CriticalIcon, Error as CriticalIcon,

View File

@ -76,6 +76,10 @@ impl Database {
total_size_bytes: row.get("total_size_bytes"), total_size_bytes: row.get("total_size_bytes"),
created_at: row.get("created_at"), created_at: row.get("created_at"),
updated_at: row.get("updated_at"), updated_at: row.get("updated_at"),
validation_status: row.get("validation_status"),
last_validation_at: row.get("last_validation_at"),
validation_score: row.get("validation_score"),
validation_issues: row.get("validation_issues"),
})), })),
None => Ok(None), None => Ok(None),
} }
@ -347,6 +351,10 @@ impl Database {
total_size_bytes: row.get("total_size_bytes"), total_size_bytes: row.get("total_size_bytes"),
created_at: row.get("created_at"), created_at: row.get("created_at"),
updated_at: row.get("updated_at"), updated_at: row.get("updated_at"),
validation_status: row.get("validation_status"),
last_validation_at: row.get("last_validation_at"),
validation_score: row.get("validation_score"),
validation_issues: row.get("validation_issues"),
}; };
sources.push(source); sources.push(source);
@ -359,7 +367,8 @@ impl Database {
let row = sqlx::query( let row = sqlx::query(
r#"SELECT id, user_id, name, source_type, enabled, config, status, r#"SELECT id, user_id, name, source_type, enabled, config, status,
last_sync_at, last_error, last_error_at, total_files_synced, last_sync_at, last_error, last_error_at, total_files_synced,
total_files_pending, total_size_bytes, created_at, updated_at total_files_pending, total_size_bytes, created_at, updated_at,
validation_status, last_validation_at, validation_score, validation_issues
FROM sources WHERE id = $1"# FROM sources WHERE id = $1"#
) )
.bind(source_id) .bind(source_id)
@ -385,6 +394,10 @@ impl Database {
total_size_bytes: row.get("total_size_bytes"), total_size_bytes: row.get("total_size_bytes"),
created_at: row.get("created_at"), created_at: row.get("created_at"),
updated_at: row.get("updated_at"), updated_at: row.get("updated_at"),
validation_status: row.get("validation_status"),
last_validation_at: row.get("last_validation_at"),
validation_score: row.get("validation_score"),
validation_issues: row.get("validation_issues"),
})) }))
} else { } else {
Ok(None) Ok(None)

View File

@ -61,6 +61,11 @@ impl SourceScheduler {
if let Err(e) = self.check_and_sync_sources().await { if let Err(e) = self.check_and_sync_sources().await {
error!("Error in source sync scheduler: {}", e); error!("Error in source sync scheduler: {}", e);
} }
// Run periodic validation checks for all sources
if let Err(e) = self.run_periodic_validations().await {
error!("Error in periodic validation checks: {}", e);
}
} }
} }
@ -946,27 +951,27 @@ impl SourceScheduler {
.map_err(|e| format!("Config parse error: {}", e))?; .map_err(|e| format!("Config parse error: {}", e))?;
let webdav_config = crate::services::webdav_service::WebDAVConfig { let webdav_config = crate::services::webdav_service::WebDAVConfig {
server_url: config.server_url, server_url: config.server_url.clone(),
username: config.username, username: config.username.clone(),
password: config.password, password: config.password.clone(),
watch_folders: config.watch_folders, watch_folders: config.watch_folders.clone(),
file_extensions: config.file_extensions, file_extensions: config.file_extensions.clone(),
timeout_seconds: 30, // Quick connectivity test timeout_seconds: 30, // Quick connectivity test
server_type: config.server_type, server_type: config.server_type.clone(),
}; };
let webdav_service = crate::services::webdav_service::WebDAVService::new(webdav_config) let webdav_service = crate::services::webdav_service::WebDAVService::new(webdav_config)
.map_err(|e| format!("Service creation failed: {}", e))?; .map_err(|e| format!("Service creation failed: {}", e))?;
let test_config = crate::models::WebDAVTestConnection { let test_config = crate::models::WebDAVTestConnection {
server_url: config.server_url.clone(), server_url: config.server_url,
username: config.username.clone(), username: config.username,
password: config.password.clone(), password: config.password,
server_type: config.server_type.clone(), server_type: config.server_type,
}; };
webdav_service.test_connection(test_config).await webdav_service.test_connection(test_config).await
.map_err(|e| format!("Connection test failed: {}", e.message))?; .map_err(|e| format!("Connection test failed: {}", e))?;
Ok(()) Ok(())
} }
@ -1073,4 +1078,33 @@ impl SourceScheduler {
Ok(ErrorAnalysis { score_penalty, issues }) Ok(ErrorAnalysis { score_penalty, issues })
} }
async fn run_periodic_validations(&self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Get all enabled sources
let sources = self.state.db.get_sources_for_sync().await?;
for source in sources {
// Only validate if it's been more than 30 minutes since last validation
let should_validate = if let Some(last_validation) = source.last_validation_at {
chrono::Utc::now().signed_duration_since(last_validation).num_minutes() > 30
} else {
true // Never validated before
};
if should_validate && source.enabled {
info!("Running periodic validation for source: {}", source.name);
// Run validation in background to avoid blocking
let source_clone = source.clone();
let state_clone = self.state.clone();
tokio::spawn(async move {
if let Err(e) = Self::validate_source_health(&source_clone, &state_clone).await {
error!("Periodic validation failed for source {}: {}", source_clone.name, e);
}
});
}
}
Ok(())
}
} }