Repository: http4s/http4s
Pull request #6805 (2022-11-13 16:34:32)

Update cats-effect, cats-effect-std, ... to 3.4.0 in series/0.23
Updates 
* [org.typelevel:cats-effect](https://github.com/typelevel/cats-effect)
* [org.typelevel:cats-effect-std](https://github.com/typelevel/cats-effect)
* [org.typelevel:cats-effect-testkit](https://github.com/typelevel/cats-effect)

 from 3.3.14 to 3.4.0.
[GitHub Release Notes](https://github.com/typelevel/cats-effect/releases/tag/v3.4.0) - [Version Diff](https://github.com/typelevel/cats-effect/compare/v3.3.14...v3.4.0)

I'll automatically update this PR to resolve conflicts as long as you don't change it yourself.

If you'd like to skip this version, you can just close this PR. If you have any feedback, just mention me in the comments below.

Configure Scala Steward for your repository with a [`.scala-steward.conf`](https://github.com/scala-steward-org/scala-steward/blob/e93966d6d80e4ff1b31567984aa7e70e11cb2070/docs/repo-specific-configuration.md) file.

Have a fantastic day writing Scala!

<details>
<summary>Files still referring to the old version number</summary>

The following files still refer to the old version number (3.3.14).
You might want to review and update them manually.
```
docs/changelog.md
```
</details>
<details>
<summary>Adjust future updates</summary>

Add this to your `.scala-steward.conf` file to ignore future updates of this dependency:
```
updates.ignore = [ { groupId = "org.typelevel" } ]
```
Or, add this to slow down future updates of this dependency:
```
dependencyOverrides = [{
  pullRequests = { frequency = "@monthly" },
  dependency = { groupId = "org.typelevel" }
}]
```
</details>

labels: library-update, early-semver-minor, semver-spec-minor, old-version-remains, commit-count:1


Patch:
diff --git a/client/js/src/main/scala/org/http4s/client/NodeJSClientBuilder.scala b/client/js/src/main/scala/org/http4s/client/NodeJSClientBuilder.scala
index 6bcd43d8cd..827d7d3d51 100644
--- a/client/js/src/main/scala/org/http4s/client/NodeJSClientBuilder.scala
+++ b/client/js/src/main/scala/org/http4s/client/NodeJSClientBuilder.scala
@@ -19,7 +19,6 @@ package client
 
 import cats.effect.kernel.Async
 import cats.effect.kernel.Resource
-import cats.effect.std.Dispatcher
 import cats.syntax.all._
 import org.http4s.internal.BackendBuilder
 import org.http4s.nodejs.ClientRequest
@@ -48,8 +47,8 @@ private[client] sealed abstract class NodeJSClientBuilder[F[_]](implicit protect
     * The shutdown of this client is a no-op. $WHYNOSHUTDOWN
     */
   def create: Client[F] = Client { (req: Request[F]) =>
-    Dispatcher[F].flatMap { dispatcher =>
-      Resource.make(F.delay(new AbortController))(ctr => F.delay(ctr.abort())).evalMap { abort =>
+    Resource.make(F.delay(new AbortController))(ctr => F.delay(ctr.abort())).evalMap { abort =>
+      F.async[IncomingMessage] { cb =>
         val options = new RequestOptions {
           method = req.method.renderString
           protocol = req.uri.scheme.map(_.value + ":").orUndefined
@@ -59,19 +58,16 @@ private[client] sealed abstract class NodeJSClientBuilder[F[_]](implicit protect
           signal = abort.signal
         }
 
-        for {
-          incomingMessage <- F.deferred[IncomingMessage]
-          cb = (msg: IncomingMessage) =>
-            dispatcher.unsafeRunAndForget(incomingMessage.complete(msg))
-          clientRequest <-
-            if (req.uri.scheme.contains(Uri.Scheme.https))
-              F.delay(httpsRequest(options, cb))
-            else
-              F.delay(httpRequest(options, cb))
-          _ <- clientRequest.writeRequest(req)
-          response <- incomingMessage.get.flatMap(_.toResponse)
-        } yield response
-      }
+        val clientRequest =
+          if (req.uri.scheme.contains(Uri.Scheme.https))
+            F.delay(httpsRequest(options, msg => cb(Right(msg))))
+          else
+            F.delay(httpRequest(options, msg => cb(Right(msg))))
+
+        clientRequest
+          .flatMap(_.writeRequest(req))
+          .as(Some(F.unit)) // cancelation guaranteed by abort controller
+      }.flatMap(_.toResponse)
     }
   }
 
diff --git a/project/Http4sPlugin.scala b/project/Http4sPlugin.scala
index 65451fc5de..e6fdae08fb 100644
--- a/project/Http4sPlugin.scala
+++ b/project/Http4sPlugin.scala
@@ -106,7 +106,7 @@ object Http4sPlugin extends AutoPlugin {
     val blaze = "0.15.3"
     val caseInsensitive = "1.3.0"
     val cats = "2.9.0"
-    val catsEffect = "3.3.14"
+    val catsEffect = "3.4.0"
     val catsParse = "0.3.8"
     val circe = "0.14.3"
     val crypto = "0.2.4"
diff --git a/server/jvm/src/main/scala/org/http4s/server/middleware/CSRF.scala b/server/jvm/src/main/scala/org/http4s/server/middleware/CSRF.scala
index 913287f813..4de550bc5e 100644
--- a/server/jvm/src/main/scala/org/http4s/server/middleware/CSRF.scala
+++ b/server/jvm/src/main/scala/org/http4s/server/middleware/CSRF.scala
@@ -24,7 +24,7 @@ import cats.data.Kleisli
 import cats.effect.Concurrent
 import cats.effect.Sync
 import cats.effect.SyncIO
-import cats.effect.std.Random
+import cats.effect.std.SecureRandom
 import cats.syntax.all._
 import cats.~>
 import org.http4s.Uri.Scheme
@@ -492,8 +492,8 @@ object CSRF {
     * SecureRandom use via jvm flags.
     */
   private val InitialSeedArraySize: Int = 20
-  private val CachedRandom: Random[SyncIO] =
-    Random
+  private val CachedRandom: SecureRandom[SyncIO] =
+    SecureRandom
       .javaSecuritySecureRandom[SyncIO]
       .flatTap(_.nextBytes(InitialSeedArraySize))
       .unsafeRunSync()
diff --git a/server/shared/src/main/scala/org/http4s/server/middleware/authentication/Nonce.scala b/server/shared/src/main/scala/org/http4s/server/middleware/authentication/Nonce.scala
index 76673d2b97..dca5e7d35b 100644
--- a/server/shared/src/main/scala/org/http4s/server/middleware/authentication/Nonce.scala
+++ b/server/shared/src/main/scala/org/http4s/server/middleware/authentication/Nonce.scala
@@ -17,7 +17,7 @@
 package org.http4s.server.middleware.authentication
 
 import cats.effect.SyncIO
-import cats.effect.std.Random
+import cats.effect.std.SecureRandom
 
 import java.util.Date
 
@@ -26,7 +26,7 @@ private[authentication] class Nonce(val created: Date, var nc: Int, val data: St
 
 @deprecated("Untracked side effects. Use NonceF.", "0.23.11")
 private[authentication] object Nonce {
-  val random: Random[SyncIO] = Random.javaSecuritySecureRandom[SyncIO].unsafeRunSync()
+  val random: SecureRandom[SyncIO] = SecureRandom.javaSecuritySecureRandom[SyncIO].unsafeRunSync()
 
   def gen(bits: Int): Nonce =
     new Nonce(new Date(), 0, NonceF.getRandomData[SyncIO](random, bits).unsafeRunSync())
diff --git a/server/shared/src/main/scala/org/http4s/server/middleware/authentication/NonceKeeperF.scala b/server/shared/src/main/scala/org/http4s/server/middleware/authentication/NonceKeeperF.scala
index 5fb1bdd914..3318d8b6b2 100644
--- a/server/shared/src/main/scala/org/http4s/server/middleware/authentication/NonceKeeperF.scala
+++ b/server/shared/src/main/scala/org/http4s/server/middleware/authentication/NonceKeeperF.scala
@@ -18,7 +18,7 @@ package org.http4s.server.middleware.authentication
 
 import cats.effect.Async
 import cats.effect.Ref
-import cats.effect.std.Random
+import cats.effect.std.SecureRandom
 import cats.effect.std.Semaphore
 import cats.syntax.all._
 
@@ -38,7 +38,7 @@ private[authentication] object NonceKeeperF {
     current <- F.monotonic
     lastCleanupMillis <- Ref[F].of(current)
     nonces = new LinkedHashMap[String, NonceF[F]]
-    random <- Random.javaSecuritySecureRandom[F]
+    random <- SecureRandom.javaSecuritySecureRandom[F]
   } yield new NonceKeeperF(
     staleTimeout,
     nonceCleanupInterval,
@@ -64,7 +64,7 @@ private[authentication] class NonceKeeperF[F[_]](
     semaphore: Semaphore[F],
     lastCleanupMillis: Ref[F, FiniteDuration],
     nonces: LinkedHashMap[String, NonceF[F]],
-    random: Random[F],
+    random: SecureRandom[F],
 )(implicit F: Async[F]) {
   require(bits > 0, "Please supply a positive integer for bits.")
 


Test patch:
diff --git a/client-testkit/js/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala b/client-testkit/js/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala
index 75ca81713c..1043fdb3b7 100644
--- a/client-testkit/js/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala
+++ b/client-testkit/js/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala
@@ -59,7 +59,7 @@ private[http4s] object ServerScaffold {
   ): Resource[F, ServerScaffold[F]] = {
     require(num == 1 && !secure)
     val app = routes.orNotFound
-    Dispatcher[F].flatMap { dispatcher =>
+    Dispatcher.parallel[F].flatMap { dispatcher =>
       Resource
         .make {
           F.delay(
diff --git a/client-testkit/jvm/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala b/client-testkit/jvm/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala
index 2a9864a05c..c68a981411 100644
--- a/client-testkit/jvm/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala
+++ b/client-testkit/jvm/src/main/scala/org/http4s/client/testkit/scaffold/ServerScaffold.scala
@@ -43,7 +43,7 @@ private[http4s] object ServerScaffold {
       F: Async[F]
   ): Resource[F, ServerScaffold[F]] =
     for {
-      dispatcher <- Dispatcher[F]
+      dispatcher <- Dispatcher.parallel[F]
       scaffold <- apply(num, secure, RoutesToNettyAdapter[F](routes, dispatcher))
     } yield scaffold
 
@@ -58,7 +58,7 @@ private[http4s] object ServerScaffold {
       F: Async[F]
   ): Resource[F, ServerScaffold[F]] =
     for {
-      dispatcher <- Dispatcher[F]
+      dispatcher <- Dispatcher.parallel[F]
       maybeSsl <-
         if (secure) Resource.eval[F, SSLContext](makeSslContext[F]).map(Some(_))
         else Resource.pure[F, Option[SSLContext]](None)
diff --git a/server/shared/src/test/scala/org/http4s/server/middleware/authentication/NonceFSpec.scala b/server/shared/src/test/scala/org/http4s/server/middleware/authentication/NonceFSpec.scala
index 1f3fcce2d3..ab6a10eeb3 100644
--- a/server/shared/src/test/scala/org/http4s/server/middleware/authentication/NonceFSpec.scala
+++ b/server/shared/src/test/scala/org/http4s/server/middleware/authentication/NonceFSpec.scala
@@ -18,13 +18,13 @@ package org.http4s
 package server.middleware.authentication
 
 import cats.effect.IO
-import cats.effect.std.Random
+import cats.effect.std.SecureRandom
 import org.scalacheck.Gen
 import org.scalacheck.effect.PropF._
 
 class NonceFSpec extends Http4sSuite {
   test("nonce in expected range") {
-    Random.javaSecuritySecureRandom[IO].map { random =>
+    SecureRandom.javaSecuritySecureRandom[IO].map { random =>
       forAllF(Gen.chooseNum(1, 240)) { (n: Int) =>
         NonceF
           .gen(random, n)
@@ -36,7 +36,7 @@ class NonceFSpec extends Http4sSuite {
 
   test("nonce has correct alphabet") {
     val alphabet = "0123456789abcdef".toSet
-    Random.javaSecuritySecureRandom[IO].map { random =>
+    SecureRandom.javaSecuritySecureRandom[IO].map { random =>
       forAllF { (_: Unit) =>
         NonceF.gen(random, 160).map(nonce => assert(nonce.data.forall(alphabet), nonce.data))
       }
diff --git a/tests/shared/src/main/scala/org/http4s/testing/DispatcherIOFixture.scala b/tests/shared/src/main/scala/org/http4s/testing/DispatcherIOFixture.scala
index be07923f1b..b7a3f9649f 100644
--- a/tests/shared/src/main/scala/org/http4s/testing/DispatcherIOFixture.scala
+++ b/tests/shared/src/main/scala/org/http4s/testing/DispatcherIOFixture.scala
@@ -23,6 +23,6 @@ import munit.CatsEffectSuite
 
 trait DispatcherIOFixture { this: CatsEffectSuite =>
 
-  def dispatcher: SyncIO[FunFixture[Dispatcher[IO]]] = ResourceFunFixture(Dispatcher[IO])
+  def dispatcher: SyncIO[FunFixture[Dispatcher[IO]]] = ResourceFunFixture(Dispatcher.parallel[IO])
 
 }
diff --git a/tests/shared/src/test/scala/org/http4s/multipart/MultipartSuite.scala b/tests/shared/src/test/scala/org/http4s/multipart/MultipartSuite.scala
index 4391d93fe8..6f9b9cc868 100644
--- a/tests/shared/src/test/scala/org/http4s/multipart/MultipartSuite.scala
+++ b/tests/shared/src/test/scala/org/http4s/multipart/MultipartSuite.scala
@@ -33,7 +33,13 @@ class MultipartSuite extends Http4sSuite {
   private val url = uri"https://example.com/path/to/some/where"
 
   private val multiparts =
-    Random.scalaUtilRandom[IO].map(Multiparts.fromRandom[IO]).syncStep.unsafeRunSync().toOption.get
+    Random
+      .scalaUtilRandom[IO]
+      .map(Multiparts.fromRandom[IO])
+      .syncStep(Int.MaxValue)
+      .unsafeRunSync()
+      .toOption
+      .get
 
   def eqPartIO(a: Part[IO], b: Part[IO]): IO[Boolean] =
     for {
diff --git a/tests/shared/src/test/scala/org/http4s/multipart/MultipartsSuite.scala b/tests/shared/src/test/scala/org/http4s/multipart/MultipartsSuite.scala
index 2d88f5b702..d47a24c0f3 100644
--- a/tests/shared/src/test/scala/org/http4s/multipart/MultipartsSuite.scala
+++ b/tests/shared/src/test/scala/org/http4s/multipart/MultipartsSuite.scala
@@ -23,7 +23,13 @@ import org.scalacheck.effect.PropF._
 
 class MultipartsSuite extends Http4sSuite {
   private val multiparts =
-    Random.scalaUtilRandom[IO].map(Multiparts.fromRandom[IO]).syncStep.unsafeRunSync().toOption.get
+    Random
+      .scalaUtilRandom[IO]
+      .map(Multiparts.fromRandom[IO])
+      .syncStep(Int.MaxValue)
+      .unsafeRunSync()
+      .toOption
+      .get
   private val alphabet =
     Set('A' to 'Z': _*) ++ Set('a' to 'z': _*) ++ Set('0' to '9': _*) ++ Set('_', '-')