Skip to main content

Databases

SqlxBroker takes the dialect built in for its database; statements are built once when a subscription opens, the insert at compile time.

A dialect builds the SQL of a broker's tables from their descriptions. The built-in one, BuiltIn<DB>, is the broker's default second type parameter: SqlxBroker<Sqlite> and SqlxBroker<Sqlite, BuiltIn<Sqlite>> name the same type. Each database has a feature that adds its dialect and its sqlx driver: postgres, mysql for MySQL and MariaDB, and sqlite. any serves an AnyPool by the built-in dialect of the database it reaches. A database without a built-in dialect is served by a dialect of the service's own.

One struct describes a queue table on every database. The broker takes the dialect of its database, which builds the claims and settlements of each subscription once, when it opens, so a message costs the same on every database. The derive renders the insert of every enabled dialect at compile time. The service writes its Publish per database, because that statement is its own SQL.

What each database serves:

PostgresMySQL, MariaDBSQLiteAnyPool
Row lock formyesyesnoPostgres and MySQL backends
Lease formyesyesyesno
Advisory lock formyesyesin the processyes
Isolation levelsthreefourthree modesthe backend's
listen_notifyyesnonono
Database clockstatement_timestamp()UTC_TIMESTAMP(6)strftime(..), as textno time columns

The connections a subscription holds depend on its form and on transactional mode, alike on every database: Connections shows how to size the pool.

Example​

The broker's type names the built-in SQLite dialect, the default of SqlxBroker::from_url.

use ruststream_sqlx::BuiltIn;

/// One row of `thumbnail_jobs`, claimed under a lease. The same struct serves a `PgPool` and a
/// `MySqlPool`: only its `Publish` is written per database.
#[derive(Inbox, sqlx::FromRow)]
#[inbox(table = "thumbnail_jobs")]
struct MakeThumbnail {
#[field(id, generated)]
id: i64,
#[field(locked_until)]
locked_until: Option<DateTime<Utc>>,
#[field(payload)]
payload: Vec<u8>,
}

#[subscriber(InboxQueue::<MakeThumbnail>::new("thumbnails"))]
async fn thumbnail(image: &Image) -> HandlerOutcome {
tracing::info!(path = %image.path, "making a thumbnail");
HandlerOutcome::ack()
}

// `SqlxBroker<Sqlite>` names the same type: the built-in dialect of the database is the default.
fn broker(url: &str) -> SqlxBroker<Sqlite, BuiltIn<Sqlite>> {
SqlxBroker::from_url(url, SqlitePoolOptions::new()).route::<MakeThumbnail>("thumbnails")
}

/// The service on the database `url` names.
fn service(url: &str) -> RustStream {
let schema_url = url.to_owned();
RustStream::new(AppInfo::new("thumbnails", "0.1.0"))
// The table, created before the subscription checks it.
.on_startup(async move |()| {
let mut conn = SqliteConnection::connect(&schema_url).await?;
sqlx::raw_sql(SCHEMA).execute(&mut conn).await?;
conn.close().await
})
.with_broker(broker(url), |b| {
b.include(thumbnail);
})
}