Releases: typelevel/cats-effect
v2.5.0
v3.0.2
This release is fully backwards and forwards compatible with everything in the 3.0.x lineage. The primary focus of this release is bug-fixing and some under-the-hood improvements in performance and stability.
User-Facing Pull Requests
- #1891 – Remove unncecessary states from the
WorkerThread
state machine (@vasilmkd) - #1894 – Fix incorrect scheduling of fibers on the work stealing runtime in presence of parasitic execution contexts (@vasilmkd)
- #1886 – Correct logic in
Sync.interruptible
(@m50d) - #1869 – Fix the cancelation check mistake (@vasilmkd)
- #1867 – Remove rarely used object references which were preallocated (@vasilmkd)
- #1871 – Fix last checked value for index in hash table (@vasilmkd)
- #1872 – Specialize
racePair
(@vasilmkd) - #1866 – Calculate child mask on demand (@vasilmkd)
- #1815 – Forward-port
NonDaemonThreadLogger
from CE2 (@Daenyth) - #1808 – Tailor made
async_
Cont
implementation (@vasilmkd) - #1893, #1890, #1873, #1853 – Documentation improvements (@jducoeur, @bplommer, @lrodero, @durban)
Special thanks to each and every one of you!
v3.0.1
This release is fully backwards and forwards compatible with everything in the 3.0.x lineage.
- Added support for Scala 3.0.0-RC2
- Removed support for Scala 3.0.0-M3
User Facing Pull Requests
- #1845 – Document how to build the site (@gvolpe)
- #1837 – Clean up some dead code (@vasilmkd)
- #1842, #1837 – Documentation improvements (@kubukoz, @LLCampos)
Special thanks to all of you!
v3.0.0
Cats Effect 3.0.0 is the first release in the 3.x lineage and the first ever major breaking change since 1.0. It represents a substantial leap forward for the library and for the ecosystem in numerous major areas, including safety, ergonomics, composability, and performance.
Even more excitingly, Cats Effect 3 represents a sturdy foundation on which we can continue to push the boundaries of what is possible within the Scala FP ecosystem! Every aspect of the library was carefully designed to foster simpler and safer usage patterns within downstream libraries. This design goal has touched almost every aspect of the API and nearly every semantic decision.
Acknowledgements
When Cats Effect 1.0.0 was released, it wasn't even clear that such a fundamentally foundational framework could exist in a space as complex as asynchronous effect systems. Over the years, we have learned that not only can such a framework exist, it is capable of fostering a thriving and innovative ecosystem for building high-performance, scalable, compositional software in an asynchronous and purely functional style. The success of Cats Effect in this space is owed in no small part to the tireless efforts of Alexandru Nedelcu, the maintainer of this project during that era. While Alex has since moved on to other endeavors, the lingering effects of his vision remain imprinted upon this library and the ecosystem as a whole.
The roots of the 3.0.0 project go back almost two and a half years. Countless people have influenced thinking and opinions on various aspects of the system. Many spirited debates and discussions were refined down to their essence and wrapped up into the whole. And of course, countless contributors have invested an enormous volume of their time into making this possible.
It is literally impossible to thank everyone who touched this project in some way. However, what follows are a list of just a few of the major contributors:
- Vasil Vasilev (@vasilmkd)
- Raas Ahsan (@RaasAhsan)
- Fabio Labella (@SystemFw)
- Tim Spence (@TimWSpence)
- Michael Pilquist (@mpilquist)
- Frank Thomas (@fthomas)
- Ben Plommer (@bplommer)
- Jakub Kozłowski (@kubukoz)
- Emrys Ingersoll (@wemrysi)
- Chris Davenport (@ChristopherDavenport)
So many of you have spent late nights tracking down race conditions, wrestling with algorithms and data structures that are nearly unprecedented, conceptualizing immensely complex abstractions and higher-order concepts in various instantiations and applications, engaging in enthusiastic discussion with countless users in various forums, and so much more. This triumph belongs to all of you.
I would also like to sincerely thank everyone who has, over the years, provided countless insightful discussions and opinions which have shaped the final result in ways both subtle and profound.
Overview
Cats Effect 3 represents an essentially complete rewrite of Cats Effect, starting from first principles and taking into account everything we've discovered and learned over the years. We went back to the drawing board on the most fundamental elements of the calculus and re-thought them from the ground up to be more compositional, more powerful, more expressive, and more amenable to high-performance implementations. As with any major reconstitution of a non-trivial framework, it would be impossible to enumerate every change individually. Thus, we will have to content ourselves with a few highlights.
If you have an interest in how the development of Cats Effect 3 unfolded, you are invited to peruse the following chronology. Each of the release notes linked below contains a thorough description of the major changes which arrived in the corresponding build:
- Milestone 1
- Milestone 2
- Milestone 3
- Milestone 4
- Milestone 5
- Release Candidate 1
- Release Candidate 2
- Release Candidate 3
New IO
Maybe we should have called it NIO
instead of IO
...
Cats Effect 3 includes a completely green field implementation of IO
, designed from the ground up to support features such as tracing, fiber locals, composable cancelation, a high-performance runtime, and much more. Even on contrived synchronous benchmarks (such as flatMap
and map
), this new IO
substantially exceeds the performance of Cats Effect 2's IO
implementation, and on more realistic benchmarks which stress the fiber runtime more heavily, the performance gains can be massive.
Even more importantly, Cats Effect 3's IO
puts a much stronger emphasis on ergonomics and completeness of user experience. The most commonly-noticed example of this in Cats Effect 2 was the lack of an IO.fromCompletableFuture
function, taking a Java CompletableFuture[A]
and producing an IO[A]
. This function is fully present in Cats Effect 3, along with many other useful operations.
Additionally, IO
no longer relies on confusing implicit structures such as ContextShift
and Timer
, nor does it have any need for tedious constructs such as Blocker
. Instead, this functionality is built directly into the runtime and available out of the box in all modes of operation. For more information, see the Getting Started section of the (new and improved!) website.
Safe Typeclass Hierarchy
The typeclass hierarchy in Cats and Cats Effect represents more than just a system of abstractions which can be used to build programs in an abstracted manner. Rather, this hierarchy forms the fundamental building blocks and capabilities which give rise to an ecosystem which fits together smoothly and safely. If you spend enough time around the Typelevel ecosystem, you'll often hear people discussing "laws" and "lawfulness", or sometimes even "algebraic soundness". These are not just academic terms for flighty ideas that have little bearing on practical software. These principles, as heady and abstract as they may be, are the seeds which are tilled into the soil that bears the fruit of the ecosystem and the overall software development experience.
In Cats Effect 3, we started from the notion that every abstraction should have well-defined semantics and laws of substitutability which encode those semantics in terms of more fundamental primitives. We rigorously demanded of ourselves that we could express these semantics in their full richness directly and cleanly, across multiple compositional effects, and with multiple backing implementations.
Furthermore, we set out to resolve one of the most glaring weaknesses in the Cats Effect 2 typeclass hierarchy: the fact that Async
and Sync
rest at the top of the hierarchy, rather than at the bottom. In other words, every effect which exists within the Cats Effect 2 ecosystem must have the ability to capture asynchronous side-effects within Async
. This is a significant handicap in reasoning and safety, not to mention the related concept of testability, since an asynchronous side-effect can feasibly be any action within your program. Thus, Concurrent
for example gave you the ability to spawn cancelable fibers... as well as do literally anything else you might want using async
.
In Cats Effect 3, Concurrent
represents the ability to run cancelable fibers which can encode linear or non-linear dataflows... and absolutely nothing else. This along is very powerful, but it is still less powerful than "you can literally do anything you want". The Async
typeclass sits at the absolute bottom of the hierarchy, where it belongs, and need not be summoned in most user code.
Compositional uncancelable
This particular semantic change may seem relatively small, but it represents an excellent example of a place in which subtle aspects of the core Cats Effect calculus can have profound impacts on the ecosystem writ large. In Cats Effect 2, uncancelable
had the following signature:
def uncancelable[A](fa: F[A]): F[A]
This function provided a mechanism for masking cancelation within a lexical scope. Any effect or composition of effects passed to uncancelable
would ignore the fiber cancel
signal until exiting the uncancelable
region. This was and is an important primitive, critical in the construction of resource-safe logic.
However, this kind of primitive is also very dangerous and limiting, since it makes it impossible to conditionally accept cancelation within the otherwise-uncancelable
block. In Cats Effect 3, this weakness has been addressed with the addition of a relatively simple parameter: Poll
:
def uncancelable[A](body: Poll[F] => F[A]): F[A]
To see why this is useful, consider the example of Semaphore
. In order to avoid leaking permits in the face of cancelation, it is absolutely necessary to guarantee that, in all cases where we acquire
a permit, we subsequently release
once and only once. Thus, acquire
falls into the classic resource acquisition pattern and would usually be wrapped in uncancelable
(particularly if done using the conventional bracket
operator).
Unfortunately, acquire
also blocks its fiber (asynchronously) in the event that no permits are currently available. This is problematic for uncancelable
because it could lead to deadlock, since that asynchronous blocking would not accept cancelation. Wrapping the acquire
itself in a poll
solves this problem by ma...
v2.4.1
v3.0.0-RC3
Cats Effect 3.0.0-RC3 is the third release candidate for 3.0.0. This will be the final release candidate prior to 3.0.0 final barring any serious show-stopper issues.
This release includes a few minor binary-incompatible changes from RC2. These are not expected to represent a significant hardship, though they do mean that the binaries are not directly substitutable.
What follows are the changes from RC2 to RC3. For a more complete summary of the changes generally included in Cats Effect 3.0.0, please see the M1, M2, M3, M4, M5, RC1, and RC2 release notes.
Notable Changes
uncancelable
Mask Regions Are Now Open At The End
This is a very subtle issue, but consider the following code:
IO uncancelable { poll =>
poll {
IO uncancelable { _ =>
...
}
// what happens here?
}
}
Assume that the containing fiber is canceled somewhere within the inner uncancelable
block. Consider the commented line: is this cancelation visible at that point? Previously, the answer to this question was "yes". Unfortunately, this semantic would also make it impossible to write safe and composable code under some circumstances!
For example, any method which wraps its body in uncancelable
and returns would be suspect. This is actually a significant percentage of Cats Effect itself, including major combinators such as bracket
.
Unfortunately, fixing this requires removing the cancelation check at the closing boundary of uncancelable
, which in turn means violating the functor laws. This, too, is quite subtle, but consider the following programs:
IO.uncancelable(_ => ...) // program 1
IO.uncancelable(_ => ...).flatMap(IO.pure) // program 2
The functor laws state that these two programs must have equivalent semantics. Unfortunately, if we remove the cancelation check at the end of uncancelable
, they no longer do! More specifically, any cancelation which happens within the uncancelable
block will be invisible at the end of the first program, but may be visible at the end of the second program. Thus, the two programs are not directly substitutable.
Fortunately, this violation is only an issue within very small program scopes. Cancelation in general is a hint and you should not be relying on it becoming visible at any particular point, only relying on it definitely not being visible at other points (e.g. inside of uncancelable
). Thus, much like catching exceptions with IO#map
, we have made the pragmatic choice to facilitate the construction of safe and reliable programs rather than prioritizing strict adherence to the mathematics.
Scalafix Migration Now Available!
Thanks to the tireless efforts of @fthomas (author of Scala Steward, may his name be praised), we now have a full-featured scalafix migration which should be able to handle most of the heavy lifting moving codebases from Cats Effect 2 to Cats Effect 3. Note that Scala Steward will be aware of this scalafix and will apply it automatically in any upgrade PRs, meaning that, for many projects, the upgrade to Cats Effect 3 may be entirely automatic!
You can find more information on how to apply this scalafix manually in the subproject readme.
Ongoing Performance Work
Despite Cats Effect 3's monumental performance results, we have only begun to scratch the surface on various things that are possible within the runtime. @vasilmkd has remained hard at work adjusting, tuning, tweaking, and coming up with new tricks to advance the state of the art. This release contains several under-the-hood improvements within the runloop and within the scheduler which should result in very noticeable improvements even above and beyond the state of performance in RC1 and RC2.
Additionally, @TimWSpence has been working on a replacement for ScheduledExecutorService
which should result in significantly improved timer performance, particularly under pressure. This change will not make it in time for 3.0.0, but should be something which lands in the near-term thereafter.
Document ALL the Things!
As we enter the final leg of the multi-year marathon that has been Cats Effect 3, the focus is increasingly on documentation and general polish. To that end, a massive amount of the changes which took place between RC2 and RC3 were not code-related at all, but actually documentation. Here again @TimWSpence has been pouring countless hours into making sure the site is fully-comprehensive and clearly explains how to use both basic and highly advanced functionality within the library.
We will be launching a brand new version of the Cats Effect website concurrently with the Cats Effect 3 release, and we absolutely cannot wait to get your feedback! Significant emphasis has been put on ensuring that newcomers have a smooth onboarding path while experienced users can find in-depth documentation that pulls back the curtain on what's really happening under the hood.
User-Facing Pull Requests
- #1803 – Do not report the cancellation exception in
IOApp
(@vasilmkd) - #1760 – Multi fiber dispatcher (@vasilmkd)
- #1686 – Scalafix migration for the update to 3.0.0 (@fthomas)
- #1784 – Exactly emulate the old
cont
state mechanism (@vasilmkd) - #1781 – Striped and batched overflow queues (@vasilmkd)
- #1800 – Opened
uncancelable
region to the right (@djspiewak) - #1798 – Shutdown the runtime after notifying all listeners (@vasilmkd)
- #1773 – Remove final fields
startIO
andstartEC
(@vasilmkd) - #1785 – Implement std queue
size
(@prova) - #1788 – Remove
MonadThrow
andApplicativeThrow
(@bplommer) - #1775 – Port
Align
instance forIO
andSyncIO
from CE2 (@alexandrustana) - #1768 – Define
unique
forIO
(@TimWSpence) - #1764 – Work stealing thread pool and worker thread refactoring (@vasilmkd)
- #1748 – Remove a branch and expensive modulo operation in the runloop (@vasilmkd)
- #1753 – Port
<&
and&>
from CE2 (@alexandrustana) - #1740 – Consolidated
IORuntime
configuration and enabled access inIOApp
itself (@djspiewak) - #1747 – Generalize
defaultCont
(@joroKr21) - #1733 –
Fiber[Resource[F, *], E, A]
join scope contained by outer (@wemrysi) - #1738 – Scala and GraalVM version updates (@vasilmkd)
- #1742 – Immediate interpreter for
Map
,FlatMap
andAttempt
(@vasilmkd) - #1720 – Use
raiseError
instead of assertions inRandom
(@patseev) - #1734 – The work stealing pool becomes a
BlockContext
(@vasilmkd) - #1730 –
IO#to
,IO#option
,IO.none
,IO.some
,Async.evalOnK
(@patseev) - #1727 – Reuse parts of the
Kleisli
GenConcurrent
instance inTimeT
(@kubukoz) - #1716 – Directly continue async execution in
Get
(@vasilmkd) - #1709 – Use
Unique
inSupervisor
instead of customToken
(@DennisVDB) - #1711 – Production ready
LocalQueue
(@vasilmkd) - #1689 – Parallel finalization in
Concurrent[Resource]#both
(@patseev) - #1701, #1713, #1718, #1735, #1743, #1756, #1778, #1771, #1799 – Documentation improvements (@djspiewak, @DennisVDB, @vasilmkd, @Daenyth, @riccardocorbella, @davidabrahams, @TimWSpence, @lrodero)
Special thanks to each and every one of you!
v2.4.0
This is the eleventh major release in the Cats Effect 2.x lineage. It is fully binary compatible with all 2.x.y releases, and forward compatible with everything in the 2.4.x line.
This release represents the final (planned) release of Cats Effect 2 prior to the release of Cats Effect 3. 🎉 To that end, the primary focus of this release has been in smoothing and improving the migration experience between 2.x and 3.0, including some minor deprecations (Resource.liftF
) as well as some backports of features from 3.0 back to the 2.x line (e.g. Supervisor
, IOApp.Simple
).
Special thanks to @fthomas for his work on the Scalafix migrations from 2.3.x up to 2.4.x, as well as the major migration from 2.x forward to 3.0.0!
User-Facing Pull Requests
- #1761 – Add rewrite for
Sync#suspend
->defer
(@bplommer) - #1759 – Port
IOApp.Simple
(@alexandrustana) - #1752 – Deprecate
Sync#suspend
(@bplommer) - #1749 – Scalafix migration for the update to 2.4.0 (@fthomas)
- #1732 – Add
Resource.eval
, deprecateliftF
(@bplommer) - #1695 – Add
Backpressure
/Supervisor
(@etspaceman)
Special thanks to each and every one of you!
v3.0.0-RC2
Cats Effect 3.0.0-RC2 is the second release candidate for 3.0.0. It is expected that one or two more release candidates will be required prior to the final release of 3.0.0, but none are specifically planned at this time. If everything goes perfectly and the ecosystem does not uncover problems, the next release will be 3.0.0 itself.
To that end, we will be attempting to maintain backward compatibility within the 3.0.0-RC lineage leading up to 3.0.0 final. This is not a guarantee and we are not enabling MiMa checks, but the intention is that any further release candidates will be binary compatible with RC1 so as to ease the burden on the ecosystem. No further changes are expected to the API, only additions.
What follows are the changes from RC1 to RC2. For a more complete summary of the changes generally included in Cats Effect 3.0.0, please see the M1, M2, M3, M4, M5, and RC1 release notes.
There are no major changes in this release since RC1. The primary purpose of this release is to support Scala 3.0.0-RC1.
User-Facing Pull Requests
- #1698 – Scala 3.0.0-RC1 (@LarsH)
- #1691 – Set remove on cancel policy for JVM
Scheduler
(@vasilmkd) - #1632 – Add
backgroundOn
andstartOn
combinators (@Wosin) - #1683 – Added
Resource#race
(@patseev)
Special thanks to each and every one of you!
v2.3.3
This is the tenth major release in the Cats Effect 2.x lineage. It is fully binary compatible with all 2.x.y releases, and forward compatible with everything in the 2.3.x line. Please note that this supersedes 2.3.2, which was published in error.
The Scala 3 release train continues onward! The primary new feature in this release is simply a cross-publication for Scala 3.0.0-RC1. Support for 3.0.0-M2 has been dropped.
Special Note
With Cats Effect 3.0.0 just around the corner, we are continuing to wind down active development on Cats Effect 2.x. Despite this, we will be continuing to support and, when necessary, backport and maintain the 2.x branch for a largely indefinite period of time (likely 1-2 years from the release of 3.0.0). Security fixes and bug fixes will be addressed with the same priority as on the 3.x release, though new feature development will be entirely focused on the newer lineage.
Along those lines, there are no user-facing pull requests in between 2.3.1 and 2.3.3.