Ficheros grandes
Leer un fichero de dos gigas en memoria es la forma más fácil de matar una aplicación. Flujos, progreso, cancelación y el camino que no pasa por el puente.
Los cuatro problemas
El patrón completo
Los cuatro juntos, que es como se escriben:
#[tauri::command]async fn procesar_archivo( app: AppHandle, estado: State<'_, Trabajos>, origen: String, // un identificador de dominio, no una ruta. Nivel 14.4) -> Result<Resumen, Error> { let ruta = estado.resolver(&origen)?; // la app decide qué fichero es let cancelar = estado.nueva_bandera(); tauri::async_runtime::spawn_blocking(move || { let total = std::fs::metadata(&ruta)?.len(); let mut leidos = 0u64; let mut buffer = vec![0u8; 64 * 1024]; let mut f = File::open(&ruta)?; let mut ultimo_aviso = 0u64; loop { if cancelar.load(Ordering::Relaxed) { return Err(Error::Cancelado); } let n = f.read(&mut buffer)?; if n == 0 { break; } procesar_trozo(&buffer[..n])?; leidos += n as u64; // avisar cada 1%, no cada trozo: el puente no es para esto if leidos - ultimo_aviso > total / 100 { ultimo_aviso = leidos; let _ = app.emit("progreso", leidos as f64 / total as f64); } } Ok(resumen()) }) .await?}Cuatro detalles del fragmento que son la lección entera:
- El buffer se reutiliza. No se asigna uno por trozo.
- La bandera se comprueba en cada vuelta, que es lo que hace cancelable el bucle. Sin eso, «cancelar» solo significa dejar de mirar.
- El progreso se emite cada uno por ciento, no cada trozo. Un fichero de dos gigas con trozos de 64 KB son treinta mil vueltas: emitir en todas satura el puente y hace la operación más lenta que el trabajo real.
- Y el comando recibe un identificador, no una ruta. El nivel 14.4 otra vez.
Los bytes no cruzan el puente
La decisión de arquitectura, y es la que más rendimiento y más seguridad da a la vez:
La pregunta que resuelve el diseño: ¿la interfaz necesita los bytes, o necesita mostrarlos? Casi siempre es lo segundo, y para mostrar hay dos caminos que no cruzan el puente.
Escribir grande
El mismo patrón al revés, con dos añadidos:
- La escritura atómica del nivel 40.2 no siempre vale. Escribir dos gigas en un temporal y renombrar duplica el espacio ocupado durante la operación. Para exportaciones grandes suele aceptarse el riesgo y escribir directo, avisando de que si se interrumpe hay que repetir — pero es una decisión, no un descuido.
- Y hay que comprobar el espacio libre antes de empezar, porque quedarse sin disco a mitad de una escritura de dos gigas deja al usuario sin espacio y sin resultado.