Releases: TimWSpence/cats-stm
Releases · TimWSpence/cats-stm
v0.10.0-RC1
Release candidates time!
This is a release tracking cats effect 3.0.0-RC2 and scala 3.0.0-RC1. Many thanks to the swift work of the maintainers of all of our dependencies for releasing faster than me!
v0.10.0-M3
A relatively small release with a few notable changes:
- Support for 3.0.0-M3!
- Fixed several bugs where error and retry handlers were not correctly lexically scoped
- Removed the distributive law
a.orElse(b) >>= f <-> (a >>= f).orElse(b >>= f)
While a nice property, it is also a lie 🍰 Takea = stm.unit
,b = stm.abort(new RuntimeException())
,f = _ => stm.retry
as a counterexample
v0.10.0-M2
A small release but with two exciting changes:
- Cross-building and publishing for Dotty!
- A rewrite of the pattern matching runloop we use to evaluate transactions. This was initially to make Dotty happy but enabled us to make this cats effect 3-inspired optimization which resulted in an ~20% performance improvement for
eval
(the core of our runloop which evaluates transactions lock-free)
v0.10.0-M1
This is a big release! (In fact, it's basically a from-scratch rewrite). Unfortunately it involves some source-incompatible changes but hopefully you'll agree the benefits are very much worth it! Highlights include:
- 'Honest effect polymorphism': previously we could run
STM.atomically[IO](txn1)
andSTM.atomically[OptionT[IO, *]](txn2)
and run the risk of class-cast exceptions as we tracked state internally that was parameterized onF
without that being tracked in the type system. Now the design looks like:
trait STM[F[_]] {
class TVar[A] {
def get: Txn[A]
}
trait Txn[A]
def commit[A](txn: Txn[A]): F[A]
}
which means that a Txn
is tied to the effect type of the STM
instance which created it and hence safe
- Stack-safe construction and evaluation of
Txn
s - Fine-grained locking: when committing we only acquire a lock on the
TVar
s that we are comitting, rather than a global lock, and hence can support a higher degree of parallelism - Fully semantic-blocking: one of the worst features of previous versions was that it would acquire a global lock via a blocking
STM.synchronized
- something you should never do on anIO
thread. Now the implementation is entirely based on the Cats Effect semantically-blockingRef
andSemaphore
abstractions - a
MonadError[Txn, Throwable]
instance which enables backtracking in a transaction eg
for {
tvar <- stm.commit(TVar.of(0))
_ <- stm.commit(
for {
_ <- tvar.set(1)
_ <- (tvar.modify(_ + 1) >> stm.abort(new RuntimeException("BOOM"))).handleErrorWith {
case _ => tvar.modify(_ + 2)
}
} yield ()
)
v <- stm.commit(tvar.get)
res <- IO(assertEquals(v, 3))
} yield res
- Laws governing the interaction of the
stm
combinators - Support for Cats Effect 3! Unfortunately this release actually depends on some specifics of cats effect 3 so it has not (yet at least) been back-ported to cats effect 2. The expectation is that the non-milestone release will happen as soon as cats effect 3 is released
- Defining a lot of derived cats combinators directly on
Txn
for convenience and discoverability in IDEs