From 2b051562d150ee8bccf4e6db394a55e6a44df99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20Mej=C3=ADa=20Su=C3=A1rez?= Date: Fri, 15 Sep 2023 12:35:33 -0500 Subject: [PATCH 01/13] Improve MapRef docs --- kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala | 6 +++++- std/shared/src/main/scala/cats/effect/std/MapRef.scala | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala b/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala index 2951b9af6e..46148f70ef 100644 --- a/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala +++ b/kernel/shared/src/main/scala/cats/effect/kernel/Ref.scala @@ -34,7 +34,11 @@ import cats.syntax.all._ * mutable data as `AtomicReference#compareAndSet` and friends are dependent upon object * reference equality. * - * See also `cats.effect.std.AtomicCell` class from `cats-effect-std` for an alternative. + * See also `cats.effect.std.AtomicCell` class from `cats-effect-std` for an alternative that + * ensures exclusive access and effectual updates. + * + * If your contents are an immutable `Map[K, V]`, and all your operations are per-key, consider + * using `cats.effect.std.MapRef`. */ abstract class Ref[F[_], A] extends RefSource[F, A] with RefSink[F, A] { diff --git a/std/shared/src/main/scala/cats/effect/std/MapRef.scala b/std/shared/src/main/scala/cats/effect/std/MapRef.scala index 6cc723b396..8d3f9ffa5c 100644 --- a/std/shared/src/main/scala/cats/effect/std/MapRef.scala +++ b/std/shared/src/main/scala/cats/effect/std/MapRef.scala @@ -26,8 +26,12 @@ import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.atomic.AtomicBoolean /** - * This is a total map from K to Ref[F, V]. This allows us to use the Ref API backed by a - * ConcurrentHashMap or similar. + * This is a total map from `K` to `Ref[F, V]`. + * + * It is conceptually similar to a `Ref[F, Map[K, V]]`, but with better ergonomics when working + * on a per key basis. It also has less contention since the key-value pairs are sharded; thus + * multiple concurrent updates may be performed independently to each other. Note, however, that + * it does not support atomic updates to multiple keys. */ trait MapRef[F[_], K, V] extends Function1[K, Ref[F, V]] { From cc0bc86920ed1c9ec38f7bf65dcf7411e2d7a46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20Mej=C3=ADa=20Su=C3=A1rez?= Date: Fri, 15 Sep 2023 12:51:08 -0500 Subject: [PATCH 02/13] Re-word the contention point --- std/shared/src/main/scala/cats/effect/std/MapRef.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/std/shared/src/main/scala/cats/effect/std/MapRef.scala b/std/shared/src/main/scala/cats/effect/std/MapRef.scala index 8d3f9ffa5c..2dddf7386c 100644 --- a/std/shared/src/main/scala/cats/effect/std/MapRef.scala +++ b/std/shared/src/main/scala/cats/effect/std/MapRef.scala @@ -29,9 +29,12 @@ import java.util.concurrent.atomic.AtomicBoolean * This is a total map from `K` to `Ref[F, V]`. * * It is conceptually similar to a `Ref[F, Map[K, V]]`, but with better ergonomics when working - * on a per key basis. It also has less contention since the key-value pairs are sharded; thus - * multiple concurrent updates may be performed independently to each other. Note, however, that - * it does not support atomic updates to multiple keys. + * on a per key basis. Note, however, that it does not support atomic updates to multiple keys. + * + * Additionally, some implementations also provide less contention, since all operations are + * performed over individual key-value pairs, those could be sharded. Thus, multiple concurrent + * updates may be executed independently to each other; as long as their keys belong to + * different shards. */ trait MapRef[F[_], K, V] extends Function1[K, Ref[F, V]] { From b72aaeca7b3077927eca578608ce61b6e34deecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20Mej=C3=ADa=20Su=C3=A1rez?= Date: Fri, 15 Sep 2023 13:08:17 -0500 Subject: [PATCH 03/13] Add simple MapRef docs page --- docs/std/mapref.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 docs/std/mapref.md diff --git a/docs/std/mapref.md b/docs/std/mapref.md new file mode 100644 index 0000000000..8a755b2483 --- /dev/null +++ b/docs/std/mapref.md @@ -0,0 +1,60 @@ +--- +id: mapref +title: MapRef +--- + +A total map from a key to a `Ref` of its value. + +```scala mdoc:silent +trait MapRef[F[_], K, V] { + + /** + * Access the reference for this Key + */ + def apply(k: K): Ref[F, V] +} +``` + +It is conceptually similar to a `Ref[F, Map[K, V]]`, +but with better ergonomics when working on a per key basis. +Note, however, that it does not support atomic updates to multiple keys. + +Additionally, some implementations also provide less contention, +since all operations are performed over individual key-value pairs, +those could be sharded. +Thus, multiple concurrent updates may be executed independently to each other; +as long as their keys belong to different shards. + +### In-Memory database + +This is probably one of the most common uses of this tool. + +```scala mdoc:reset:silent +//> using lib "org.typelevel::cats-effect:3.4.11" + +import cats.effect.IO +import cats.effect.std.MapRef + +type Id +type Data + +trait DatabaseClient[F[_]] { + def getDataById(id: Id): F[Option[Data]] + def upsertData(id: Id, data: Data): F[Unit] +} + +object DatabaseClient { + def inMemory: IO[DatabaseClient[IO]] = + MapRef.ofShardedImmutableMap[IO, Id, Data]( + shardCount = 5 // Arbitrary number of shards just for demonstration. + ).map { mapRef => + new DatabaseClient[IO] { + override def getDataById(id: Id): F[Option[Data]] = + mapRef(id).get + + override def upsertData(id: Id, data: Data): F[Unit] = + mapRef(id).update(_ => Some(data)) + } + } +} +``` From 0385b342fa22d8a82c461109841ed6030065de40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20Mej=C3=ADa=20Su=C3=A1rez?= Date: Fri, 15 Sep 2023 16:32:18 -0500 Subject: [PATCH 04/13] Update docs/std/mapref.md Co-authored-by: Amund Murstad --- docs/std/mapref.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/std/mapref.md b/docs/std/mapref.md index 8a755b2483..55ab03cbfd 100644 --- a/docs/std/mapref.md +++ b/docs/std/mapref.md @@ -49,10 +49,10 @@ object DatabaseClient { shardCount = 5 // Arbitrary number of shards just for demonstration. ).map { mapRef => new DatabaseClient[IO] { - override def getDataById(id: Id): F[Option[Data]] = + override def getDataById(id: Id): IO[Option[Data]] = mapRef(id).get - override def upsertData(id: Id, data: Data): F[Unit] = + override def upsertData(id: Id, data: Data): IO[Unit] = mapRef(id).update(_ => Some(data)) } } From bc3bb0cb7daa32a73e286a0aeb586c0f8bc9a35f Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Thu, 21 Sep 2023 03:29:14 +0000 Subject: [PATCH 05/13] Acquire exclusive lock before finalizing `Hotswap` --- .../main/scala/cats/effect/std/Hotswap.scala | 15 ++++++++------- .../scala/cats/effect/std/HotswapSpec.scala | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/std/shared/src/main/scala/cats/effect/std/Hotswap.scala b/std/shared/src/main/scala/cats/effect/std/Hotswap.scala index 454744b4ba..de6838c9d0 100644 --- a/std/shared/src/main/scala/cats/effect/std/Hotswap.scala +++ b/std/shared/src/main/scala/cats/effect/std/Hotswap.scala @@ -103,6 +103,12 @@ object Hotswap { */ def create[F[_], R](implicit F: Concurrent[F]): Resource[F, Hotswap[F, R]] = Resource.eval(Semaphore[F](Long.MaxValue)).flatMap { semaphore => + def shared: Resource[F, Unit] = semaphore.permit + + def exclusive: Resource[F, Unit] = + Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => + semaphore.releaseN(Long.MaxValue)) + sealed abstract class State case object Cleared extends State case class Acquired(r: R, fin: F[Unit]) extends State @@ -111,22 +117,17 @@ object Hotswap { def initialize: F[Ref[F, State]] = F.ref(Cleared) - def finalize(state: Ref[F, State]): F[Unit] = + def finalize(state: Ref[F, State]): F[Unit] = exclusive.surround { state.getAndSet(Finalized).flatMap { case Acquired(_, finalizer) => finalizer case Cleared => F.unit case Finalized => raise("Hotswap already finalized") } + } def raise(message: String): F[Unit] = F.raiseError[Unit](new RuntimeException(message)) - def shared: Resource[F, Unit] = semaphore.permit - - def exclusive: Resource[F, Unit] = - Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => - semaphore.releaseN(Long.MaxValue)) - Resource.make(initialize)(finalize).map { state => new Hotswap[F, R] { diff --git a/tests/shared/src/test/scala/cats/effect/std/HotswapSpec.scala b/tests/shared/src/test/scala/cats/effect/std/HotswapSpec.scala index 550e3b0222..c335d7782e 100644 --- a/tests/shared/src/test/scala/cats/effect/std/HotswapSpec.scala +++ b/tests/shared/src/test/scala/cats/effect/std/HotswapSpec.scala @@ -97,6 +97,23 @@ class HotswapSpec extends BaseSpec { outer => go must completeAs(()) } + "not finalize Hotswap while resource is in use" in ticked { implicit ticker => + val r = Resource.make(IO.ref(true))(_.set(false)) + val go = Hotswap.create[IO, Ref[IO, Boolean]].allocated.flatMap { + case (hs, fin) => + hs.swap(r) *> (IO.sleep(1.second) *> fin).background.surround { + hs.get.use { + case Some(ref) => + val notReleased = ref.get.flatMap(b => IO(b must beTrue)) + notReleased *> IO.sleep(2.seconds) *> notReleased.void + case None => IO(false must beTrue).void + } + } + } + + go must completeAs(()) + } + "resource can be accessed concurrently" in ticked { implicit ticker => val go = Hotswap.create[IO, Unit].use { hs => hs.swap(Resource.unit) *> From 2b1f5373611789f1722e939a83549e0837ac6151 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 20 Sep 2023 20:55:38 -0700 Subject: [PATCH 06/13] Scope lock acquisition more tightly --- std/shared/src/main/scala/cats/effect/std/Hotswap.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/std/shared/src/main/scala/cats/effect/std/Hotswap.scala b/std/shared/src/main/scala/cats/effect/std/Hotswap.scala index de6838c9d0..58253bdd7e 100644 --- a/std/shared/src/main/scala/cats/effect/std/Hotswap.scala +++ b/std/shared/src/main/scala/cats/effect/std/Hotswap.scala @@ -117,13 +117,12 @@ object Hotswap { def initialize: F[Ref[F, State]] = F.ref(Cleared) - def finalize(state: Ref[F, State]): F[Unit] = exclusive.surround { + def finalize(state: Ref[F, State]): F[Unit] = state.getAndSet(Finalized).flatMap { - case Acquired(_, finalizer) => finalizer + case Acquired(_, finalizer) => exclusive.surround(finalizer) case Cleared => F.unit case Finalized => raise("Hotswap already finalized") } - } def raise(message: String): F[Unit] = F.raiseError[Unit](new RuntimeException(message)) From 7d73c7398c227d1fe9482355c2425ea1d2424c5c Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Fri, 22 Sep 2023 01:30:36 +0000 Subject: [PATCH 07/13] Revert spurious changes --- .../src/main/scala/cats/effect/std/Hotswap.scala | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/std/shared/src/main/scala/cats/effect/std/Hotswap.scala b/std/shared/src/main/scala/cats/effect/std/Hotswap.scala index 58253bdd7e..cf68fb204d 100644 --- a/std/shared/src/main/scala/cats/effect/std/Hotswap.scala +++ b/std/shared/src/main/scala/cats/effect/std/Hotswap.scala @@ -103,12 +103,6 @@ object Hotswap { */ def create[F[_], R](implicit F: Concurrent[F]): Resource[F, Hotswap[F, R]] = Resource.eval(Semaphore[F](Long.MaxValue)).flatMap { semaphore => - def shared: Resource[F, Unit] = semaphore.permit - - def exclusive: Resource[F, Unit] = - Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => - semaphore.releaseN(Long.MaxValue)) - sealed abstract class State case object Cleared extends State case class Acquired(r: R, fin: F[Unit]) extends State @@ -127,6 +121,12 @@ object Hotswap { def raise(message: String): F[Unit] = F.raiseError[Unit](new RuntimeException(message)) + def shared: Resource[F, Unit] = semaphore.permit + + def exclusive: Resource[F, Unit] = + Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => + semaphore.releaseN(Long.MaxValue)) + Resource.make(initialize)(finalize).map { state => new Hotswap[F, R] { From 58a0ffc42c51b0e57f126457169b1d395cde6a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20Mej=C3=ADa=20Su=C3=A1rez?= Date: Sun, 24 Sep 2023 10:48:44 -0500 Subject: [PATCH 08/13] Apply review comments --- docs/std/mapref.md | 12 ++++++------ .../src/main/scala/cats/effect/std/MapRef.scala | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/std/mapref.md b/docs/std/mapref.md index 55ab03cbfd..4705f23fbe 100644 --- a/docs/std/mapref.md +++ b/docs/std/mapref.md @@ -19,18 +19,18 @@ It is conceptually similar to a `Ref[F, Map[K, V]]`, but with better ergonomics when working on a per key basis. Note, however, that it does not support atomic updates to multiple keys. -Additionally, some implementations also provide less contention, -since all operations are performed over individual key-value pairs, -those could be sharded. -Thus, multiple concurrent updates may be executed independently to each other; +Additionally, some implementations also provide less contention: +since all operations are performed on individual key-value pairs, +the pairs can be sharded by key. +Thus, multiple concurrent updates may be executed independently to each other, as long as their keys belong to different shards. ### In-Memory database -This is probably one of the most common uses of this tool. +This is probably one of the most common uses of this datatype. ```scala mdoc:reset:silent -//> using lib "org.typelevel::cats-effect:3.4.11" +//> using lib "org.typelevel::cats-effect:3.5.1" import cats.effect.IO import cats.effect.std.MapRef diff --git a/std/shared/src/main/scala/cats/effect/std/MapRef.scala b/std/shared/src/main/scala/cats/effect/std/MapRef.scala index 2dddf7386c..cc4c7d97e5 100644 --- a/std/shared/src/main/scala/cats/effect/std/MapRef.scala +++ b/std/shared/src/main/scala/cats/effect/std/MapRef.scala @@ -31,10 +31,10 @@ import java.util.concurrent.atomic.AtomicBoolean * It is conceptually similar to a `Ref[F, Map[K, V]]`, but with better ergonomics when working * on a per key basis. Note, however, that it does not support atomic updates to multiple keys. * - * Additionally, some implementations also provide less contention, since all operations are - * performed over individual key-value pairs, those could be sharded. Thus, multiple concurrent - * updates may be executed independently to each other; as long as their keys belong to - * different shards. + * Additionally, some implementations also provide less contention: since all operations are + * performed on individual key-value pairs, the pairs can be sharded by key. Thus, multiple + * concurrent updates may be executed independently to each other, as long as their keys belong + * to different shards. */ trait MapRef[F[_], K, V] extends Function1[K, Ref[F, V]] { From b933ebd1f35edfc22312b0e85480477ad88a62f3 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Mon, 25 Sep 2023 12:18:07 -0700 Subject: [PATCH 09/13] Try quoting labels in release notes config [ci skip] --- .github/release.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/release.yml b/.github/release.yml index 6dc5f68c19..7d789f6234 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -2,14 +2,14 @@ changelog: categories: - title: Features labels: - - :mushroom: enhancement + - ':mushroom: enhancement' - title: Bug Fixes labels: - - :beetle: bug + - ':beetle: bug' - title: Behind the Scenes labels: - - :gear: infrastructure - - :robot: + - ':gear: infrastructure' + - ':robot:' - title: Documentation labels: - - :books: docs + - ':books: docs' From 33c93b1e7dab50fcfd64571076446e57fb208923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Miguel=20Mej=C3=ADa=20Su=C3=A1rez?= Date: Mon, 25 Sep 2023 21:28:01 -0500 Subject: [PATCH 10/13] Fix mdoc compilation error --- docs/std/mapref.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/std/mapref.md b/docs/std/mapref.md index 4705f23fbe..3b4266d082 100644 --- a/docs/std/mapref.md +++ b/docs/std/mapref.md @@ -6,6 +6,8 @@ title: MapRef A total map from a key to a `Ref` of its value. ```scala mdoc:silent +import cats.effect.Ref + trait MapRef[F[_], K, V] { /** @@ -35,20 +37,17 @@ This is probably one of the most common uses of this datatype. import cats.effect.IO import cats.effect.std.MapRef -type Id -type Data - -trait DatabaseClient[F[_]] { +trait DatabaseClient[F[_], Id, Data] { def getDataById(id: Id): F[Option[Data]] def upsertData(id: Id, data: Data): F[Unit] } object DatabaseClient { - def inMemory: IO[DatabaseClient[IO]] = + def inMemory[Id, Data]: IO[DatabaseClient[IO, Id, Data]] = MapRef.ofShardedImmutableMap[IO, Id, Data]( shardCount = 5 // Arbitrary number of shards just for demonstration. ).map { mapRef => - new DatabaseClient[IO] { + new DatabaseClient[IO, Id, Data] { override def getDataById(id: Id): IO[Option[Data]] = mapRef(id).get From 3847eb1b2f037b15f150b93fafc06e0e83f99f43 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Tue, 26 Sep 2023 11:54:59 -0700 Subject: [PATCH 11/13] Add catch-all category for unlabeled PRs [ci skip] --- .github/release.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/release.yml b/.github/release.yml index 7d789f6234..2c49e97bcd 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -13,3 +13,7 @@ changelog: - title: Documentation labels: - ':books: docs' + # Not for published notes, just to make sure we don't forget any accidentally unlabeled PRs + - title: Uncategorized + labels: + - '*' From 077e52aadff7f71e4081fcad97f5689870a7eace Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Wed, 27 Sep 2023 17:16:04 -0700 Subject: [PATCH 12/13] Update versions for 3.5.2 --- README.md | 14 +++++++------- docs/core/native-image.md | 2 +- docs/core/scala-native.md | 2 +- docs/core/test-runtime.md | 2 +- docs/getting-started.md | 2 +- docs/migration-guide.md | 8 ++++---- docs/tutorial.md | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index b167aa2390..785f456725 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,11 @@ ## Getting Started -- Wired: **3.5.1** +- Wired: **3.5.2** - Tired: **2.5.5** (end of life) ```scala -libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.1" +libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.2" ``` The above represents the core, stable dependency which brings in the entirety of Cats Effect. This is *most likely* what you want. All current Cats Effect releases are published for Scala 2.12, 2.13, 3.0, and Scala.js 1.7. @@ -30,22 +30,22 @@ Depending on your use-case, you may want to consider one of the several other mo ```scala libraryDependencies ++= Seq( - "org.typelevel" %% "cats-effect-kernel" % "3.5.1", - "org.typelevel" %% "cats-effect-laws" % "3.5.1" % Test) + "org.typelevel" %% "cats-effect-kernel" % "3.5.2", + "org.typelevel" %% "cats-effect-laws" % "3.5.2" % Test) ``` If you're a middleware framework (like [Fs2](https://fs2.io/)), you probably want to depend on **std**, which gives you access to `Queue`, `Semaphore`, and much more without introducing a hard-dependency on `IO` outside of your tests: ```scala libraryDependencies ++= Seq( - "org.typelevel" %% "cats-effect-std" % "3.5.1", - "org.typelevel" %% "cats-effect" % "3.5.1" % Test) + "org.typelevel" %% "cats-effect-std" % "3.5.2", + "org.typelevel" %% "cats-effect" % "3.5.2" % Test) ``` You may also find some utility in the **testkit** and **kernel-testkit** projects, which contain `TestContext`, generators for `IO`, and a few other things: ```scala -libraryDependencies += "org.typelevel" %% "cats-effect-testkit" % "3.5.1" % Test +libraryDependencies += "org.typelevel" %% "cats-effect-testkit" % "3.5.2" % Test ``` Cats Effect provides backward binary compatibility within the 2.x and 3.x version lines, and both forward and backward compatibility within any major/minor line. This is analogous to the versioning scheme used by Cats itself, as well as other major projects such as Scala.js. Thus, any project depending upon Cats Effect 2.2.1 can be used with libraries compiled against Cats Effect 2.0.0 or 2.2.3, but *not* with libraries compiled against 2.3.0 or higher. diff --git a/docs/core/native-image.md b/docs/core/native-image.md index 237a70351a..0fefa4e45d 100644 --- a/docs/core/native-image.md +++ b/docs/core/native-image.md @@ -33,7 +33,7 @@ ThisBuild / scalaVersion := "2.13.8" lazy val root = (project in file(".")).enablePlugins(NativeImagePlugin).settings( name := "cats-effect-3-hello-world", - libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.1", + libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.2", Compile / mainClass := Some("com.example.Main"), nativeImageOptions += "--no-fallback", nativeImageVersion := "22.1.0" // It should be at least version 21.0.0 diff --git a/docs/core/scala-native.md b/docs/core/scala-native.md index d146d72fb4..7bceac890a 100644 --- a/docs/core/scala-native.md +++ b/docs/core/scala-native.md @@ -22,7 +22,7 @@ lazy val root = project.in(file(".")) .enablePlugins(ScalaNativePlugin) .settings( name := "cats-effect-3-hello-world", - libraryDependencies += "org.typelevel" %%% "cats-effect" % "3.5.1", + libraryDependencies += "org.typelevel" %%% "cats-effect" % "3.5.2", Compile / mainClass := Some("com.example.Main") ) diff --git a/docs/core/test-runtime.md b/docs/core/test-runtime.md index be1e17f199..a6c8746e4c 100644 --- a/docs/core/test-runtime.md +++ b/docs/core/test-runtime.md @@ -28,7 +28,7 @@ For those migrating code from Cats Effect 2, `TestControl` is a considerably mor In order to use `TestControl`, you will need to bring in the **cats-effect-testkit** dependency: ```scala -libraryDependencies += "org.typelevel" %% "cats-effect-testkit" % "3.5.1" % Test +libraryDependencies += "org.typelevel" %% "cats-effect-testkit" % "3.5.2" % Test ``` ## Example diff --git a/docs/getting-started.md b/docs/getting-started.md index 8ad0bc3fe6..8eae7764a7 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -6,7 +6,7 @@ title: Getting Started Add the following to your **build.sbt**: ```scala -libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.1" +libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.2" ``` Naturally, if you're using ScalaJS, you should replace the double `%%` with a triple `%%%`. If you're on Scala 2, it is *highly* recommended that you enable the [better-monadic-for](https://github.com/oleg-py/better-monadic-for) plugin, which fixes a number of surprising elements of the `for`-comprehension syntax in the Scala language: diff --git a/docs/migration-guide.md b/docs/migration-guide.md index 9fa8838271..33eae63039 100644 --- a/docs/migration-guide.md +++ b/docs/migration-guide.md @@ -81,9 +81,9 @@ Cats Effect 3 splits the code dependency into multiple modules. If you were prev The current non-test modules are: ```scala -"org.typelevel" %% "cats-effect-kernel" % "3.5.1", -"org.typelevel" %% "cats-effect-std" % "3.5.1", -"org.typelevel" %% "cats-effect" % "3.5.1", +"org.typelevel" %% "cats-effect-kernel" % "3.5.2", +"org.typelevel" %% "cats-effect-std" % "3.5.2", +"org.typelevel" %% "cats-effect" % "3.5.2", ``` - `kernel` - type class definitions, simple concurrency primitives @@ -96,7 +96,7 @@ The current non-test modules are: libraryDependencies ++= Seq( //... - "org.typelevel" %% "cats-effect" % "2.4.0", -+ "org.typelevel" %% "cats-effect" % "3.5.1", ++ "org.typelevel" %% "cats-effect" % "3.5.2", //... ) ``` diff --git a/docs/tutorial.md b/docs/tutorial.md index 4f8b48cf99..ffdf9c3e87 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -42,11 +42,11 @@ running the code snippets in this tutorial, it is recommended to use the same ```scala name := "cats-effect-tutorial" -version := "3.5.1" +version := "3.5.2" scalaVersion := "2.13.6" -libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.1" withSources() withJavadoc() +libraryDependencies += "org.typelevel" %% "cats-effect" % "3.5.2" withSources() withJavadoc() scalacOptions ++= Seq( "-feature", From 7dfe45de87ba0da7b9f760133a0e79311db1db5a Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Thu, 28 Sep 2023 00:24:27 +0000 Subject: [PATCH 13/13] Update more versions --- docs/faq.md | 2 +- docs/getting-started.md | 2 +- docs/std/mapref.md | 2 +- docs/std/ref.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index d19089559c..2720afe6ab 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -9,7 +9,7 @@ title: FAQ ```scala-cli //> using scala "2.13.8" -//> using lib "org.typelevel::cats-effect::3.4.11" +//> using lib "org.typelevel::cats-effect::3.5.2" import cats.effect._ diff --git a/docs/getting-started.md b/docs/getting-started.md index 8eae7764a7..eff54fead0 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -62,7 +62,7 @@ We will learn more about constructs like `start` and `*>` in later pages, but fo Of course, the easiest way to play with Cats Effect is to try it out in a Scala REPL. We recommend using [Ammonite](https://ammonite.io/#Ammonite-REPL) for this kind of thing. To get started, run the following lines (if not using Ammonite, skip the first line and make sure that Cats Effect and its dependencies are correctly configured on the classpath): ```scala -import $ivy.`org.typelevel::cats-effect:3.4.11` +import $ivy.`org.typelevel::cats-effect:3.5.2` import cats.effect.unsafe.implicits._ import cats.effect.IO diff --git a/docs/std/mapref.md b/docs/std/mapref.md index 3b4266d082..54535d2411 100644 --- a/docs/std/mapref.md +++ b/docs/std/mapref.md @@ -32,7 +32,7 @@ as long as their keys belong to different shards. This is probably one of the most common uses of this datatype. ```scala mdoc:reset:silent -//> using lib "org.typelevel::cats-effect:3.5.1" +//> using lib "org.typelevel::cats-effect::3.5.2" import cats.effect.IO import cats.effect.std.MapRef diff --git a/docs/std/ref.md b/docs/std/ref.md index 259d208558..b4c7cc5892 100644 --- a/docs/std/ref.md +++ b/docs/std/ref.md @@ -33,7 +33,7 @@ This is probably one of the most common uses of this concurrency primitive. In this example, the workers will concurrently run and update the value of the `Ref`. ```scala mdoc:reset:silent -//> using lib "org.typelevel::cats-effect:3.4.11" +//> using lib "org.typelevel::cats-effect::3.5.2" import cats.effect.{IO, IOApp, Sync} import cats.effect.kernel.Ref