Releases: typelevel/cats-effect
v3.5.5
This is the fiftieth release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release and fully source-compatible with every 3.5.x release.
Warning
The 3.5.x series contains some changes that may be semantically breaking with respect to earlier 3.x releases. If you're using fs2, http4s, or other libraries from the ecosystem, make sure you've upgraded to versions of these libraries that are compatible with this release (for fs2, that's 3.7.0+, for http4s it's 0.23.19+)!
Additionally, if you're using methods like fromFuture
, make sure you're aware of the major changes to async
, described in these release notes.
What's Changed
Enhancements
Dispatcher
: avoid spinning by @durban in #4052- Relax
access
semantics inMapRef
implementations by @armanbilge in #4116 - optimize
IO.whenA
by @Jasper-M in #4135
Bug Fixes
- Fix #4066: shut down executors when
IORuntime.global
shuts down by @durban in #4067 - Use
IOApp#reportFailure
instead ofprintStackTrace()
for blocking EC by @fredfp in #4044 - Fix
cancelable
toguarantee
cancelation by @armanbilge in #4118
Documentation
- Update versions for 3.5.4 by @djspiewak in #4032
- Improve contributor documentation by @durban in #4038
- Expand the example of using
Random[F]
in the doc for 3.5.x by @sshark in #4041 - Document usage of
-Wnonunit-statement
by @froth in #4054 - link to
MapRef
docs in site sidebar by @samspills in #4122 - Add lifecycle diagrams to
Supervisor
web docs by @samspills in #4127
Behind the Scenes
- Fix CI step to post release to Discord by @armanbilge in #4031
- Create 8-core Cirrus CI job by @armanbilge in #4036
- Try to address
DispatcherSpec
timeout in CI by @durban in #4057 - Pin CI to macOS 12 by @armanbilge in #4078
- Remove GraalVM from CI matrix by @mzuehlke in #4153
New Contributors
Full Changelog: v3.5.4...v3.5.5
v3.5.4
This is the forty-ninth release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release and fully source-compatible with every 3.5.x release.
Warning
The 3.5.x series contains some changes that may be semantically breaking with respect to earlier 3.x releases. If you're using fs2, http4s, or other libraries from the ecosystem, make sure you've upgraded to versions of these libraries that are compatible with this release (for fs2, that's 3.7.0+, for http4s it's 0.23.19+)!
Additionally, if you're using methods like fromFuture
, make sure you're aware of the major changes to async
, described in these release notes.
What's Changed
The most significant change in this release involves the complete greenfield rewrite of Dispatcher
. While Dispatcher
is, in practice, one of the most-used components of Cats Effect apart from IO
itself, it is also one of the oldest and most "accreted" parts of the codebase. The original variant of Dispatcher
had far fewer features and was thrown together relatively quickly during the 3.0 milestone process, and every change and enhancement to its functionality has been layered on top of that foundation.
In this release, we started with an empty editor buffer and rebuilt the whole thing, taking the opportunity to correct a number of corner cases in semantics while significantly beefing up the test suite. We're very confident that the results are much more stable and reliable than the previous iteration, and we're excited to get it into everyone's hands!
Enhancements
IORuntimeConfig
: reject invalid auto-yield and cancelation check thresholds by @durban in #3987- Rewrote
Dispatcher
by @djspiewak in #3923
Bug Fixes
- Fix a few Supervisor bugs by @durban in #3972
- Clear the CallbackStack more aggressively by @samspills in #3973
- Fix issue #3998 by @durban in #4001
- Fix issue #4002 by @durban in #4003
- Introduce
WeakList
and use inFiberMonitor
by @armanbilge in #3964
Documentation
- Fix typos in
Async
scaladoc by @durban in #3995 - Removes language:postfixOps from tutorial as it is not used. by @froth in #4025
Behind the Scenes
- Update versions for 3.5.3 by @armanbilge in #3957
- Fix Discord post step in release job by @armanbilge in #3956
- Refine steps about post-release scripts by @armanbilge in #3961
- Attempt to cancel the running test in case of a timeout by @durban in #3969
- Add explanatory comment to Mutex implementation by @durban in #3968
- Updated copyright year by @djspiewak in #3976
- Try to fix issue #3979 by @durban in #3983
- Fixed
WeakList
headers by @djspiewak in #4027
New Contributors
Full Changelog: v3.5.3...v3.5.4
v3.5.3
This is the forty-eighth release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release and fully source-compatible with every 3.5.x release.
Warning
The 3.5.x series contains some changes that may be semantically breaking with respect to earlier 3.x releases. If you're using fs2, http4s, or other libraries from the ecosystem, make sure you've upgraded to versions of these libraries that are compatible with this release (for fs2, that's 3.7.0+, for http4s it's 0.23.19+)!
Additionally, if you're using methods like fromFuture
, make sure you're aware of the major changes to async
, described in these release notes.
What's Changed
Enhancements
- Optimize
Dispatcher#unsafeRunAndForget
by @kamilkloch in #3878 - Execute
IO.blocking
on WSTP withoutBlockContext
indirection by @armanbilge in #3903 - Reset auto-cede counter after
blocking
by @armanbilge in #3938 - Remove unneeded
notifyParked
when worker transitions to blocking by @armanbilge in #3937 - Implement
Fiber#join
viaasyncCheckAttempt
by @armanbilge, @samspills in #3942
Bug Fixes
- Fix cancelation leak in
fromFuture
,fromFutureCancelable
by @TimWSpence in #3892 - Fix #3898 for
Dispatcher.parallel
by @durban in #3900 - Immediately surface fatal errors in
IO.raiseError
by @scott-thomson239 in #3811 - Fix off-by-1 in
CallbackStack#pack
by @armanbilge in #3936 - Prevent
Hotswap#get
from acquiring a lock when there is noResource
present by @josgarmar28 in #3922 - Refactor
CallbackStack
based on new "pack locking" strategy by @armanbilge, @samspills, @mernst-github in #3943
Documentation
- Fix starvation demo app in tuning guide by @armanbilge in #3881
- Try to fix race condition in
Hotswap
example by @armanbilge in #3885 - Add note to starvation docs re: cpus in k8s by @Daenyth in #3750
- Add The Case For Effect Systems talk by @lenguyenthanh in #3905
Behind the Scenes
- Update versions for 3.5.2 by @armanbilge in #3857
- Release script improvements by @armanbilge in #3859
- Post release to Discord in CI by @armanbilge in #3855
- Tweak release notes config by @armanbilge, @samspills in #3951
- Decrease concurrency/replicas in
CallbackStackSpec
by @armanbilge, @samspills in #3952 - Update release.yml by @samspills in #3953
- Document release process by @armanbilge, @samspills in #3954
New Contributors
- @scott-thomson239 made their first contribution in #3811
- @josgarmar28 made their first contribution in #3922
Full Changelog: v3.5.2...v3.5.3
v3.5.2
This is the forty-seventh release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release and fully source-compatible with every 3.5.x release.
⚠️ Important note
The 3.5.x series contains some changes that may be semantically breaking with respect to earlier 3.x releases. If you're using fs2, http4s, or other libraries from the ecosystem, make sure you've upgraded to versions of these libraries that are compatible with this release (for fs2, that's 3.7.0+, for http4s it's 0.23.19+)!
Additionally, if you're using methods like fromFuture
, make sure you're aware of the major changes to async
, described in these release notes.
What's Changed
Features
- Optimize
liveTraces()
on JS by @armanbilge in #3724 - Elide thunk allocation when using
sleepInternal
by @armanbilge in #3775 - Remove
Thunk.asFunction0
utility by @armanbilge in #3788 - Print warning when we detect a non-main-thread main by @Daenyth in #3774
- Optimize
Dispatcher#{unsafeRunAsync,unsafeRunAndForget}
by @kamilkloch in #3822
Bug Fixes
- Fix
Hotswap#get
being blocked byHotswap#swap
by @forkedcancel in #3800 - Acquire exclusive lock before finalizing
Hotswap
by @armanbilge in #3841
Behind the Scenes
- Fix major branch PR in release script by @armanbilge in #3713
- Added script for automatically posting release to discord by @djspiewak in #3711
- Add release notes config by @armanbilge in #3710
- Remove unused code by @durban in #3729
- Allow that the renamed blocker thread is terminated by @aeons in #3728
- Dispatcher: test cleanup by @samspills in #3749
- update CI to use graalvm@17 by @samspills in #3773
- Cirrus CI cutbacks ... by @armanbilge in #3796
- Drop macOS jobs from Cirrus by @armanbilge in #3831
- Enough is Enough by @djspiewak in #3833
- Run Cirrus only for labeled PRs or tags by @armanbilge in #3842
- Updated versions script to look for
**
pattern by @djspiewak in #3843 - Try quoting labels in release notes config by @armanbilge in #3847
- Add catch-all category for unlabeled PRs by @armanbilge in #3854
Documentation
- Update versions for 3.5.1 by @armanbilge in #3718
- Fix typo by @durban in #3738
- update
Deferred#complete
type by @ag91 in #3740 - fix typo in tutorial by @vgrigoriu in #3760
- Explain "uhandled error" in
reportFailure
scaladoc by @kamilkloch in #3769 - Improve
MapRef
docs by @BalmungSan in #3829
New Contributors
- @ag91 made their first contribution in #3740
- @vgrigoriu made their first contribution in #3760
- @forkedcancel made their first contribution in #3800
Full Changelog: v3.5.1...v3.5.2
v3.5.1
This is the forty-sixth release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release and fully source-compatible with every 3.5.x release.
⚠️ Important note
The 3.5.x series contains some changes that may be semantically breaking with respect to earlier 3.x releases. If you're using fs2, http4s, or other libraries from the ecosystem, make sure you've upgraded to versions of these libraries that are compatible with this release (for fs2, that's 3.7.0+, for http4s it's 0.23.19+)!
Additionally, if you're using methods like fromFuture
, make sure you're aware of the major changes to async
, described in these release notes.
What's Changed
Bug Fixes
- Fix issue #3589 by @durban in #3622
- Don't use
object
forexecuteBatchTaskRunnable
by @armanbilge in #3642 - Catch exceptions in IOCont by @durban in #3670
- Directly get secure random data to array on native by @armanbilge in #3678
- Document that signals don't work for fiber dumps on JDK8 by @armanbilge in #3680
- Fix
queueMicrotask
polyfill by @armanbilge in #3693 - Cache
now
inWorkerThread
in states 4-63 by @djspiewak in #3690 - Dispatcher: remove
alive
in favour of nullifying queues by @samspills in #3701
Behind the Scenes
- Drafted version update script by @djspiewak in #3617
- Updated versions for 3.5.0 by @djspiewak in #3618
- Added script to automate the minor update pr by @djspiewak in #3624
- Implemented script for auto-updating the site following a release by @djspiewak in #3629
- Don't set
turbo := false
in Scastie by @armanbilge in #3631 - Remove workaround for
Scala3
inSupervisor
by @danicheg in #3650 - Increase timeout for windows configure-pagefile by @armanbilge in #3652
- Update to Scala Native v0.4.13 by @armanbilge in #3665
- Temporarily disable Cirrus ARM jobs by @armanbilge in #3705
Documentation
Full Changelog: v3.5.0...v3.5.1
v3.5.0
This is the forty-fifth release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release.
⚠️ Important note
This release contains some changes that may be semantically breaking. If you're using fs2, http4s, or other libraries from the ecosystem, make sure you've upgraded to versions of these libraries that are compatible with this release (for fs2, that's 3.7.0, for http4s it's 0.23.19)!
Additionally, if you're using methods like fromFuture
, make sure you're aware of the major changes to async
, described in these release notes.
This is an incredibly exciting release! 3.5.0 represents the very first steps towards a fully integrated runtime, with support for timers (IO.sleep
) built directly into the Cats Effect fiber runtime. This considerably increases performance for existing Cats Effect applications, but particularly those which rely more heavily on native IO
concurrency (e.g. Http4s Ember will see more benefits than Http4s Blaze).
Additionally, we've taken the opportunity presented by a minor release to fix some breaking semantic issues within some of the core IO
functionality, particularly related to async
. For most applications this should be essentially invisible, but it closes a long-standing loophole in the cancelation and backpressure model, ensuring a greater degree of safety in Cats Effect's guarantees.
Major Changes
Despite the deceptively short list of merged pull requests, this release contains an unusually large number of significant changes in runtime semantics. The changes in async
cancelation (and particularly the implications on async_
) are definitely expected to have user-facing impact, potentially breaking existing code in subtle ways. If you have any code which uses async_
(or async
) directly, you should read this section very carefully and potentially make the corresponding changes.
async
Cancelation Semantics
The IO.async
(and correspondingly, Async#async
) constructor takes a function which returns a value of type IO[Option[IO[Unit]]]
, with the Some
case indicating the finalizer which should be invoked if the fiber is canceled while asynchronously suspended at this precise point, and None
indicating that there is no finalizer for the current asynchronous suspension. This mechanism is most commonly used for "unregister" functions. For example, consider the following reimplementation of the sleep
constructor:
def sleep(time: FiniteDuration, executor: ScheduledExecutorService): IO[Unit] =
IO.async[Unit] { cb =>
IO {
val f = executor.schedule(() => cb(Right(())), time.toNanos, TimeUnit.NANOSECONDS)
Some(IO(f.cancel()))
}
}
In the above, the IO
returned from sleep
will suspend for time
. If its fiber is canceled, the f.cancel()
function will be invoked (on ScheduledFuture
), which in turn removes the Runnable
from the ScheduledExecutorService
, avoiding memory leaks and such. If we had instead returned None
from the registration effect, there would have been no finalizer and no way for fiber cancelation to clean up the stray ScheduledFuture
.
The entirety of Cats Effect's design is prescriptively oriented around safe cancelation. If Cats Effect cannot guarantee that a resource is safely released, it will prevent cancelation from short-circuiting until execution proceeds to a point at which all finalization is safe. This design does have some tradeoffs (it can lead to deadlocks in poorly behaved programs), but it has the helpful outcome of strictly avoiding resource leaks, either due to incorrect finalization or circumvented backpressure.
...except in IO.async
. Prior to 3.5.0, defining an async
effect without a finalizer (i.e. producing None
) resulted in an effect which could be canceled unconditionally, without the invocation of any finalizer. This was most seriously felt in the async_
convenience constructor, which always returns None
. Unfortunately, this semantic is very much the wrong default. It makes the assumption that the normal case for async
is that the callback just cleans itself up (somehow) and no unregistration is possible or necessary. In almost all cases, the opposite is true.
It is exceptionally rare, in fact, for an async
effect to not have an obvious finalizer. By defining the default in this fashion, Cats Effect made it very easy to engineer resource leaks and backpressure loss. This loophole is now closed, both in the IO
implementation and in the laws which govern its behavior.
As of 3.5.0, the following is now considered to be uncancelable:
IO.async[A] { cb =>
IO {
// ...
None // we aren't returning a finalizer
}
}
Previously, the above was cancelable without any caveats. Notably, this applies to all uses of the async_
constructor!
In practice, we expect that usage of the async
constructor which was already well behaved will be unaffected by this change. However, any use which is (possibly unintentionally) relying on the old semantic will break, potentially resulting in deadlock as a cancelation which was previously observed will now be suppressed until the async
completes. For this reason, users are advised to carefully audit their use of async
to ensure that they always return Some(...)
with the appropriate finalizer that unregisters their callback.
In the event that you need to restore the previous semantics, they can be approximated by producing Some(IO.unit)
from the registration. This is a very rare situation, but it does arise in some cases. For example, the definition of IO.never
had to be adjusted to the following:
def never: IO[Nothing] =
IO.async(_ => IO.pure(Some(IO.unit))) // was previously IO.pure(None)
This change can result in some very subtle consequences. If you find unexpected effects in your application after upgrading to 3.5.0, you should start your investigation with this change! (note that this change also affects third-party libraries using async
, even if they have themselves not yet updated to 3.5.0 or higher!)
Integrated Timers
From the very beginning, Cats Effect and applications built on top of it have managed timers (i.e. IO.sleep
and everything built on top of it) on the JVM by using a separate thread pool. In particular, ScheduledExecutorService
. This is an extremely standard approach used prolifically by almost all JVM applications. Unfortunately, it is also fundamentally suboptimal.
The problem stems from the fact that ScheduledExecutorService
isn't magic. It works by maintaining one or more event dispatch threads which interrogate a data structure containing all active timers. If any timers have passed their expiry, the thread invokes their Runnable
. If no timers are expired, the thread blocks for the minimum time until the next timer becomes available. In its default configuration, the Cats Effect runtime provisions exactly one event dispatch thread for this purpose.
This isn't so bad when an application makes very little use of timers, since the thread in question will spend almost all of its time blocked, doing nothing. This affects timeslice granularity within the OS kernel and adds an additional GC root, but both effects are small enough that they are usually unnoticed. The bigger problem comes when an application is using a lot of timers and the thread is constantly busy reading that data structure and dispatching the next set of Runnable
(s) (all of which complete async
s and immediately shift back into the Cats Effect compute pool).
Unfortunately, this situation where a lot of timers are in use is exactly what happens in every network application, since each and every active socket must have at least one IO.sleep
associated with it to time out handling if the remote side stops responding (in most cases, such as HTTP, even more than one timer is needed). In other words, the fact that IO.sleep
is relatively inefficient when a lot of concurrent sleep
s are scheduled is particularly egregiously bad, since this is precisely the situation that describes most real-world usage of Cats Effect.
So we made this better! Cats Effect 3.5.0 introduces a new implementation of timers based on cooperative polling, which is basically the idea that timers can be dispatched and handled entirely by the same threads which handle compute work. Every time a compute worker thread runs out of work to do (and has nothing to steal), rather than just parking and waiting for more work, it first checks to see if there are any outstanding timers. If there are some which are ready to run, it runs them. Otherwise, if there are timers which aren't yet completed, the worker parks for that period of time (or until awakened by new work), ensuring the timer fires on schedule. In the event that a worker has not had the opportunity to park in some number of iterations, it proactively checks on its timers just to see if any have expired while it has been busy doing CPU-bound work.
This technique works extremely well in Cats Effect precisely because every timer had to shift back to the compute pool anyway, meaning that it was already impossible for any timer to have a granularity which was finer than that of the compute worker thread task queue. Thus, having that same task queue manage the dispatching of the timers themselves ensures that at worst those timers run with the same precision as previously, and at best we are able to avoid a considerable amount of overhead both in the form of OS kernel scheduler contention (since we are removing a whole thread from ...
v3.4.11
This is the forty-fourth release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release. It is fully binary compatible with every 3.x release, and fully source-compatible with every 3.4.x release. Note that source compatibility has been broken with 3.3.x in some minor areas. Since those changes require active choice on the part of users to decide the best adjusted usage for their specific scenario, we have chosen to not provide scalafixes which automatically patch the affected call sites.
User-Facing Pull Requests
Thank you, Daniel!
v3.5.0-RC5
This is the forty-third release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release. It is expected to be fully source- and binary-compatible with the final version of 3.5.0, but there are no guarantees of such.
As with all release candidates, we are not aware of any bugs or issues preventing production use, but we are making this release precisely because we know that the changes in this version are of a sufficiently significant nature as to benefit from broader testing and experimentation across the ecosystem before we incorporate them into a stable release. If you have the time, please do take a moment to try this version in your library or service and see how things work!
For the full, cumulative list of changes in the 3.5.0 release, please also see the release notes for RC1, RC2, RC3, and RC4. This list only encompasses the changes from RC4 to RC5 (not including changes already released and ported from the 3.4.x line).
User-Facing Pull Requests
- #3562 – New (old)
AsyncMutex
implementation (@BalmungSan) - #3567 – Make
blockedThreadDetectionEnabled
configurable via a system property (@chunjef) - #3549, #3555 – Fix mutex cancelled acquire (@durban)
Thank you so much!
v3.4.10
This is the forty-second release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release. It is fully binary compatible with every 3.x release, and fully source-compatible with every 3.4.x release. Note that source compatibility has been broken with 3.3.x in some minor areas. Since those changes require active choice on the part of users to decide the best adjusted usage for their specific scenario, we have chosen to not provide scalafixes which automatically patch the affected call sites.
User-Facing Pull Requests
Very special thanks to all!
v3.5.0-RC4
This is the forty-first release in the Cats Effect 3.x lineage. It is fully binary compatible with every 3.x release. It is expected to be fully source- and binary-compatible with the final version of 3.5.0, but there are no guarantees of such.
As with all release candidates, we are not aware of any bugs or issues preventing production use, but we are making this release precisely because we know that the changes in this version are of a sufficiently significant nature as to benefit from broader testing and experimentation across the ecosystem before we incorporate them into a stable release. If you have the time, please do take a moment to try this version in your library or service and see how things work!
Far and away the most significant change in this release is the rewriting of the timer data structure within WorkerThread
(courtesy of @durban!). This results in significantly higher sleep
performance, particularly under load when most timers are being canceled. If you previously tested an earlier RC and saw issues with these types of scenarios, we recommend you take another look using this latest RC!
For the full, cumulative list of changes in the 3.5.0 release, please also see the release notes for RC1, RC2, and RC3. This list only encompasses the changes from RC3 to RC4 (not including changes already released and ported from the 3.4.x line).
User-Facing Pull Requests
- #3499 – Shared timers (@durban)
- #3518 –
AtomicCell#get
should not semantically block (@armanbilge) - #3465 – Make
Console#readLine
cancelable (@armanbilge) - #3435 – Further optimize
IODeferred
(@armanbilge) - #3480 – Make
HotSwap
safe to concurrent access (@armanbilge) - #3484 – Allow that the renamed blocker thread is terminated (@aeons)
- #3478 – Fix
IORuntimeBuilder
failureReporter config on JS (@armanbilge) - #3477, #3479 – Documentation fixes and improvements (@amast09, @durban)
Thank you so much!