Skip to content

Commit d7d0c84

Browse files
committed
Bump cats-effect to 3.6.0-RC1 and make the necessary changes accordingly.
1 parent 0ae875a commit d7d0c84

File tree

7 files changed

+1147
-27
lines changed

7 files changed

+1147
-27
lines changed

build.sbt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,15 +305,15 @@ lazy val logbackMdcCatsEffect3 = module(ProjectName("logback-mdc-cats-effect3"),
305305
libraryDependencies ++= Seq(
306306
libs.logbackClassic,
307307
libs.logbackScalaInterop,
308-
libs.catsEffect3Eap,
308+
libs.catsEffect3,
309309
libs.tests.effectieCatsEffect3,
310310
libs.tests.extrasHedgehogCatsEffect3,
311311
) ++ libs.tests.hedgehogLibs,
312312
libraryDependencies := libraryDependenciesRemoveScala3Incompatible(
313313
scalaVersion.value,
314314
libraryDependencies.value,
315315
),
316-
javaOptions += "-Dcats.effect.ioLocalPropagation=true",
316+
javaOptions += "-Dcats.effect.trackFiberContext=true",
317317
)
318318
.dependsOn(
319319
core,
@@ -593,7 +593,7 @@ lazy val props =
593593

594594
final val CatsVersion = "2.7.0"
595595

596-
val CatsEffect3Version = "3.3.14"
596+
val CatsEffect3Version = "3.6.0-RC1"
597597

598598
val Monix3Version = "3.4.0"
599599

@@ -628,8 +628,6 @@ lazy val libs =
628628

629629
lazy val catsEffect3 = "org.typelevel" %% "cats-effect" % props.CatsEffect3Version
630630

631-
lazy val catsEffect3Eap = "org.typelevel" %% "cats-effect" % "3.6-02a43a6"
632-
633631
lazy val monix3Execution = "io.monix" %% "monix-execution" % props.Monix3Version
634632

635633
lazy val effectieCore: ModuleID = "io.kevinlee" %% "effectie-core" % props.EffectieVersion

modules/logger-f-logback-mdc-cats-effect3/shared/src/main/scala/loggerf/logger/logback/Ce3MdcAdapter.scala

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package loggerf.logger.logback
22

3-
import cats.effect.unsafe.IOLocals
43
import cats.effect.{IOLocal, SyncIO}
54
import cats.syntax.all._
65
import ch.qos.logback.classic.LoggerContext
@@ -18,7 +17,7 @@ class Ce3MdcAdapter extends JLoggerFMdcAdapter {
1817

1918
private[this] val localContext: IOLocal[Map[String, String]] =
2019
IOLocal[Map[String, String]](Map.empty[String, String])
21-
.syncStep(1)
20+
.syncStep(100)
2221
.flatMap(
2322
_.leftMap(_ =>
2423
new Error(
@@ -28,27 +27,32 @@ class Ce3MdcAdapter extends JLoggerFMdcAdapter {
2827
)
2928
.unsafeRunSync()
3029

31-
override def put(key: String, `val`: String): Unit =
32-
IOLocals.update(localContext)(_ + (key -> `val`))
30+
override def put(key: String, `val`: String): Unit = {
31+
val unsafeThreadLocal = localContext.unsafeThreadLocal()
32+
unsafeThreadLocal.set(unsafeThreadLocal.get + (key -> `val`))
33+
}
3334

34-
@SuppressWarnings(Array("org.wartremover.warts.Null"))
35+
@SuppressWarnings(Array("org.wartremover.warts.Null", "org.wartremover.warts.StringPlusAny"))
3536
override def get(key: String): String =
36-
IOLocals.get(localContext).getOrElse(key, null) // scalafix:ok DisableSyntax.null
37+
localContext.unsafeThreadLocal().get.getOrElse(key, null) // scalafix:ok DisableSyntax.null
3738

38-
override def remove(key: String): Unit = IOLocals.update(localContext)(_ - key)
39+
override def remove(key: String): Unit = {
40+
val unsafeThreadLocal = localContext.unsafeThreadLocal()
41+
unsafeThreadLocal.set(unsafeThreadLocal.get - key)
42+
}
3943

40-
override def clear(): Unit = IOLocals.reset(localContext)
44+
override def clear(): Unit = localContext.unsafeThreadLocal().set(Map.empty[String, String])
4145

4246
override def getCopyOfContextMap: JMap[String, String] = getPropertyMap0
4347

4448
override def setContextMap0(contextMap: JMap[String, String]): Unit =
45-
IOLocals.set(localContext, contextMap.asScala.toMap)
49+
localContext.unsafeThreadLocal().set(contextMap.asScala.toMap)
4650

47-
private def getPropertyMap0: JMap[String, String] = IOLocals.get(localContext).asJava
51+
private def getPropertyMap0: JMap[String, String] = localContext.unsafeThreadLocal().get.asJava
4852

4953
override def getPropertyMap: JMap[String, String] = getPropertyMap0
5054

51-
override def getKeys: JSet[String] = IOLocals.get(localContext).keySet.asJava
55+
override def getKeys: JSet[String] = localContext.unsafeThreadLocal().get.keySet.asJava
5256

5357
}
5458
object Ce3MdcAdapter {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package loggerf.logger.logback
2+
3+
import cats.effect.{IOLocal, unsafe}
4+
import ch.qos.logback.classic.LoggerContext
5+
import logback_scala_interop.JLoggerFMdcAdapter
6+
import org.slf4j.{LoggerFactory, MDC}
7+
8+
import java.util.{Map => JMap, Set => JSet}
9+
import scala.jdk.CollectionConverters._
10+
import scala.util.control.NonFatal
11+
12+
/** @author Kevin Lee
13+
* @since 2023-07-07
14+
*/
15+
class Ce3MdcAdapterWithIoRuntime(private val ioRuntime: unsafe.IORuntime) extends JLoggerFMdcAdapter {
16+
17+
private[this] val localContext: IOLocal[Map[String, String]] =
18+
IOLocal[Map[String, String]](Map.empty[String, String])
19+
.unsafeRunSync()(ioRuntime)
20+
21+
override def put(key: String, `val`: String): Unit = {
22+
val unsafeThreadLocal = localContext.unsafeThreadLocal()
23+
unsafeThreadLocal.set(unsafeThreadLocal.get + (key -> `val`))
24+
}
25+
26+
@SuppressWarnings(Array("org.wartremover.warts.Null", "org.wartremover.warts.StringPlusAny"))
27+
override def get(key: String): String =
28+
localContext.unsafeThreadLocal().get.getOrElse(key, null) // scalafix:ok DisableSyntax.null
29+
30+
override def remove(key: String): Unit = {
31+
val unsafeThreadLocal = localContext.unsafeThreadLocal()
32+
unsafeThreadLocal.set(unsafeThreadLocal.get - key)
33+
}
34+
35+
override def clear(): Unit = localContext.unsafeThreadLocal().set(Map.empty[String, String])
36+
37+
override def getCopyOfContextMap: JMap[String, String] = getPropertyMap0
38+
39+
override def setContextMap0(contextMap: JMap[String, String]): Unit =
40+
localContext.unsafeThreadLocal().set(contextMap.asScala.toMap)
41+
42+
private def getPropertyMap0: JMap[String, String] = localContext.unsafeThreadLocal().get.asJava
43+
44+
override def getPropertyMap: JMap[String, String] = getPropertyMap0
45+
46+
override def getKeys: JSet[String] = localContext.unsafeThreadLocal().get.keySet.asJava
47+
48+
}
49+
object Ce3MdcAdapterWithIoRuntime {
50+
51+
@SuppressWarnings(Array("org.wartremover.warts.Null"))
52+
private def initialize0(ioRuntime: unsafe.IORuntime): Ce3MdcAdapterWithIoRuntime = {
53+
val field = classOf[MDC].getDeclaredField("mdcAdapter")
54+
field.setAccessible(true)
55+
val adapter = new Ce3MdcAdapterWithIoRuntime(ioRuntime)
56+
field.set(null, adapter) // scalafix:ok DisableSyntax.null
57+
field.setAccessible(false)
58+
adapter
59+
}
60+
61+
@SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf", "scalafix:DisableSyntax.asInstanceOf"))
62+
def initialize()(implicit ioRuntime: unsafe.IORuntime): Ce3MdcAdapterWithIoRuntime = {
63+
val loggerContext =
64+
LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
65+
initializeWithLoggerContext(loggerContext)
66+
}
67+
68+
def initializeWithLoggerContext(
69+
loggerContext: LoggerContext
70+
)(implicit ioRuntime: unsafe.IORuntime): Ce3MdcAdapterWithIoRuntime = {
71+
val adapter = initialize0(ioRuntime)
72+
try {
73+
val field = classOf[LoggerContext].getDeclaredField("mdcAdapter")
74+
field.setAccessible(true)
75+
field.set(loggerContext, adapter)
76+
field.setAccessible(false)
77+
adapter
78+
} catch {
79+
case NonFatal(_) => adapter
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)