Crate axum_sqlx_tx
source ·Expand description
Request-bound SQLx transactions for axum.
Tx
is an axum
extractor for obtaining a transaction that’s bound to the
HTTP request. A transaction begins the first time the extractor is used for a request, and is
then stored in request extensions for use by other middleware/handlers. The transaction is
resolved depending on the status code of the eventual response – successful (HTTP 2XX
or
3XX
) responses will cause the transaction to be committed, otherwise it will be rolled back.
This behaviour is often a sensible default, and using the extractor (e.g. rather than directly
using sqlx::Transaction
s) means you can’t forget to commit the transactions!
§Usage
To use the Tx
extractor, you must first add State
and Layer
to your app. State
holds the configuration for the extractor, and the Layer
middleware manages the
request-bound transaction.
// It's recommended to create aliases specialised for your extractor(s)
type Tx = axum_sqlx_tx::Tx<sqlx::Sqlite>;
let pool = sqlx::SqlitePool::connect("...").await.unwrap();
let (state, layer) = Tx::setup(pool);
let app = axum::Router::new()
// .route(...)s
.layer(layer)
.with_state(state);
You can then simply add Tx
as an argument to your handlers:
type Tx = axum_sqlx_tx::Tx<sqlx::Sqlite>;
async fn create_user(mut tx: Tx, /* ... */) {
// `&mut Tx` implements `sqlx::Executor`
let user = sqlx::query("INSERT INTO users (...) VALUES (...)")
.fetch_one(&mut tx)
.await
.unwrap();
// `Tx` also implements `Deref<Target = sqlx::Transaction>` and `DerefMut`
use sqlx::Acquire;
let inner = tx.begin().await.unwrap();
/* ... */
}
§Error handling
axum
requires that errors can be turned into responses. The Error
type converts into a
HTTP 500 response with the error message as the response body. This may be suitable for
development or internal services but it’s generally not advisable to return internal error
details to clients.
See Error
for how to customise error handling.
§Multiple databases
If you need to work with multiple databases, you can define marker structs for each. See
Marker
for an example.
It’s not currently possible to use Tx
for a dynamic number of databases. Feel free to open an
issue if you have a requirement for this.
§Accessing the pool
Note that State
implements FromRef
into the inner SQLx pool. Therefore,
if you still need to access the database pool at some handler, you can use axum’s State
extractor normally.
use axum::extract::State;
async fn this_still_works(State(pool): State<sqlx::SqlitePool>) {
/* ... */
}
§Examples
See examples/
in the repo for more examples.
Structs§
- Configuration for
Tx
extractors. - A
tower_layer::Layer
that enables theTx
extractor. - A
tower_service::Service
that enables theTx
extractor. - Application state that enables the
Tx
extractor. - An
axum
extractor for a database transaction.
Enums§
- Possible errors when extracting
Tx
from a request.
Traits§
- Extractor marker type.