Saltar a contenido

Transacciones

Las transacciones te permiten asegurar que múltiples operaciones se completen con éxito antes de un guardado en tu base de datos. Una vez una transacción ha empezado, puedes ejecutar consultas de Fluent de manera normal. Sin embargo, ningún dato será guardado en la base de datos hasta que la transacción se complete. Si se lanza un error en algún momento durante la transacción (por ti o por la base de datos), no se efectuará ningún cambio.

Para llevar a cabo una transacción, necesitas acceso a algo que pueda conectar con la base de datos. Normalmente, esto es una petición HTTP entrante. Para esto, usa req.db.transaction(_ :):

req.db.transaction { database in
    // usar la base de datos
}

Una vez dentro del closure de la transacción, debes usar la base de datos proporcionada en el parámetro del closure (llamado database en el ejemplo) para hacer consultas.

Cuando este closure devuelva de manera exitosa, se hará la transacción.

var sun: Star = ...
var sirius: Star = ...

return req.db.transaction { database in
    return sun.save(on: database).flatMap { _ in
        return sirius.save(on: database)
    }
}

El ejemplo anterior guardará sun y después sirius antes de completar la transacción. Si falla el guardado de cualquiera de las estrellas, ninguna se guardará.

Una vez la transacción se haya completado, el resultado puede transformarse en un futuro diferente, como una respuesta HTTP que indique la finalización, de manera similar al siguiente ejemplo:

return req.db.transaction { database in
    // usa la base de datos y ejecuta la transacción
}.transform(to: HTTPStatus.ok)

async/await

Si usas async/await puedes refactorizar el código de la siguiente manera:

try await req.db.transaction { transaction in
    try await sun.save(on: transaction)
    try await sirius.save(on: transaction)
}
return .ok