Update src/server/csv_import_export.rs

This commit is contained in:
Григорий Сафронов 2026-01-20 21:39:13 +00:00
parent 61b8a6795c
commit 12364a7edd

View File

@ -30,8 +30,8 @@ use crate::server::database::Database;
/// Lock-free хэш-таблица для прогресса импорта
/// Использует DashMap для атомарного доступа к данным прогресса
struct LockFreeProgressMap {
progress_data: DashMap<String, f64>,
active_imports: AtomicUsize,
progress_data: DashMap<String, f64>, // Данные прогресса по коллекциям
active_imports: AtomicUsize, // Количество активных импортов
}
impl LockFreeProgressMap {
@ -74,14 +74,14 @@ impl LockFreeProgressMap {
/// Менеджер CSV операций с lock-free архитектурой
#[derive(Clone)]
pub struct CsvManager {
database: Arc<Database>,
config: CsvConfig,
import_progress: Arc<LockFreeProgressMap>,
// Используем RwLock для буферизации, но без блокировок на операции
import_buffer: Arc<RwLock<DashMap<String, Vec<Value>>>>,
database: Arc<Database>, // Ссылка на базу данных
config: CsvConfig, // Конфигурация CSV операций
import_progress: Arc<LockFreeProgressMap>, // Прогресс импорта
import_buffer: Arc<RwLock<DashMap<String, Vec<Value>>>>, // Буфер для импорта
}
impl CsvManager {
/// Создает новый менеджер CSV операций
pub fn new(database: Arc<Database>, 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<usize> {
// Проверяем размер файла
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<usize> {
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<Vec<String>> {
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()
}
}
}