/// Run our sample transaction. We're given our own copy of the driver and a
/// task id and we must return that same task id as well as a boolean indicating
/// whether or not we won the race. We win the race if we're the transaction
/// that inserts the example document.
///
/// Take special note of the fact that we *always* call `tx.commit`. In QLDB, it
/// is really important to call `commit` because that's when optimistic
/// concurrency control is done. Any data you've seen before `commit` is
/// speculative.
///
/// In our example, the "state machine" of the example document transitions from
/// "DOES NOT EXIST" to "EXISTS" and that's it. So, you may be tempted to think
/// that if `check.len() != 0` then the document exists and there is no need to
/// do any futher work (including calling abort).
///
/// However, consider that our state machine actually has a loop! We *might*
/// delete the record and run the example again. In that case, the check
/// statement might return 1 if it still observes the existence of the previous
/// example run (i.e. that the delete did not yet reflect).
///
/// How can this happen? QLDB is a Journal-first database. Transactions are
/// first written to the Journal and then "indexed storage" is updated to
/// reflect those changes. Writes go to the Journal first, queries go from
/// indexed storage. So, when we run our check query, we're actually querying
/// the indexed storage which may or may not reflect the results of all writes.
///
/// In practice, the QLDB indexed storage is usually instantly up to date. It is
/// highly unlikely you can trigger this behavior by running this example
/// quickly and emptying the table in between!
///
/// It is a best practice in QLDB to **always call commit**. In QLDB, there is
/// no reason to take a lock or check rows updated with a conditional.
/// Concurrency in QLDB is simple. Write your code as if you're the only actor
/// in the system **and then call commit**.
Run our sample transaction. We're given our own copy of the driver and a
task id and we must return that same task id as well as a boolean indicating
whether or not we won the race. We win the race if we're the transaction
that inserts the example document.

Take special note of the fact that we *always* call `tx.commit`. In QLDB, it
is really important to call `commit` because that's when optimistic
concurrency control is done. Any data you've seen before `commit` is
speculative.



However, consider that our state machine actually has a loop. We *might
delete the record and run the example again. In that case, the check
statement might return 1 if it still observes the existence of the previous
example run .



In practice, the QLDB indexed storage is usually instantly up to date. It is
highly unlikely you can trigger this behavior by running this example
quickly and emptying the table in between!

It is a best practice in QLDB to **always call commit**. In QLDB, there is
no reason to take a lock or check rows updated with a conditional.
Concurrency in QLDB is simple. Write your code as if you're the only actor
in the system **and then call commit**.
Run our sample transaction . We ' re given our own copy of the driver and a task id and we must return that same task id as well as a boolean indicating whether or not we won the race . We win the race if we ' re the transaction that inserts the example document . Take special note of the fact that we * always * call ` tx . commit ` . In QLDB it is really important to call ` commit ` because that ' s when optimistic concurrency control is done . Any data you ' ve seen before ` commit ` is speculative . However consider that our state machine actually has a loop . We * might delete the record and run the example again . In that case the check statement might return 1 if it still observes the existence of the previous example run . In practice the QLDB indexed storage is usually instantly up to date . It is highly unlikely you can trigger this behavior by running this example quickly and emptying the table in between! It is a best practice in QLDB to ** always call commit ** . In QLDB there is no reason to take a lock or check rows updated with a conditional . Concurrency in QLDB is simple . Write your code as if you ' re the only actor in the system ** and then call commit ** .
async fn example_transaction<C>(driver: QldbDriver<C>, task_id: u32) -> Result<(bool, u32)>
where
    C: QldbSession + Send + Sync + Clone,
{
    let winner = driver
        .transact(|mut tx| async {
            let check = tx
                .execute_statement("select * from example where id = 1")
                .await?;
            if check.len() == 0 {
                tx.execute_statement("insert into example `{id: 1}`")
                    .await?;
                tx.commit(true).await
            } else {
                // Note that we always call commit, even though we're not
                // inserting the example document here. The `false` argument is
                // not sent to QLDB. Rather, it becomes the return value of the
                // `transact` method (bound to the variable `winner`) **only
                // after the commit succeeds**. In this way, if `winner` is
                // assigned to, you are guaranteed that your transaction was
                // serialized with other changes to the ledger.
                tx.commit(false).await
            }
        })
        .await?;
    Ok((winner, task_id))
}
async fn example_transaction < C > ( driver : QldbDriver < C > , task_id : u32 ) -> Result < ( bool , u32 ) > where C : QldbSession + Send + Sync + Clone , { let winner = driver . transact ( | mut tx | async { let check = tx . execute_statement ( " " ) . await ? ; if check . len ( ) == 0 { tx . execute_statement ( " " ) . await ? ; tx . commit ( true ) . await } else { // Note that we always call commit, even though we're not // inserting the example document here. The `false` argument is // not sent to QLDB. Rather, it becomes the return value of the // `transact` method (bound to the variable `winner`) **only // after the commit succeeds**. In this way, if `winner` is // assigned to, you are guaranteed that your transaction was // serialized with other changes to the ledger. tx . commit ( false ) . await } } ) . await ? ; Ok ( ( winner , task_id ) ) }
Run our sample transaction.
Run our sample transaction .
driver
QldbDriver<C>
task_id
u32