Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Concurrency Control

When multiple writers modify the same record, you need a way to detect conflicting writes. Toasty supports optimistic concurrency control (OCC) through the #[version] attribute: Toasty conditions each write on a version field and atomically increments it, so a stale writer sees its update fail rather than silently overwrite a newer value.

Optimistic concurrency with #[version]

Add #[version] to a u64 field to enable OCC on a model. Toasty manages the field — you declare it but never set it manually.

#![allow(unused)]
fn main() {
use toasty::Model;
#[derive(Debug, toasty::Model)]
struct Document {
    #[key]
    #[auto]
    id: uuid::Uuid,

    content: String,

    #[version]
    version: u64,
}
}

Create. Toasty sets the version to 1 on the new record.

Instance update. doc.update()...exec() conditions the write on the current version and atomically increments it. If another writer has updated the record since you last loaded it, the update returns an error.

Instance delete. doc.delete().exec() conditions the delete on the current version. If the record has been updated since you last loaded it, the delete returns an error.

Query-based update. Document::filter_by_id(id).update()...exec() atomically increments the version on every matched row (version = version + 1), but does not condition the write on a prior version — a query-based update is atomic at the database level and may span many rows. Advancing the counter is enough to make a concurrent instance update or delete from a stale snapshot fail its version check instead of overwriting the query update.

#![allow(unused)]
fn main() {
use toasty::Model;
#[derive(Debug, toasty::Model)]
struct Document {
    #[key]
    #[auto]
    id: uuid::Uuid,
    content: String,
    #[version]
    version: u64,
}
async fn __example(mut db: toasty::Db) -> toasty::Result<()> {
let mut doc = toasty::create!(Document { content: "hello" })
    .exec(&mut db)
    .await?;

assert_eq!(doc.version, 1);

// Load a second handle — both start at version 1
let mut stale = Document::get_by_id(&mut db, &doc.id).await?;

// Advance doc to version 2
doc.update().content("world").exec(&mut db).await?;
assert_eq!(doc.version, 2);

// stale is still at version 1 — the update fails with a conflict error
let result = stale.update().content("conflict").exec(&mut db).await;
assert!(result.is_err());
Ok(())
}
}

Only instance updates and instance deletes check the version and fail on conflict. Query-based updates increment the version but apply unconditionally — they never fail on a version mismatch.

Note: #[version] is supported by the DynamoDB driver only. SQL drivers do not yet implement OCC.