Transactions

Stambecco provides transaction support for Workers.  The transaction support has three components:

Transactions can be nested and composed.  Transactions can only be initiated from within a Worker.  The simplest way to define a transaction is:

transaction on other send Moo(33)

The transaction will complete when the Moo message is serviced successfully by the other Worker, as long as the Moo message does not send a transactional message.  If the target's message handler sends out a transactional message, then the transaction will complete on successful completion of the transactional messages, recursively.

I should point out that all message sends in Stambecco are asynchronous.

Multiple transactional messages can be sent at once:

    for {
      transfer <- msg.xacts
      fromWorker <- WorkerMgr.find(transfer.from)
    } transaction on fromWorker send SetupTransfer(transfer)

You can define what to do after the rollback of the JDBC connection... in this case read the current balance from the backing store:

    transaction postRollback {
      (workerid, msg) => TestRecord.findAll().foreach{r => balance = r.balance}
    } update

The update command says, "add the stuff that comes before me, in this case what to do post rollback, to the list of things that define this transaction."

A particular message handler in a Worker instance can be marked not-re-entrant.  If the Worker is asked to process the same message twice, the transaction will be rolled back:

    transaction notReentrant "doSetup called second time with "+msg

A transaction can be explicitly rolled back:

    if (balance < msg.transfer.amount) 
      transaction rollback("Insufficient balance: "+balance+
                           " need "+msg.transfer.amount)

You can define what happens at the end of a successful transaction (before the transaction is committed to backing store):

    transaction complete {myCount += 32} update

You can also specify that the given complete (or postRollback or postCommit) operation such that the functions will only be added to the list of things to do if there has been no prior definitions of any operations with the setup command:

for (i <- 1 to 100) transaction complete {myCount += 1} setup

In the above example, on a complete transaction, myCount will only be incremented once, where this would result in myCount being incremented 100 times:

for (i <- 1 to 100) transaction complete {myCount += 1} update

By default, a transaction will be rolled back if it does not complete within 10 seconds.  To change the timeout for a transaction:

transaction withTimeout 3.seconds on other send Moo(33)

Timeouts can only be defined for the first message of a transaction.  All subsequent attempts to change the transaction timeout will fail.

Note that Ask/Answer cannot be used from within a transaction.  Because a question cannot be sent as part of a transaction, the response function to the Ask/Answer will not be processed until the transaction is finished.