Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit 1bbec11

Browse files
authored
Merge pull request #262 from polyvariant/ce3
Cats Effect 3 migration
2 parents 0aed18b + 74a52e9 commit 1bbec11

20 files changed

+162
-170
lines changed

build.sbt

+32-25
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ ThisBuild / missinglinkExcludedDependencies += moduleFilter(
5656
name = "slf4j-api"
5757
)
5858

59+
ThisBuild / libraryDependencySchemes ++= Seq(
60+
"io.circe" %% "circe-core" % "early-semver",
61+
"io.circe" %% "circe-generic-extras" % "early-semver",
62+
"io.circe" %% "circe-literal" % "early-semver",
63+
"io.circe" %% "circe-parser" % "early-semver"
64+
)
65+
5966
def crossPlugin(x: sbt.librarymanagement.ModuleID) =
6067
compilerPlugin(x.cross(CrossVersion.full))
6168

@@ -71,31 +78,31 @@ val commonSettings = List(
7178
scalacOptions += "-Ymacro-annotations",
7279
libraryDependencies ++= List(
7380
"org.typelevel" %% "cats-core" % "2.6.1",
74-
"org.typelevel" %% "cats-effect" % "2.5.1",
81+
"org.typelevel" %% "cats-effect" % "3.1.1",
7582
"org.typelevel" %% "cats-tagless-macros" % "0.14.0",
76-
"co.fs2" %% "fs2-core" % "2.5.6",
77-
"com.github.valskalla" %% "odin-core" % "0.11.0",
78-
"io.circe" %% "circe-core" % "0.13.0",
83+
"co.fs2" %% "fs2-core" % "3.0.4",
84+
"io.github.irevive" %% "odin-core" % "0.12.0-M3",
85+
"io.circe" %% "circe-core" % "0.14.1",
7986
"com.github.julien-truffaut" %% "monocle-macro" % "2.1.0",
80-
"com.disneystreaming" %% "weaver-framework" % "0.5.1" % Test,
81-
"com.disneystreaming" %% "weaver-scalacheck" % "0.5.1" % Test
87+
"com.disneystreaming" %% "weaver-cats" % "0.7.3" % Test,
88+
"com.disneystreaming" %% "weaver-scalacheck" % "0.7.3" % Test
8289
) ++ compilerPlugins,
83-
testFrameworks += new TestFramework("weaver.framework.TestFramework"),
90+
testFrameworks += new TestFramework("weaver.framework.CatsEffect"),
8491
publish / skip := true
8592
)
8693

8794
lazy val gitlab = project
8895
.settings(
8996
commonSettings,
9097
libraryDependencies ++= List(
91-
"is.cir" %% "ciris" % "1.2.1",
92-
"com.kubukoz" %% "caliban-gitlab" % "0.0.14",
93-
"io.circe" %% "circe-generic-extras" % "0.13.0",
94-
"io.circe" %% "circe-parser" % "0.13.0" % Test,
95-
"io.circe" %% "circe-literal" % "0.13.0" % Test,
96-
"com.softwaremill.sttp.tapir" %% "tapir-core" % "0.17.19",
97-
"com.softwaremill.sttp.tapir" %% "tapir-json-circe" % "0.17.19",
98-
"com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % "0.17.19"
98+
"is.cir" %% "ciris" % "2.0.1",
99+
"com.kubukoz" %% "caliban-gitlab" % "0.1.0",
100+
"io.circe" %% "circe-generic-extras" % "0.14.1",
101+
"io.circe" %% "circe-parser" % "0.14.1" % Test,
102+
"io.circe" %% "circe-literal" % "0.14.1" % Test,
103+
"com.softwaremill.sttp.tapir" %% "tapir-core" % "0.18.0-M15",
104+
"com.softwaremill.sttp.tapir" %% "tapir-json-circe" % "0.18.0-M15",
105+
"com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % "0.18.0-M15"
99106
)
100107
)
101108
.dependsOn(core)
@@ -181,19 +188,19 @@ lazy val pitgull =
181188
buildInfoPackage := "io.pg",
182189
buildInfoKeys := List(version, scalaVersion),
183190
libraryDependencies ++= List(
184-
"com.softwaremill.sttp.client3" %% "http4s-ce2-backend" % "3.3.6",
185-
"org.http4s" %% "http4s-dsl" % "0.21.24",
186-
"org.http4s" %% "http4s-circe" % "0.21.24",
187-
"org.http4s" %% "http4s-blaze-server" % "0.21.24",
188-
"org.http4s" %% "http4s-blaze-client" % "0.21.24",
189-
"is.cir" %% "ciris" % "1.2.1",
190-
"io.circe" %% "circe-generic-extras" % "0.13.0",
191+
"com.softwaremill.sttp.client3" %% "http4s-backend" % "3.3.6",
192+
"org.http4s" %% "http4s-dsl" % "0.23.0-RC1",
193+
"org.http4s" %% "http4s-circe" % "0.23.0-RC1",
194+
"org.http4s" %% "http4s-blaze-server" % "0.23.0-RC1",
195+
"org.http4s" %% "http4s-blaze-client" % "0.23.0-RC1",
196+
"is.cir" %% "ciris" % "2.0.1",
197+
"io.circe" %% "circe-generic-extras" % "0.14.0",
191198
"io.estatico" %% "newtype" % "0.4.4",
192199
"io.scalaland" %% "chimney" % "0.6.1",
193200
"io.chrisdavenport" %% "cats-time" % "0.3.4",
194-
"com.github.valskalla" %% "odin-core" % "0.11.0",
195-
"com.github.valskalla" %% "odin-slf4j" % "0.11.0",
196-
"io.github.vigoo" %% "prox-fs2" % "0.7.1"
201+
"io.github.irevive" %% "odin-core" % "0.12.0-M3",
202+
"io.github.irevive" %% "odin-slf4j" % "0.12.0-M3",
203+
"io.github.vigoo" %% "prox-fs2-3" % "0.7.1"
197204
)
198205
)
199206
.dependsOn(core, gitlab)

core/src/main/scala/io/pg/Prelude.scala

-16
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,6 @@
11
package io.pg
22

3-
import cats.effect.Resource
4-
import cats.syntax.functor._
5-
import cats.Applicative
6-
import cats.MonadError
7-
83
object Prelude {
9-
type MonadThrow[F[_]] = MonadError[F, Throwable]
10-
11-
implicit class EffectToResourceLiftSyntax[F[_], A](private val fa: F[A]) extends AnyVal {
12-
13-
def resource(implicit F: Applicative[F]): Resource[F, A] =
14-
Resource.eval(fa)
15-
16-
def resource_(implicit F: Applicative[F]): Resource[F, Unit] =
17-
fa.void.resource
18-
19-
}
204

215
implicit class AnythingAnything[A](private val a: A) extends AnyVal {
226
def ??? : Nothing = ???

core/src/main/scala/io/pg/background/background.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ object BackgroundProcess {
1515

1616
final case class DrainStream[F[_], G[_]](
1717
stream: fs2.Stream[F, Nothing],
18-
C: fs2.Stream.Compiler[F, G]
18+
C: fs2.Compiler[F, G]
1919
) extends BackgroundProcess[G]
2020

2121
def fromStream[F[_], G[_]](
2222
stream: fs2.Stream[F, _]
2323
)(
24-
implicit C: fs2.Stream.Compiler[F, G]
24+
implicit C: fs2.Compiler[F, G]
2525
): BackgroundProcess[G] =
2626
new DrainStream(stream.drain, C)
2727

@@ -30,7 +30,7 @@ object BackgroundProcess {
3030
)(
3131
processor: Processor[F, A]
3232
)(
33-
implicit C: fs2.Stream.Compiler[F, F]
33+
implicit C: fs2.Compiler[F, F]
3434
): BackgroundProcess[F] =
3535
fromStream(channel.consume.through(processor.process))
3636

core/src/main/scala/io/pg/messaging/messaging.scala

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package io.pg.messaging
22

3-
import fs2.concurrent.Queue
3+
import cats.effect.std.Queue
44
import scala.reflect.ClassTag
55
import cats.tagless.autoInvariant
66
import cats.syntax.all._
77
import cats.ApplicativeError
88
import io.odin.Logger
9+
import cats.Functor
910

1011
trait Publisher[F[_], -A] {
1112
def publish(a: A): F[Unit]
@@ -41,10 +42,10 @@ trait Channel[F[_], A] extends Publisher[F, A] { self =>
4142

4243
object Channel {
4344

44-
def fromQueue[F[_], A](q: Queue[F, A]): Channel[F, A] =
45+
def fromQueue[F[_]: Functor, A](q: Queue[F, A]): Channel[F, A] =
4546
new Channel[F, A] {
46-
def publish(a: A): F[Unit] = q.enqueue1(a)
47-
val consume: fs2.Stream[F, A] = q.dequeue
47+
def publish(a: A): F[Unit] = q.offer(a)
48+
val consume: fs2.Stream[F, A] = fs2.Stream.fromQueueUnterminated(q)
4849
}
4950

5051
implicit class ChannelOpticsSyntax[F[_], A](val ch: Channel[F, A]) extends AnyVal {

gitlab/src/main/scala/io/pg/gitlab/Gitlab.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import io.pg.gitlab.graphql.PipelineStatusEnum
2121
import io.pg.gitlab.graphql.Project
2222
import io.pg.gitlab.graphql.ProjectConnection
2323
import io.pg.gitlab.graphql.Query
24-
import io.pg.gitlab.graphql.User
24+
import io.pg.gitlab.graphql.UserCore
2525
import sttp.client3.Request
2626
import sttp.client3.SttpBackend
2727
import sttp.model.Uri
@@ -80,7 +80,7 @@ object Gitlab {
8080
accessToken: Secret[String]
8181
)(
8282
implicit backend: SttpBackend[F, Any],
83-
SC: fs2.Stream.Compiler[F, F]
83+
SC: fs2.Compiler[F, F]
8484
): Gitlab[F] = {
8585

8686
def runRequest[O](request: Request[O, Any]): F[O] =
@@ -139,7 +139,7 @@ object Gitlab {
139139
MergeRequest.iid.mapEither(_.toLongOption.toRight(DecodingError("MR IID wasn't a Long"))) ~
140140
MergeRequest.headPipeline(Pipeline.status.map(convertPipelineStatus)) ~
141141
MergeRequest
142-
.author(User.username)
142+
.author(UserCore.username)
143143
.mapEither(_.toRight(DecodingError("MR has no author"))) ~
144144
MergeRequest.description ~
145145
MergeRequest.shouldBeRebased ~

src/main/java/org/slf4j/impl/StaticLoggerBinder.java

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ public static StaticLoggerBinder getSingleton() {
88
return _instance;
99
}
1010
}
11+
+47-52
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package io.pg
22

33
import cats.data.NonEmptyList
4-
import cats.effect.Blocker
5-
import cats.effect.ConcurrentEffect
6-
import cats.effect.ContextShift
74
import cats.effect.Resource
5+
import cats.effect.kernel.Async
6+
import cats.effect.std.Queue
7+
import cats.effect.implicits._
88
import cats.syntax.all._
9-
import fs2.concurrent.Queue
109
import io.odin.Logger
1110
import io.pg.background.BackgroundProcess
1211
import io.pg.config.ProjectConfigReader
@@ -15,16 +14,14 @@ import io.pg.gitlab.webhook.WebhookEvent
1514
import io.pg.messaging._
1615
import io.pg.webhook._
1716
import org.http4s.HttpApp
18-
import org.http4s.client.blaze.BlazeClientBuilder
17+
import org.http4s.blaze.client.BlazeClientBuilder
1918
import org.http4s.implicits._
2019
import sttp.capabilities.fs2.Fs2Streams
2120
import sttp.client3.SttpBackend
2221
import sttp.client3.http4s.Http4sBackend
2322

2423
import scala.concurrent.ExecutionContext
2524

26-
import Prelude._
27-
2825
sealed trait Event extends Product with Serializable
2926

3027
object Event {
@@ -38,56 +35,54 @@ final class Application[F[_]](
3835

3936
object Application {
4037

41-
def resource[F[_]: ConcurrentEffect: ContextShift: Logger](
38+
def resource[F[_]: Logger: Async](
4239
config: AppConfig
4340
): Resource[F, Application[F]] = {
4441
implicit val projectConfigReader = ProjectConfigReader.test[F]
4542

46-
Blocker[F].flatMap { blocker =>
47-
Queue
48-
.bounded[F, Event](config.queues.maxSize)
49-
.map(Channel.fromQueue)
50-
.resource
51-
.flatMap { eventChannel =>
52-
implicit val webhookChannel: Channel[F, WebhookEvent] =
53-
eventChannel.only[Event.Webhook].imap(_.value)(Event.Webhook)
54-
55-
BlazeClientBuilder[F](ExecutionContext.global)
56-
.resource
57-
.map(
58-
org
59-
.http4s
60-
.client
61-
.middleware
62-
.Logger(logHeaders = true, logBody = false, redactHeadersWhen = config.middleware.sensitiveHeaders.contains)
43+
Queue
44+
.bounded[F, Event](config.queues.maxSize)
45+
.map(Channel.fromQueue(_))
46+
.toResource
47+
.flatMap { eventChannel =>
48+
implicit val webhookChannel: Channel[F, WebhookEvent] =
49+
eventChannel.only[Event.Webhook].imap(_.value)(Event.Webhook)
50+
51+
BlazeClientBuilder[F](ExecutionContext.global)
52+
.resource
53+
.map(
54+
org
55+
.http4s
56+
.client
57+
.middleware
58+
.Logger(logHeaders = true, logBody = false, redactHeadersWhen = config.middleware.sensitiveHeaders.contains)
59+
)
60+
.map { client =>
61+
implicit val backend: SttpBackend[F, Fs2Streams[F]] =
62+
Http4sBackend.usingClient[F](client)
63+
64+
implicit val gitlab: Gitlab[F] =
65+
Gitlab.sttpInstance[F](config.git.apiUrl, config.git.apiToken)
66+
67+
implicit val projectActions: ProjectActions[F] =
68+
ProjectActions.instance[F]
69+
70+
implicit val stateResolver: StateResolver[F] =
71+
StateResolver.instance[F]
72+
73+
implicit val mergeRequests: MergeRequests[F] =
74+
MergeRequests.instance[F]
75+
76+
val webhookProcess = BackgroundProcess.fromProcessor(
77+
webhookChannel
78+
)(Processor.simple(WebhookProcessor.instance[F]))
79+
80+
new Application[F](
81+
routes = WebhookRouter.routes[F].orNotFound,
82+
background = NonEmptyList.one(webhookProcess)
6383
)
64-
.map { client =>
65-
implicit val backend: SttpBackend[F, Fs2Streams[F]] =
66-
Http4sBackend.usingClient[F](client, blocker)
67-
68-
implicit val gitlab: Gitlab[F] =
69-
Gitlab.sttpInstance[F](config.git.apiUrl, config.git.apiToken)
70-
71-
implicit val projectActions: ProjectActions[F] =
72-
ProjectActions.instance[F]
73-
74-
implicit val stateResolver: StateResolver[F] =
75-
StateResolver.instance[F]
76-
77-
implicit val mergeRequests: MergeRequests[F] =
78-
MergeRequests.instance[F]
79-
80-
val webhookProcess = BackgroundProcess.fromProcessor(
81-
webhookChannel
82-
)(Processor.simple(WebhookProcessor.instance[F]))
83-
84-
new Application[F](
85-
routes = WebhookRouter.routes[F].orNotFound,
86-
background = NonEmptyList.one(webhookProcess)
87-
)
88-
}
89-
}
90-
}
84+
}
85+
}
9186
}
9287

9388
}

0 commit comments

Comments
 (0)