# Base de Datos y Transacciones en OxiCloud ## Introducción a Transacciones Explícitas en la Base de Datos Este documento describe la implementación de transacciones explícitas en OxiCloud para garantizar la integridad de los datos en operaciones de base de datos PostgreSQL. ## ¿Qué son las Transacciones? Una transacción es una secuencia de operaciones de base de datos tratadas como una única unidad lógica. Las transacciones siguen las propiedades ACID: - **Atomicidad**: Una transacción es "todo o nada". Si cualquier parte falla, toda la transacción falla. - **Consistencia**: La base de datos pasa de un estado válido a otro estado válido. - **Aislamiento**: Las transacciones simultáneas se comportan como si fueran secuenciales. - **Durabilidad**: Una vez confirmada, la transacción permanece confirmada incluso en caso de fallo del sistema. ## Implementación en OxiCloud OxiCloud ahora utiliza un enfoque consistente para las transacciones de base de datos mediante la función `with_transaction`, que: 1. Comienza una transacción 2. Ejecuta operaciones 3. Confirma automáticamente si todo fue exitoso 4. Revierte (rollback) automáticamente en caso de error ### Utilidad de Transacciones En `src/infrastructure/repositories/pg/transaction_utils.rs` hemos implementado: ```rust /// Helper function to execute database operations in a transaction pub async fn with_transaction( pool: &Arc, operation_name: &str, operation: F, ) -> Result where F: for<'c> FnOnce(&'c mut Transaction<'_, Postgres>) -> futures::future::BoxFuture<'c, Result>, E: From + std::fmt::Display { ... } ``` Esta función: - Recibe un pool de conexiones y un closure con operaciones - Maneja begin/commit/rollback automáticamente - Proporciona logging detallado del ciclo de vida de la transacción ### Ejemplo de Uso en Repositorios ```rust // Creación de un usuario con transacción explícita async fn create_user(&self, user: User) -> UserRepositoryResult { with_transaction( &self.pool, "create_user", |tx| { Box::pin(async move { // Operación principal - insertar usuario sqlx::query("INSERT INTO auth.users ...") .bind(...) .execute(&mut **tx) .await?; // Operaciones adicionales dentro de la misma transacción // ... Ok(user_clone) }) } ).await } ``` ## Casos de Uso Implementados ### En UserPgRepository 1. **Creación de Usuario** - Garantiza que todas las operaciones de inserción son atómicas - Permite agregar operaciones relacionadas (como configuración de permisos) 2. **Actualización de Usuario** - Asegura que las modificaciones se apliquen completamente o no se apliquen en absoluto - Soporta operaciones combinadas como actualización de información de perfil y preferencias ### En SessionPgRepository 1. **Creación de Sesión** - Inserta la sesión y actualiza el timestamp de último acceso del usuario en una única transacción - Garantiza consistencia entre sesiones y datos de usuario 2. **Revocación de Sesiones** - Asegura que la revocación de una sesión o de todas las sesiones de un usuario sea atómica - Permite registrar eventos de seguridad dentro de la misma transacción ## Niveles de Aislamiento OxiCloud admite diferentes niveles de aislamiento de transacciones mediante `with_transaction_isolation`: ```rust // Ejemplo de uso con nivel de aislamiento específico with_transaction_isolation( &pool, "operacion_critica", sqlx::postgres::PgIsolationLevel::Serializable, |tx| { ... } ).await ``` Los niveles de aislamiento disponibles son: 1. **Read Committed** (predeterminado) - Garantiza que los datos leídos están confirmados - No previene lecturas no repetibles o fantasma 2. **Repeatable Read** - Garantiza que las lecturas sean consistentes durante toda la transacción - Previene lecturas no repetibles pero no lecturas fantasma 3. **Serializable** - Nivel más alto de aislamiento - Garantiza que las transacciones se comporten como si se ejecutaran en serie - Puede causar errores de serialización que requieren reintento ## Mejores Prácticas 1. **Duración de Transacciones** - Mantén las transacciones lo más cortas posible - Evita operaciones de larga duración dentro de transacciones 2. **Manejo de Errores** - Los errores dentro de una transacción provocan rollback automático - Utiliza logging adecuado para diagnosticar fallos 3. **Límites de Transacción** - Define claramente dónde comienzan y terminan las transacciones - Agrupa operaciones relacionadas en una sola transacción 4. **Aislamiento Apropiado** - Usa el nivel de aislamiento más bajo adecuado para tu caso de uso - Considera serializable para operaciones críticas con posibilidad de conflicto ## Ventajas de Transacciones Explícitas 1. **Integridad de Datos Mejorada** - Garantía ACID para operaciones complejas - Prevención de estados inconsistentes 2. **Mejor Manejo de Errores** - Rollback automático ante fallos - Comportamiento predecible en caso de error 3. **Concurrencia Segura** - Manejo adecuado de operaciones simultáneas - Prevención de condiciones de carrera 4. **Rendimiento** - Reducción de trips a la base de datos - Operaciones en lote para mejor eficiencia ## Consideraciones de Rendimiento - Las transacciones añaden cierta sobrecarga - El rendimiento puede verse afectado por: - Duración de la transacción - Nivel de aislamiento - Número de registros afectados - Contención por bloqueos ## Conclusión La implementación de transacciones explícitas en OxiCloud mejora significativamente la robustez del sistema y garantiza la integridad de los datos en escenarios complejos. El enfoque modular y la API de transacciones simplificada permiten extender fácilmente estos beneficios a nuevas funcionalidades.