Saltar al contenido

Abrir la conexión

Dónde vive el fichero, cómo se abre, y por qué una sola conexión detrás de un cerrojo basta y sobra para una aplicación de un solo usuario.

Dónde va el fichero

En el directorio de datos del nivel 39.1 — no en configuración, no en caché, y desde luego no junto al binario:

Rust
let dir = app.path().app_data_dir()?;std::fs::create_dir_all(&dir)?;              // nivel 39.2: puede no existirlet ruta = dir.join("datos.db");

Y con eso hereda el contrato correcto: entra en las copias de seguridad del usuario, no lo borra el sistema por presión de disco, y sobrevive a una desinstalación — que es lo que quieres para el trabajo de alguien.

Abrir, con las opciones que importan

Rust
let conn = rusqlite::Connection::open(&ruta)?;// las tres que casi nadie pone y todas hacen faltaconn.pragma_update(None, "journal_mode", "WAL")?;   // nivel 42conn.pragma_update(None, "foreign_keys", "ON")?;    // no está activo por omisiónconn.pragma_update(None, "busy_timeout", 5000)?;    // esperar en vez de fallar

Las tres merecen su frase:

  • El registro de escritura anticipada cambia cómo se escriben las transacciones y es lo que permite leer mientras se escribe. El nivel 42 lo desarrolla, y activarlo es una decisión que se toma una vez y persiste en el fichero.
  • Las claves foráneas están desactivadas por omisión, por compatibilidad histórica. Si tu esquema las declara y no activas esto, no se comprueban: tienes las restricciones escritas y sin efecto, que es peor que no tenerlas porque crees que están.
  • Y el tiempo de espera hace que una operación bloqueada espere unos segundos en vez de fallar inmediatamente. Sin él, dos operaciones que coincidan producen un error en vez de esperar su turno.

Una conexión, un cerrojo

El patrón, y es todo lo que hace falta:

Rust
struct Db(Mutex<Connection>);// al arrancarapp.manage(Db(Mutex::new(conn)));// en un comando#[tauri::command]async fn listar_proyectos(db: State<'_, Db>) -> Result<Vec<Proyecto>, Error> {    let conn = db.0.lock().await;    // … consulta …}

La conclusión: no traigas un grupo de conexiones a una aplicación de escritorio salvo que hayas medido que hace falta. Es complejidad importada de un problema que no tienes.

Cuándo deja de bastar

Tres casos reales donde una sola conexión se queda corta:

  • Una operación larga bloquea a las demás. Una importación de diez minutos con el cerrojo tomado congela todo lo demás. La respuesta no es más conexiones: es trocear la operación en transacciones cortas, soltando el cerrojo entre ellas.
  • Lecturas frecuentes mientras se escribe. Con el registro de escritura anticipada, una segunda conexión solo para lectura es una optimización legítima. Nivel 42.
  • Y varias bases distintas. Si tu aplicación abre documentos independientes, cada uno con su fichero, entonces hay una conexión por documento abierto — que no es un grupo, es una por recurso.