Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
yanns committed Feb 20, 2023
1 parent 2ce95a5 commit 4f937c2
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
run: sbt ++${{ matrix.scala }} test

- name: Compress target directories
run: tar cf targets.tar modules/core/target modules/parser/target modules/test-monix/target modules/benchmarks/target modules/derivation/target modules/test-fs2/target modules/ast/target target modules/sangria/target project/target
run: tar cf targets.tar modules/core/target modules/parser/target modules/test-monix/target modules/benchmarks/target modules/derivation/target modules/test-fs2/target modules/ast/target modules/test-cats-effect/target target modules/sangria/target project/target

- name: Upload target directories
uses: actions/upload-artifact@v2
Expand Down
30 changes: 27 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ def emptyForScala3(isScala3: Boolean, module: ModuleID): Set[ModuleID] =
lazy val root = project
.in(file("."))
.withId("sangria-root")
.aggregate(ast, parser, core, benchmarks, derivation, sangriaTestMonix, sangriaTestFS2, sangria)
.aggregate(
ast,
parser,
core,
benchmarks,
derivation,
sangriaTestMonix,
sangriaTestFS2,
sangriaTestCatsEffect,
sangria)
.settings(inThisBuild(projectInfo))
.settings(
scalacSettings ++ shellSettings ++ noPublishSettings
Expand Down Expand Up @@ -210,12 +219,27 @@ lazy val sangriaTestFS2 = project
.dependsOn(core % "compile->compile;test->test")
.settings(scalacSettings ++ shellSettings ++ noPublishSettings)
.settings(
name := "sangria-test-monix",
description := "Tests with monix",
name := "sangria-test-fs2",
description := "Tests with FS2",
libraryDependencies += "co.fs2" %% "fs2-core" % "3.6.0" % Test
)
.disablePlugins(MimaPlugin)

lazy val sangriaTestCatsEffect = project
.in(file("modules/test-cats-effect"))
.withId("sangria-test-cats-effect")
.dependsOn(core % "compile->compile;test->test")
.settings(scalacSettings ++ shellSettings ++ noPublishSettings)
.settings(
name := "sangria-test-cats-effect",
description := "Tests with Cats Effect",
libraryDependencies ++= List(
"org.typelevel" %% "cats-effect" % "3.4.7" % Test,
"org.sangria-graphql" %% "sangria-circe" % "1.3.2" % Test
)
)
.disablePlugins(MimaPlugin)

lazy val benchmarks = project
.in(file("modules/benchmarks"))
.withId("sangria-benchmarks")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,30 @@ object ExecutionScheme extends AlternativeExecutionScheme {
}
}

trait EffectOps[F[_]] {
def failed[Ctx, Res](error: Throwable): F[Res]
def flatMapFuture[Res, T](future: Future[T])(resultFn: T => F[Res]): F[Res]
def map[T, Out](in: Future[T])(f: T => Out): F[Out]
}

class EffectBasedExecutionScheme[F[_]](
ops: EffectOps[F]
) extends ExecutionScheme {
override type Result[Ctx, Res] = F[Res]
override def failed[Ctx, Res](error: Throwable): Result[Ctx, Res] =
ops.failed(error)
override def onComplete[Ctx, Res](result: Result[Ctx, Res])(op: => Unit)(implicit
ec: ExecutionContext): Result[Ctx, Res] = ???
override def flatMapFuture[Ctx, Res, T](future: Future[T])(resultFn: T => Result[Ctx, Res])(
implicit ec: ExecutionContext): Result[Ctx, Res] =
ops.flatMapFuture(future)(resultFn)
def mapEffect[Ctx, Res, T](future: Future[(Ctx, T)])(f: (Ctx, T) => Res)(implicit
ec: ExecutionContext): F[Res] =
ops.map(future) { case (ctx, in) => f(ctx, in) }

override def extended: Boolean = false
}

trait AlternativeExecutionScheme {
trait StreamBasedExecutionScheme[S[_]] {
def subscriptionStream: SubscriptionStream[S]
Expand Down
4 changes: 4 additions & 0 deletions modules/core/src/main/scala/sangria/execution/Resolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ class Resolver[Ctx](
})
.asInstanceOf[scheme.Result[Ctx, marshaller.Node]]

case s: EffectBasedExecutionScheme[_] =>
s.mapEffect(result.map(_.swap)) { case (_, in) => in._2 }
.asInstanceOf[scheme.Result[Ctx, marshaller.Node]]

case s =>
throw new IllegalStateException(s"Unsupported execution scheme: $s")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package sangria.execution

import cats.effect.IO
import cats.effect.unsafe.implicits.global
import io.circe.Json
import org.scalatest.matchers.must.Matchers
import org.scalatest.wordspec.AnyWordSpec
import sangria.macros._
import sangria.marshalling.circe._
import sangria.schema._

import scala.concurrent.{ExecutionContext, Future}

class IOExecutionScheme extends AnyWordSpec with Matchers {
private implicit val ec: ExecutionContext = global.compute
private val ioEffectOps = new EffectOps[IO] {
override def failed[Ctx, Res](error: Throwable): IO[Res] = IO.raiseError(error)
override def flatMapFuture[Res, T](future: Future[T])(resultFn: T => IO[Res]): IO[Res] =
IO.fromFuture(IO(future)).flatMap(resultFn)
override def map[T, Out](in: Future[T])(f: T => Out): IO[Out] = IO.fromFuture(IO(in)).map(f)
}
private implicit val ioExecutionScheme: EffectBasedExecutionScheme[IO] =
new EffectBasedExecutionScheme[IO](ioEffectOps)

import IOExecutionScheme._
"IOExecutionScheme" must {
"allow using IO effect" in {
val query = gql"""
query q1 {
ids
}
"""
val res: IO[Json] = Executor.execute(schema, query)

val expected: Json = Json.obj(
"data" -> Json.obj(
"ids" -> Json.arr(
Json.fromInt(1),
Json.fromInt(2)
)
)
)
res.unsafeRunSync() must be(expected)
}
}
}

object IOExecutionScheme {
private val QueryType: ObjectType[Unit, Unit] = ObjectType(
"Query",
() =>
fields[Unit, Unit](
Field("ids", ListType(IntType), resolve = _ => List(1, 2))
))

val schema = Schema(QueryType)
}

0 comments on commit 4f937c2

Please sign in to comment.