Skip to main content

Events

custom(..) hands one event of a table to the service's own SQL, Claim to Extend, and every other event keeps the statement the dialect builds.

An event the table names, in #[inbox(custom(..))] on the derive or with .own::<own::X>() by hand, runs the service's own code in place of the dialect's statement. Each event is a trait the struct implements for its database:

EventTraitWhat it does
claimClaimselects and takes the ids of the next rows
fetchFetchreads the claimed rows, such as over a join
ackAckfinishes a row its handler acknowledged
retryRetryreturns a row to the queue at once
retry_afterRetryAfterhides a row until a time
discardDiscardfinishes a row its handler dropped
dead_letterDeadLettermoves a row past its cap
extendExtendextends the leases in work
lock, unlockLock, Unlocktake and release the key of a row

A named event without its impl does not compile, and the error names the trait. The table and the broker stay as they were, and every event the table does not name keeps the dialect's statement.

A settlement of the service's own runs in the transaction the crate commits, so it settles the row as the built-in one does. An acknowledgement takes the row out of what the claim selects: a row it leaves claimable is delivered again. The form limits the events: the advisory lock form selects its candidates by key itself and takes no claim, extend belongs to the lease form, and lock and unlock come together in the advisory lock form.

Example​

A sent email stays in its table for an audit: the acknowledgement moves it to the sent group instead of deleting it.

use ruststream_sqlx::Ack;
use sqlx::{Sqlite, SqliteConnection};

#[derive(Inbox, sqlx::FromRow)]
#[inbox(table = "email_jobs", custom(ack))]
struct SendEmail {
#[field(id, generated)]
job_id: i64,
#[field(group)]
name: String,
#[field(locked_until)]
locked_until: Option<DateTime<Utc>>,
#[field(payload)]
payload: Vec<u8>,
}

// A sent email stays in its table, in the `sent` group, for an audit.
impl Ack<Sqlite> for SendEmail {
async fn ack(conn: &mut SqliteConnection, id: &i64) -> Result<(), sqlx::Error> {
sqlx::query("UPDATE email_jobs SET name = 'sent' WHERE job_id = ?")
.bind(id)
.execute(conn)
.await?;
Ok(())
}
}