diff --git a/src/server/csv_import_export.rs b/src/server/csv_import_export.rs index 26d1fae..3b3e338 100644 --- a/src/server/csv_import_export.rs +++ b/src/server/csv_import_export.rs @@ -30,8 +30,8 @@ use crate::server::database::Database; /// Lock-free хэш-таблица для прогресса импорта /// Использует DashMap для атомарного доступа к данным прогресса struct LockFreeProgressMap { - progress_data: DashMap, - active_imports: AtomicUsize, + progress_data: DashMap, // Данные прогресса по коллекциям + active_imports: AtomicUsize, // Количество активных импортов } impl LockFreeProgressMap { @@ -74,14 +74,14 @@ impl LockFreeProgressMap { /// Менеджер CSV операций с lock-free архитектурой #[derive(Clone)] pub struct CsvManager { - database: Arc, - config: CsvConfig, - import_progress: Arc, - // Используем RwLock для буферизации, но без блокировок на операции - import_buffer: Arc>>>, + database: Arc, // Ссылка на базу данных + config: CsvConfig, // Конфигурация CSV операций + import_progress: Arc, // Прогресс импорта + import_buffer: Arc>>>, // Буфер для импорта } impl CsvManager { + /// Создает новый менеджер CSV операций pub fn new(database: Arc, config: CsvConfig) -> Self { // Создаем директории для импорта и экспорта, если они не существуют let _ = std::fs::create_dir_all(&config.import_dir); @@ -95,6 +95,7 @@ impl CsvManager { } } + /// Импортирует CSV файл в указанную коллекцию pub fn import_csv(&self, collection_name: &str, file_path: &str) -> Result { // Проверяем размер файла let metadata = std::fs::metadata(file_path) @@ -143,6 +144,7 @@ impl CsvManager { let mut document = serde_json::Map::new(); + // Преобразуем каждое поле CSV в JSON значение for (i, field) in record.iter().enumerate() { let header = if i < headers.len() { &headers[i] @@ -157,8 +159,8 @@ impl CsvManager { let json_value = Value::Object(document); buffer.push(json_value); + // Вставляем пачку записей при достижении лимита if buffer.len() >= 100 { - // Вставляем пачку записей match self.insert_batch(collection_name, &buffer) { Ok(inserted) => { record_count += inserted; @@ -170,6 +172,7 @@ impl CsvManager { } buffer.clear(); + // Обновляем прогресс каждые 100 записей if record_count % 100 == 0 { println!("Imported {} records...", record_count); @@ -266,6 +269,7 @@ impl CsvManager { Value::String(field.to_string()) } + /// Экспортирует коллекцию в CSV файл pub fn export_csv(&self, collection_name: &str, file_path: &str) -> Result { println!("Exporting collection '{}' to CSV file '{}'", collection_name, file_path); @@ -332,6 +336,7 @@ impl CsvManager { .map_err(|e| crate::common::FutriixError::CsvError(e.to_string()))?; record_count += 1; + // Отображаем прогресс каждые 100 записей if record_count % 100 == 0 { println!("Exported {} records...", record_count); } @@ -363,11 +368,13 @@ impl CsvManager { } } + /// Получает прогресс импорта для указанной коллекции pub fn get_import_progress(&self, collection_name: &str) -> f64 { self.import_progress.get(collection_name) .unwrap_or(0.0) } + /// Список доступных CSV файлов в директории импорта pub fn list_csv_files(&self) -> Result> { let csv_dir = &self.config.import_dir; let mut csv_files = Vec::new(); @@ -390,6 +397,7 @@ impl CsvManager { Ok(csv_files) } + /// Полный путь к файлу импорта pub fn get_import_file_path(&self, file_name: &str) -> String { Path::new(&self.config.import_dir) .join(file_name) @@ -397,6 +405,7 @@ impl CsvManager { .to_string() } + /// Полный путь к файлу экспорта pub fn get_export_file_path(&self, file_name: &str) -> String { Path::new(&self.config.export_dir) .join(file_name) @@ -404,11 +413,13 @@ impl CsvManager { .to_string() } + /// Проверяет существование файла pub fn file_exists(&self, file_path: &str) -> bool { Path::new(file_path).exists() } + /// Количество активных импортов pub fn active_imports_count(&self) -> usize { self.import_progress.active_imports() } -} +} \ No newline at end of file