Composable in-memory transactions for Cats Effect which will handle locking, optimistic concurrency and automatic retries for you. The STM runtime takes care of acquiring locks in the correct order so your transactions are safe and should not deadlock. This locking is optimistic so it will only acquire the minimal set of locks and only when necessary to commit the result of a transaction.
For more information, see the microsite.
import scala.concurrent.duration._
import cats.effect.{IO, IOApp}
import io.github.timwspence.cats.stm.__
object Main extends IOApp.Simple {
override def run: IO[Unit] = STM.runtime[IO].flatMap(run(_))
def run(stm: STM[IO]): IO[Unit] = {
import stm._
def transfer(accountForTim: TVar[Long], accountForSteve: TVar[Long]): IO[Unit] =
stm.commit {
for {
balance <- accountForTim.get
_ <- stm.check(balance > 100)
_ <- accountForTim.modify(_ - 100)
_ <- accountForSteve.modify(_ + 100)
} yield ()
}
def giveTimMoreMoney(accountForTim: TVar[Long]): IO[Unit] =
for {
_ <- IO.sleep(5000.millis)
_ <- stm.commit(accountForTim.modify(_ + 1))
} yield ()
def printBalances(accountForTim: TVar[Long], accountForSteve: TVar[Long]): IO[Unit] =
for {
t <- stm.commit(for {
t <- accountForTim.get
s <- accountForSteve.get
} yield (t, s))
(amountForTim, amountForSteve) = t
_ <- IO(println(s"Tim: $amountForTim"))
_ <- IO(println(s"Steve: $amountForSteve"))
} yield ()
for {
accountForTim <- stm.commit(TVar.of[Long](100))
accountForSteve <- stm.commit(TVar.of[Long](0))
_ <- printBalances(accountForTim, accountForSteve)
_ <- giveTimMoreMoney(accountForTim).start
_ <- transfer(accountForTim, accountForSteve)
_ <- printBalances(accountForTim, accountForSteve)
} yield ()
}
}
The documentation is built using docusaurus. You can
generate it via nix-shell --run "sbt docs/docusaurusCreateSite"
. You can then
view it via nix-shell --run "cd website && npm start"
.
This software was inspired by Beautiful Concurrency and the stm package.
Many thanks to @impurepics for the awesome logo!
Development of Cats STM is generously supported in part by YourKit through the use of their excellent Java profiler.