1use crate::core::types::TrackingResult;
6use crate::export::fast_export_coordinator::{CompleteExportStats, FastExportCoordinator};
7use crate::export::quality_validator::{
8 ExportConfig, ExportMode, ExportModeManager, QualityValidator, ValidationResult,
9 ValidationTiming,
10};
11use std::future::Future;
12use std::path::Path;
13use std::pin::Pin;
14
15pub type FastExportResult = TrackingResult<CompleteExportStats>;
19
20pub type NormalExportResult = TrackingResult<(CompleteExportStats, ValidationResult)>;
22
23#[derive(Debug)]
25pub enum ExportOutcome {
26 Fast(CompleteExportStats),
28 WithValidation(CompleteExportStats, ValidationResult),
30}
31
32pub fn export_fast<P: AsRef<Path>>(
34 output_path: P,
35) -> Pin<Box<dyn Future<Output = FastExportResult> + Send>> {
36 let path = output_path.as_ref().to_path_buf();
37
38 Box::pin(async move {
39 tracing::info!("🚀 Starting fast export mode (no validation)");
40
41 let mut coordinator = FastExportCoordinator::new_fast_mode();
43
44 let stats = coordinator.export_without_validation(&path).await?;
46
47 tracing::info!(
48 "✅ Fast export completed: {} allocations, {:.2} MB",
49 stats.parallel_processing.total_allocations,
50 stats.write_performance.total_bytes_written as f64 / 1024.0 / 1024.0
51 );
52
53 Ok(stats)
54 })
55}
56
57pub fn export_with_validation<P: AsRef<Path>>(
59 output_path: P,
60) -> Pin<Box<dyn Future<Output = NormalExportResult> + Send>> {
61 let path = output_path.as_ref().to_path_buf();
62
63 Box::pin(async move {
64 tracing::info!("🚀 Starting export with validation mode (export first, then validate)");
65
66 tracing::info!("📝 Step 1: Executing export...");
68 let mut coordinator = FastExportCoordinator::new_normal_mode();
69 let stats = coordinator.export_without_validation(&path).await?;
70
71 tracing::info!(
72 "✅ Export completed: {} allocations, {:.2} MB",
73 stats.parallel_processing.total_allocations,
74 stats.write_performance.total_bytes_written as f64 / 1024.0 / 1024.0
75 );
76
77 tracing::info!("🔍 Step 2: Executing validation...");
79 let mut validator = QualityValidator::new_default();
80 let validation_result = validator.validate_file_async(&path).await?;
81
82 tracing::info!(
83 "✅ Validation completed: {}",
84 if validation_result.is_valid {
85 "PASSED"
86 } else {
87 "FAILED"
88 }
89 );
90
91 Ok((stats, validation_result))
92 })
93}
94
95pub struct ExportCoordinator {
97 config: ExportConfig,
99 mode_manager: ExportModeManager,
101}
102
103impl ExportCoordinator {
104 pub fn new(config: ExportConfig) -> Self {
106 Self {
107 config,
108 mode_manager: ExportModeManager::new(),
109 }
110 }
111
112 pub fn new_fast() -> Self {
114 Self::new(ExportConfig::fast())
115 }
116
117 pub fn new_slow() -> Self {
119 Self::new(ExportConfig::slow())
120 }
121
122 pub fn new_auto() -> Self {
124 Self::new(ExportConfig::auto())
125 }
126
127 pub fn new_auto_sized(data_size: usize) -> Self {
129 let mode_manager = ExportModeManager::new();
130 let config = mode_manager.create_auto_config(data_size);
131 Self::new(config)
132 }
133
134 pub async fn export<P: AsRef<Path>>(&self, output_path: P) -> TrackingResult<ExportOutcome> {
136 match (&self.config.mode, &self.config.validation_timing) {
137 (ExportMode::Fast, _) | (_, ValidationTiming::Disabled) => {
138 let stats = export_fast(output_path).await?;
139 Ok(ExportOutcome::Fast(stats))
140 }
141 (ExportMode::Slow, ValidationTiming::Inline) => {
142 let (stats, validation) = export_with_validation(output_path).await?;
145 Ok(ExportOutcome::WithValidation(stats, validation))
146 }
147 _ => {
148 let (stats, validation) = export_with_validation(output_path).await?;
150 Ok(ExportOutcome::WithValidation(stats, validation))
151 }
152 }
153 }
154
155 pub fn config(&self) -> &ExportConfig {
157 &self.config
158 }
159
160 pub fn update_config(
162 &mut self,
163 mut config: ExportConfig,
164 data_size: Option<usize>,
165 ) -> Vec<String> {
166 let mut warnings = config.validate_and_fix();
167
168 if let Some(size) = data_size {
169 let (optimized_config, optimization_warnings) =
170 self.mode_manager.optimize_config(config, size);
171 config = optimized_config;
172 warnings.extend(optimization_warnings);
173 }
174
175 self.config = config;
176 warnings
177 }
178
179 pub fn mode_manager(&self) -> &ExportModeManager {
181 &self.mode_manager
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188 use crate::export::error_handling::ValidationType;
189
190 #[test]
191 fn test_export_outcome_debug() {
192 let stats = create_test_stats();
193 let outcome = ExportOutcome::Fast(stats.clone());
194 let debug_str = format!("{outcome:?}");
195 assert!(debug_str.contains("Fast"));
196
197 let validation = create_test_validation_result();
198 let outcome = ExportOutcome::WithValidation(stats, validation);
199 let debug_str = format!("{outcome:?}");
200 assert!(debug_str.contains("WithValidation"));
201 }
202
203 #[test]
204 fn test_fast_export_result_type() {
205 let _result: FastExportResult = Ok(create_test_stats());
206 }
208
209 #[test]
210 fn test_normal_export_result_type() {
211 let _result: NormalExportResult =
212 Ok((create_test_stats(), create_test_validation_result()));
213 }
215
216 #[test]
217 fn test_export_coordinator_new() {
218 let config = ExportConfig::fast();
219 let coordinator = ExportCoordinator::new(config.clone());
220
221 assert_eq!(coordinator.config().mode, config.mode);
222 assert_eq!(
223 coordinator.config().validation_timing,
224 config.validation_timing
225 );
226 }
227
228 #[test]
229 fn test_export_coordinator_new_fast() {
230 let coordinator = ExportCoordinator::new_fast();
231
232 assert_eq!(coordinator.config().mode, ExportMode::Fast);
233 assert_eq!(
234 coordinator.config().validation_timing,
235 ValidationTiming::Deferred
236 );
237 }
238
239 #[test]
240 fn test_export_coordinator_new_slow() {
241 let coordinator = ExportCoordinator::new_slow();
242
243 assert_eq!(coordinator.config().mode, ExportMode::Slow);
244 assert_eq!(
245 coordinator.config().validation_timing,
246 ValidationTiming::Inline
247 );
248 }
249
250 #[test]
251 fn test_export_coordinator_new_auto() {
252 let coordinator = ExportCoordinator::new_auto();
253
254 assert_eq!(coordinator.config().mode, ExportMode::Auto);
255 assert_eq!(
256 coordinator.config().validation_timing,
257 ValidationTiming::Deferred
258 );
259 }
260
261 #[test]
262 fn test_export_coordinator_new_auto_sized() {
263 let coordinator = ExportCoordinator::new_auto_sized(1000);
264
265 assert_eq!(coordinator.config().mode, ExportMode::Fast);
268 }
269
270 #[test]
271 fn test_export_coordinator_update_config() {
272 let mut coordinator = ExportCoordinator::new_fast();
273 let _old_config = coordinator.config().clone();
274
275 let new_config = ExportConfig::slow();
276 let warnings = coordinator.update_config(new_config.clone(), None);
277
278 assert_eq!(coordinator.config().mode, new_config.mode);
279 assert_eq!(
280 coordinator.config().validation_timing,
281 new_config.validation_timing
282 );
283 assert!(warnings.is_empty());
285 }
286
287 #[test]
288 fn test_export_coordinator_update_config_with_optimization() {
289 let mut coordinator = ExportCoordinator::new_fast();
290
291 let new_config = ExportConfig::slow();
292 let _warnings = coordinator.update_config(new_config.clone(), Some(1000000)); assert_eq!(coordinator.config().mode, new_config.mode);
295 assert_eq!(
296 coordinator.config().validation_timing,
297 new_config.validation_timing
298 );
299 }
302
303 #[test]
304 fn test_export_coordinator_mode_manager() {
305 let coordinator = ExportCoordinator::new_fast();
306 let mode_manager = coordinator.mode_manager();
307
308 let (mode, threshold, _perf_threshold) = mode_manager.get_settings();
310 assert_eq!(mode, ExportMode::Fast);
311 assert!(threshold > 0);
312 }
313
314 fn create_test_stats() -> CompleteExportStats {
316 use crate::export::data_localizer::DataGatheringStats;
317 use crate::export::high_speed_buffered_writer::WritePerformanceStats;
318 use crate::export::parallel_shard_processor::ParallelProcessingStats;
319
320 CompleteExportStats {
321 data_gathering: DataGatheringStats {
322 total_time_ms: 50,
323 basic_data_time_ms: 30,
324 ffi_data_time_ms: 10,
325 scope_data_time_ms: 10,
326 allocation_count: 100,
327 ffi_allocation_count: 10,
328 scope_count: 50,
329 },
330 parallel_processing: ParallelProcessingStats {
331 total_allocations: 100,
332 shard_count: 4,
333 threads_used: 2,
334 total_processing_time_ms: 100,
335 avg_shard_processing_time_ms: 25.0,
336 parallel_efficiency: 1.8,
337 throughput_allocations_per_sec: 1000.0,
338 used_parallel_processing: true,
339 total_output_size_bytes: 10240,
340 },
341 write_performance: WritePerformanceStats {
342 total_bytes_written: 10240,
343 shards_written: 4,
344 total_write_time_ms: 50,
345 avg_write_speed_bps: 204800.0,
346 flush_count: 2,
347 preallocation_effective: true,
348 buffer_utilization: 0.8,
349 },
350 total_export_time_ms: 200,
351 total_allocations_processed: 100,
352 total_output_size_bytes: 10240,
353 overall_throughput_allocations_per_sec: 500.0,
354 overall_write_speed_mbps: 0.05,
355 data_gathering_percentage: 25.0,
356 processing_percentage: 50.0,
357 writing_percentage: 25.0,
358 estimated_traditional_time_ms: 1000,
359 performance_improvement_factor: 5.0,
360 }
361 }
362
363 fn create_test_validation_result() -> ValidationResult {
364 use crate::export::quality_validator::{IssueSeverity, IssueType, ValidationIssue};
365
366 ValidationResult {
367 is_valid: true,
368 validation_type: ValidationType::DataIntegrity,
369 message: "Test validation".to_string(),
370 issues: vec![ValidationIssue {
371 issue_type: IssueType::InconsistentData,
372 description: "Test issue".to_string(),
373 severity: IssueSeverity::Medium,
374 affected_data: "test_data".to_string(),
375 suggested_fix: Some("Fix the data".to_string()),
376 auto_fixable: false,
377 }],
378 validation_time_ms: 10,
379 data_size: 10240,
380 }
381 }
382}