Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move logging to kernel-only dependency #710

Merged
merged 4 commits into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ lazy val loggingStr = project
defaultSettings,
libraryDependencies ++= Seq(
catsCore,
catsEffect,
circeCore,
tethys,
tethysJackson,
Expand All @@ -95,7 +94,7 @@ lazy val loggingStr = project
catsTagless
),
)
.dependsOn(core, concurrent)
.dependsOn(kernel)

lazy val loggingDer = project
.in(file("modules/logging/derivation"))
Expand All @@ -111,7 +110,7 @@ lazy val loggingLayout = project
.in(file("modules/logging/layout"))
.settings(
defaultSettings,
libraryDependencies ++= Seq(catsCore, catsEffect, logback, slf4j),
libraryDependencies ++= Seq(catsCore, logback, slf4j),
name := "tofu-logging-layout"
)
.dependsOn(loggingStr)
Expand All @@ -121,9 +120,9 @@ lazy val loggingUtil = project
.settings(
defaultSettings,
name := "tofu-logging-util",
libraryDependencies += slf4j,
libraryDependencies ++= Vector(slf4j, catsEffect),
)
.dependsOn(loggingStr, concurrent)
.dependsOn(loggingStr)

lazy val loggingShapeless = project
.in(file("modules/logging/interop/shapeless"))
Expand Down
27 changes: 27 additions & 0 deletions modules/core/src/test/scala/tofu/concurrent/AtomSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package tofu.concurrent

import cats.effect.Sync
import cats.effect.IO
import cats.data.ReaderT
import scala.annotation.nowarn
import org.scalatest.funsuite.AnyFunSuite
import cats.Monad
import tofu.syntax.monadic._

@nowarn
class AtomSuite extends AnyFunSuite {
def summonInstance[I[_]: Sync, F[_]: Sync] = {
implicitly[MakeAtom[I, F]]
}

test("check IO has Atom") {
assert(MakeAtom[IO, ReaderT[IO, Unit, *]].of(1).flatMap(atomProg(_).run(())).unsafeRunSync() === ("1" -> 2))
}

def atomProg[F[_]: Monad](atom: Atom[F, Int]) =
for {
x <- atom.modify(i => (i + 1, i.toString))
y <- atom.get
} yield (x, y)

}
31 changes: 31 additions & 0 deletions modules/core/src/test/scala/tofu/concurrent/QVarSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package tofu.concurrent

import cats.effect.Sync
import cats.effect.IO
import cats.data.ReaderT
import scala.annotation.nowarn

import org.scalatest.funsuite.AnyFunSuite
import cats.effect.Concurrent
import cats.Monad
import tofu.syntax.monadic._
import scala.concurrent.ExecutionContext

@nowarn
class QVarSuite extends AnyFunSuite {
def summonInstance[I[_]: Sync, F[_]: Concurrent] = {
implicitly[MakeQVar[I, F]]
}

implicit val iocs = IO.contextShift(ExecutionContext.global)

test("check IO has QVar") {
assert(MakeQVar[IO, ReaderT[IO, Unit, *]].of(1).flatMap(qvarProg(_).run(())).unsafeRunSync() === (1 -> 2))
}

def qvarProg[F[_]: Monad](q: QVar[F, Int]) = for {
x <- q.take
_ <- q.put(x + 1)
y <- q.read
} yield (x, y)
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package tofu.concurrent
import cats.{Applicative, Functor}
import cats.effect.Sync
import cats.effect.concurrent.Ref
import tofu.Guarantee
import tofu.concurrent.Atom.AtomByRef

import tofu.higherKind.{RepresentableK, derived}
import tofu.optics.Contains
import tofu.syntax.monadic._
import tofu.syntax.bracket._
import cats.data.StateT
import tofu.data.calc.CalcM
import tofu.internal.carriers._

/** a middleground between cats.concurrent.Ref and zio.Ref */
trait Atom[+F[_], A] {
Expand Down Expand Up @@ -58,25 +55,6 @@ object Atom {
}
}

final case class AtomByRef[F[_], A](ref: Ref[F, A]) extends Atom[F, A] {
override def get: F[A] = ref.get
override def set(a: A): F[Unit] = ref.set(a)
override def getAndSet(a: A): F[A] = ref.getAndSet(a)
override def update(f: A => A): F[Unit] = ref.update(f)
override def modify[B](f: A => (A, B)): F[B] = ref.modify(f)
}

final case class QAtom[F[_]: Applicative: Guarantee, A](qvar: QVar[F, A]) extends Atom[F, A] {
def get: F[A] = qvar.read
def set(a: A): F[Unit] = getAndSet(a).void
def getAndSet(a: A): F[A] = qvar.take.guaranteeAlways(qvar.put(a))
def update(f: A => A): F[Unit] = qvar.take.bracketIncomplete(a => qvar.put(f(a)))(qvar.put)
def modify[B](f: A => (A, B)): F[B] = qvar.take.bracketIncomplete { a =>
val (next, res) = f(a)
qvar.put(next) as res
}(qvar.put)
}

private[Atom] case class FocusedAtom[F[_]: Functor, A, B](v: Atom[F, A], focus: Contains[A, B]) extends Atom[F, B] {
def get: F[B] = v.get.map(focus.get)
def set(b: B): F[Unit] = v.update(focus.set(_, b))
Expand Down Expand Up @@ -115,14 +93,16 @@ trait MakeAtom[I[_], F[_]] {
def atom[A](a: A): I[Atom[F, A]]
}

object MakeAtom {
object MakeAtom extends MakeAtomInterop {
def apply[I[_], F[_]](implicit makeAtom: MakeAtom[I, F]) = new Applier[I, F](makeAtom)

final class Applier[I[_], F[_]](private val makeAtom: MakeAtom[I, F]) extends AnyVal {
def of[A](a: A): I[Atom[F, A]] = makeAtom.atom(a)
}

implicit def syncInstance[I[_]: Sync, F[_]: Sync]: MakeAtom[I, F] = new MakeAtom[I, F] {
def atom[A](a: A): I[Atom[F, A]] = Ref.in[I, F, A](a).map(AtomByRef(_))
}
final implicit def interopCE3[I[_], F[_]](implicit carrier: MkAtomCE3Carrier[I, F]): MakeAtom[I, F] = carrier
}

trait MakeAtomInterop {
final implicit def interopCE2[I[_], F[_]](implicit carrier: MkAtomCE2Carrier[I, F]): MakeAtom[I, F] = carrier
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package tofu.concurrent
import cats.effect.concurrent.MVar
import cats.effect.{Concurrent, Sync}

import tofu.higherKind.{RepresentableK, derived}
import cats.Applicative
import tofu.Guarantee
import tofu.concurrent.QVar.QVarByMVar
import tofu.higherKind.{RepresentableK, derived}
import tofu.syntax.monadic._

import scala.annotation.nowarn
import tofu.syntax.guarantee._
import tofu.internal.carriers.MkQVarCE3Carrier
import tofu.internal.carriers.MkQVarCE2Carrier

/** a middleground between cats.concurrent.MVar and zio.Queue.bounded(1) */
trait QVar[+F[_], A] {
Expand Down Expand Up @@ -58,15 +57,7 @@ object QVar {
implicit def representableK[A]: RepresentableK[QVar[*[_], A]] = derived.genRepresentableK[QVar[*[_], A]]

final implicit class QVarOps[F[_], A](private val self: QVar[F, A]) extends AnyVal {
def toAtom(implicit F: Applicative[F], FG: Guarantee[F]): Atom[F, A] = Atom.QAtom(self)
}

@nowarn("cat=deprecation")
final case class QVarByMVar[F[_], A](mvar: MVar[F, A]) extends QVar[F, A] {
override def isEmpty: F[Boolean] = mvar.isEmpty
override def put(a: A): F[Unit] = mvar.put(a)
override def take: F[A] = mvar.take
override def read: F[A] = mvar.read
def toAtom(implicit F: Applicative[F], FG: Guarantee[F]): Atom[F, A] = QAtom(self)
}
}

Expand All @@ -76,19 +67,32 @@ trait MakeQVar[I[_], F[_]] {
}

object QVars {
def apply[F[_]](implicit qvars: QVars[F]): MakeQVar.Applier[F, F] = new MakeQVar.Applier(qvars)
def apply[F[_]](implicit qvars: MakeQVar[F, F]): MakeQVar.Applier[F, F] = new MakeQVar.Applier(qvars)
}

object MakeQVar {
object MakeQVar extends MakeQVarInterop {
def apply[I[_], F[_]](implicit mkvar: MakeQVar[I, F]) = new Applier[I, F](mkvar)

final class Applier[I[_], F[_]](private val makeMVar: MakeQVar[I, F]) extends AnyVal {
def empty[A]: I[QVar[F, A]] = makeMVar.qvarEmpty[A]
def of[A](a: A): I[QVar[F, A]] = makeMVar.qvarOf(a)
}

implicit def concurrentMakeMVar[I[_]: Sync, F[_]: Concurrent]: MakeQVar[I, F] = new MakeQVar[I, F] {
def qvarOf[A](a: A): I[QVar[F, A]] = MVar.in[I, F, A](a).map(QVarByMVar(_))
def qvarEmpty[A]: I[QVar[F, A]] = MVar.emptyIn[I, F, A].map(QVarByMVar(_))
}
final implicit def interopCE3[I[_], F[_]](implicit carrier: MkQVarCE3Carrier[I, F]): MakeQVar[I, F] = carrier

}

trait MakeQVarInterop {
final implicit def interopCE2[I[_], F[_]](implicit carrier: MkQVarCE2Carrier[I, F]): MakeQVar[I, F] = carrier
}

final case class QAtom[F[_]: Applicative: Guarantee, A](qvar: QVar[F, A]) extends Atom[F, A] {
def get: F[A] = qvar.read
def set(a: A): F[Unit] = getAndSet(a).void
def getAndSet(a: A): F[A] = qvar.take.guaranteeAlways(qvar.put(a))
def update(f: A => A): F[Unit] = qvar.take.bracketIncomplete(a => qvar.put(f(a)))(qvar.put)
def modify[B](f: A => (A, B)): F[B] = qvar.take.bracketIncomplete { a =>
val (next, res) = f(a)
qvar.put(next) as res
}(qvar.put)
}
6 changes: 3 additions & 3 deletions modules/kernel/src/main/scala/tofu/internal/ContextBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package tofu.internal
import cats.arrow.FunctionK
import cats.data.ReaderT
import cats.{Applicative, Functor, Monad, ~>}
import tofu.internal.carriers.UnliftEffect
import tofu.internal.carriers.UnliftCarrier
import tofu.lift.Unlift
import tofu.syntax.monadic._
import tofu.{WithContext, WithLocal, WithProvide, WithRun}
Expand Down Expand Up @@ -82,6 +82,6 @@ trait ContextBaseInstances5 extends ContextBaseInstances6 {
}

trait ContextBaseInstances6 {
final implicit def unliftEffect[F[_], G[_]](implicit carrier: UnliftEffect[F, G]): Unlift[F, G] =
carrier.value
final implicit def unliftEffect[F[_], G[_]](implicit carrier: UnliftCarrier[F, G]): Unlift[F, G] =
carrier
}
1 change: 1 addition & 0 deletions modules/kernel/src/main/scala/tofu/internal/Interop.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Interop(val c: blackbox.Context) {
c.Expr[R](delegateParamTree[N](Seq(ps))(ts))

def delegate[R: WTT, F[_]: WTTU, N: WTT]: c.Expr[R] = delegateImpl[R, N](tc[F])
def delegate2[R: WTT, I[_]: WTTU, F[_]: WTTU, N: WTT]: c.Expr[R] = delegateImpl[R, N](tc[I], tc[F])
def delegate1p1[R: WTT, T: WTT, F[_]: WTTU, N: WTT](p1: Tree): c.Expr[R] = delegateParamImpl[R, N](p1)(t[T], tc[F])
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import tofu.internal.WBInterop
abstract class FibersCarrier[F[_]] {
type Fib[_]
type Exit[_]
val content: Fibers[F, Exit, Fib]
def content: Fibers[F, Exit, Fib]
}

object FibersCarrier {
type Aux[F[_], Ex[_], Fb[_]] = FibersCarrier[F] { type Exit[a] = Ex[a]; type Fib[a] = Fb[a]; }
def apply[F[_], Ex[_], Fb[_]](fin: Fibers[F, Ex, Fb]) = new FibersCarrier[F] {
type Fib[a] = Fb[a]

trait Impl[F[_], Ex[_], Fb[_]] extends FibersCarrier[F] with Fibers[F, Ex, Fb] {
type Exit[a] = Ex[a]
val content = fin
type Fib[a] = Fb[a]
def content = this
}

final implicit def startFromConcurrent[F[_], Exit[_], Fiber[_]]: Aux[F, Exit, Fiber] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ package tofu.internal.carriers
import tofu.Finally
import tofu.internal.WBInterop

abstract class FinallyCarrier[F[_], E] {
trait FinallyCarrier[F[_], E] {
type Exit[_]
val content: Finally[F, Exit]
def content: Finally[F, Exit]
}

object FinallyCarrier {
type Aux[F[_], E, Ex[_]] = FinallyCarrier[F, E] { type Exit[a] = Ex[a] }
def apply[F[_], E, Ex[_]](fin: Finally[F, Ex]) = new FinallyCarrier[F, E] {

trait Impl[F[_], E, Ex[_]] extends FinallyCarrier[F, E] with Finally[F, Ex] {
type Exit[a] = Ex[a]
val content = fin
def content = this
}

final implicit def fromBracket[F[_], E, Exit[_]]: Aux[F, E, Exit] =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package tofu.internal.carriers

import tofu.internal.Interop
import tofu.lift.Unlift

// This is purely workaround for scala 2.12
// Which denies to unfold a macro (and recieve a type error)
// before checking an implicit for eligibility
trait UnliftCarrier[F[_], G[_]] extends Unlift[F, G]

object UnliftCarrier {
final implicit def unliftIOEffect[F[_], G[_]]: UnliftCarrier[F, G] =
macro Interop.delegate[UnliftCarrier[F, G], G, { val `tofu.interop.CE2Kernel.unliftEffect`: Unit }]
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package tofu.internal.carriers

import tofu.internal.Interop
import tofu.concurrent.MakeAtom
import tofu.concurrent.MakeQVar

trait MkAtomCE2Carrier[I[_], F[_]] extends MakeAtom[I, F]

object MkAtomCE2Carrier {
final implicit def interopCE2Carrier[I[_], F[_]]: MkAtomCE2Carrier[I, F] =
macro Interop.delegate2[MkAtomCE2Carrier[I, F], I, F, { val `tofu.interop.CE2Kernel.atomBySync`: Unit }]
}

trait MkAtomCE3Carrier[I[_], F[_]] extends MakeAtom[I, F]

object MkAtomCE3Carrier {
final implicit def interopCE3Carrier[I[_], F[_]]: MkAtomCE3Carrier[I, F] =
macro Interop.delegate2[MkAtomCE2Carrier[I, F], I, F, { val `tofu.interop.CE3Kernel.atomBySync`: Unit }]
}

trait MkQVarCE2Carrier[I[_], F[_]] extends MakeQVar[I, F]

object MkQVarCE2Carrier {
final implicit def interopCE2Carrier[I[_], F[_]]: MkQVarCE2Carrier[I, F] =
macro Interop.delegate2[MkQVarCE2Carrier[I, F], I, F, { val `tofu.interop.CE2Kernel.qvarByConcurrent`: Unit }]
}

trait MkQVarCE3Carrier[I[_], F[_]] extends MakeQVar[I, F]

object MkQVarCE3Carrier {
final implicit def interopCE3Carrier[I[_], F[_]]: MkQVarCE3Carrier[I, F] =
macro Interop.delegate2[MkQVarCE3Carrier[I, F], I, F, { val `tofu.interop.CE3Kernel.qvarByConcurrent`: Unit }]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package tofu.interop

import cats.effect.concurrent.Ref
import tofu.concurrent.Atom

final case class AtomByRef[F[_], A](ref: Ref[F, A]) extends Atom[F, A] {
override def get: F[A] = ref.get
override def set(a: A): F[Unit] = ref.set(a)
override def getAndSet(a: A): F[A] = ref.getAndSet(a)
override def update(f: A => A): F[Unit] = ref.update(f)
override def modify[B](f: A => (A, B)): F[B] = ref.modify(f)
}
Loading