SuperAPI AI Directory

diesel

Coding & development

View repository

Updated 10-15 20:31

About this skill

Diesel

ORM with DSL and schema.rs generated. In Axum/Tokio: diesel-async + pool (deadpool-diesel / bb8 of the project). Not diesel::Connection synchronous in the handler — this blocks the runtime (tokio).

Explicit SQL: sqlx. Async ORM without Diesel DSL: sea-orm. Do not introduce Diesel if the crate is already sqlx/SeaORM.

Stack

Ask Role
diesel DSL, table!, migrations CLI
diesel_migrations embed in the binary if the repo already embeds
diesel-async AsyncPgConnection / run_query
Pool deadpool / bb8 — the project's Cargo.toml

CLI (diesel setup, migration, print-schema) in the team's flow. schema.rs is generated — do not edit by hand unless the project already does so.

Organization

migrations/
src/
  schema.rs          # gerado
  models/
  db.rs              # pool async
  • Models (Queryable, Insertable, AsChangeset) near the domain.
  • Features postgres / chrono / uuid aligned with the schema.

Non-negotiable rules

  • Axum handler: .await in diesel_async::RunQueryDsl. Sync only in spawn_blocking if the repo still has not migrated — do not add new sync.
  • diesel::update/filter with id and tenancy. Unique → AppError 409.
  • Async transaction (conn.transaction) in composite writes.
  • print-schema / migration in the same PR that changed the table.
  • Pool in State. No opening a connection per request.

Query DSL

  • users::table.filter(users::id.eq(id)).first() — types from schema.rs.
  • Explicit Select in large listings (select) — avoid loading the entire row if you only need 3 columns.
  • for_update in the mutated aggregate; skip_locked in worker (background-jobs).
  • Deep offset: prefer keyset (postgres).

Do not build SQL strings if the DSL covers it. sql_query only in a justified corner (FTS, specific upsert).

Axum

async fn get_user(
    State(pool): State<Pool>,
    Path(id): Path<i32>,
) -> Result<Json<User>, AppError> {
    let mut conn = pool.get().await?;
    let user = users::table.find(id).first(&mut conn).await?;
    Ok(Json(user))
}
  • Map NotFound / DatabaseError unique. No diesel internals in the body.
  • SQLite in CLI/sync test may remain; HTTP API stays async.

Anti-patterns

  • establish_connection + block_on in the extractor
  • Edit schema.rs and forget the migration
  • load::<T> of the entire table
  • Diesel + SeaORM in the same service without a crate boundary
  • expect("db") in production

Integration with other skills

  • Runtime: tokio (spawn_blocking only for legacy sync)
  • HTTP: axum
  • Alternatives: sqlx, sea-orm
  • Jobs: background-jobs
  • Tests: rust-unit-testing

Completion criteria

  • Async queries on the HTTP path (or documented legacy explicit blocking)
  • schema.rs + coherent migration
  • Pool in state; composite tx
  • Tenancy in filter
  • Mapped errors; no DSL leaked in the API