zirv-db-sqlx 0.3.0

A convenient wrapper around sqlx: global connection-pool management, tunable pool settings, graceful shutdown, and transaction helpers for MySQL, PostgreSQL, and SQLite.
Documentation

zirv-db-sqlx

A small, convenient wrapper around SQLx that standardises connection-pool management, pool tuning, graceful shutdown, and transaction handling across a service. Works with MySQL, PostgreSQL, and SQLite.

Built on top of zirv-config: the pool reads its settings from the database.* configuration namespace.

Features

  • Global connection pool stored in a process-wide OnceLock. Initialize once with init_db_pool!(), then read it anywhere with get_db_pool!() (it returns a shared reference, so there is no per-call cost).
  • Tunable pool settings read from configuration, each falling back to sqlx's own default when unset (see Configuration).
  • Graceful shutdown via close_db_pool(), which drains and closes the pool.
  • Transaction helpers (start_transaction!, commit_transaction!, rollback_transaction!) that remove the usual boilerplate and log failures with tracing.
  • Multi-database support selected at compile time through Cargo features.

Installation

zirv-db-sqlx requires you to choose one database backend and one runtime + TLS backend. The default is MySQL on Tokio with native-tls:

[dependencies]
zirv-db-sqlx = "0.3"

For PostgreSQL or SQLite, disable the defaults and pick your backend:

# PostgreSQL, Tokio, rustls
zirv-db-sqlx = { version = "0.3", default-features = false, features = ["postgres", "runtime-tokio", "tls-rustls"] }

# SQLite, Tokio, native-tls
zirv-db-sqlx = { version = "0.3", default-features = false, features = ["sqlite", "runtime-tokio", "tls-native-tls"] }

Enabling zero or more than one database backend is a compile error with a clear message telling you what to fix.

Feature flags

Feature Default Description
mysql MySQL / MariaDB backend.
postgres PostgreSQL backend.
sqlite SQLite backend.
runtime-tokio Tokio async runtime.
tls-native-tls TLS via the system's native TLS stack.
tls-rustls TLS via rustls.

Configuration

Register a database configuration block with zirv-config before calling init_db_pool!(). Only url is required; everything else falls back to the same default sqlx uses, so you keep sane behaviour out of the box.

Config key Type Default Meaning
database.url string (required) Connection string passed to sqlx.
database.max_connections u32 10 Hard cap on open connections.
database.min_connections u32 0 Connections kept warm while idle.
database.acquire_timeout_seconds u64 30 How long acquire waits before erroring.
database.idle_timeout_seconds u64 600 Reap idle connections after this long. 0 disables.
database.max_lifetime_seconds u64 1800 Recycle connections older than this. 0 disables.
database.test_before_acquire bool true Ping a connection before handing it out.

Usage

Setting up and using the pool

use zirv_config::register_config;
use zirv_db_sqlx::{init_db_pool, get_db_pool, close_db_pool};

#[derive(serde::Serialize)]
struct DatabaseConfig {
    url: String,
    max_connections: u32,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    register_config!("database", DatabaseConfig {
        url: "mysql://user:password@localhost/db_name".to_string(),
        max_connections: 10,
    });

    // Initialize the pool once at startup. Fails fast if the database is unreachable.
    init_db_pool!();

    // Read the pool anywhere.
    let pool = get_db_pool!();
    let row: (i64,) = sqlx::query_as("SELECT 1").fetch_one(pool).await?;
    assert_eq!(row.0, 1);

    // Drain and close the pool on shutdown.
    close_db_pool().await;
    Ok(())
}

Transactions

The transaction macros log failures and early-return the error, so the enclosing function must return Result<_, sqlx::Error>. Do not add a ? to them.

use zirv_db_sqlx::{start_transaction, commit_transaction, rollback_transaction};
use sqlx::types::Uuid;

async fn rename_user(id: Uuid, name: &str) -> Result<(), sqlx::Error> {
    let mut tx = start_transaction!();

    if let Err(e) = sqlx::query("UPDATE users SET name = ? WHERE id = ?")
        .bind(name)
        .bind(id)
        .execute(&mut *tx)
        .await
    {
        rollback_transaction!(tx);
        return Err(e);
    }

    commit_transaction!(tx);
    Ok(())
}

API beyond the macros

  • zirv_db_sqlx::db::get_db_pool() -> &'static DbPool — the function the macro wraps.
  • zirv_db_sqlx::close_db_pool().await — graceful shutdown.
  • zirv_db_sqlx::PoolSettings — the resolved pool configuration, including PoolSettings::from_config() and to_pool_options() if you want to build the pool yourself.
  • zirv_db_sqlx::{Db, DbPool} — type aliases for the selected backend and its pool.

Minimum Supported Rust Version

1.94, matching sqlx 0.9.

Contributing

Contributions are welcome. Please open an issue or pull request.

License

Licensed under either of MIT or Apache-2.0 at your option.