Source

fogbow / src / main / scala / fogbow / example / actor / BankStm.scala

package fogbow.example.actor

import akka.stm._
import akka.actor._
import akka.util.duration._
import akka.event.EventHandler

// From Akka documentation

object BankStm {
  type Account = Ref[Double]

  case class Transfer(from: Account, to: Account, amount: Double)

  class Transferer extends Actor {
    implicit val txFactory = 
      TransactionFactory(blockingAllowed = true, trackReads = true, timeout = 10 seconds)

    def receive = {
      case Transfer(from, to, amount) =>
	atomic {
          if (from.get < amount) {
            EventHandler.info(this, "not enough money - retrying")
            retry
          }
          EventHandler.info(this, "transferring")
          from alter (_ - amount)
          to alter (_ + amount)
	}
    }
  }

  def main (args: Array[String]) {

    val account1 = Ref(100.0)
    val account2 = Ref(100.0)

    val transferer = Actor.actorOf(new Transferer).start

    transferer ! Transfer(account1, account2, 500.0)
    // INFO Transferer: not enough money - retrying

    Thread.sleep(1000)

    println("Account 1 gets paid!")
    atomic { 
      account1 alter (_ + 2000) 
    }
    // INFO Transferer: transferring

    Thread.sleep(1000)

    atomic { 
      println("Account 1: " + account1.get)
    }
    // -> 1600.0

    atomic { 
      println("Account 2: " + account2.get)
    }
    // -> 600.0

    println("Done.")
    transferer.stop
    System.exit(0)
  }

}