Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
puneettandon
@puneettandon
as I want to query for professions under given with engineer skill as scala
Please let me know if there is any way in sangria
Yann Simon
@yanns
@Tehnix they are per request. You can set up a cache if you want them across requests.
@puneettandon please try to format your post, it will help the readability.
Yes, it's possible to have arguments on any field.
Example:
        Field(
          "field_name",
          arguments = IncludeKeys :: ExcludeKeys :: Limit :: Offset :: SortArg :: Nil,
          resolve = ctx => {
            val includes = ctx.arg(IncludeKeys)
            val excludes = ctx.arg(ExcludeKeys)
            val limit = ctx.arg(Limit)
            val offset = ctx.arg(Offset)
richa002
@richa002
Hi ..I am new to sangaria graphql. I have a big list (about 500) of map having more than 300 key ,values in each map. I noticed while resolving , it is taking a lot of time approx 800-1200 ms . Can I improve the performance . Is there any way I can make the resolution of list parallelly. Any help highly appreciated.
Yann Simon
@yanns
Daan Debie
@DonDebonair
That is awesome!
PsyfireX
@PsyfireX
Awesome, I might give the Scala 3 branch a try in the next month!
My app is currently entirely Scala 2.13, so I'd have to carve out a chunk of time, but this was the last piece I was waiting for.
PsyfireX
@PsyfireX

I'm trying to make a HandledException and include a custom JSON response. That goes through the additionalFields: Map[String, ResultMarshaller#Node] = Map.empty, field, which Node appears to be an interface, perhaps supporting other libraries (ex: io.circe.Json).

Is there a way I can somehow pass Json directly into the HandledException.additionalFields ?

PsyfireX
@PsyfireX
Hah, I think I figured it out, I just needed the right implicit conversion.
        import _root_.sangria.marshalling.circe._
        val params = Map[String, ResultMarshaller#Node]("" -> io.circe.Json.obj())

        HandledException(
          log.traceId,
          params,
          addFieldsInError = true,
          addFieldsInExtensions = false,
        )
PsyfireX
@PsyfireX
That actually didn't work. I think I'm somewhere in the right ballpark though. If anyone has advice/suggestions, I'm interested.
PsyfireX
@PsyfireX
So, this actually works. A little messy, but I only need this code in one place.
        import _root_.sangria.marshalling.circe._

        val json: CirceResultMarshaller.Node = Json.obj(???)
        val params: Map[String, ResultMarshaller#Node] = Map[String, ResultMarshaller#Node](
          "error" -> json
        )

        HandledException(
          log.traceId,
          params,
          addFieldsInError = true,
          addFieldsInExtensions = false,
        )
Yann Simon
@yanns
You can also use implicit val resultTypeMarshaller = SimpleResultMarshallerForType[resultMarshaller.Node](resultMarshaller), and add your json like value.convertMarshaled[resultMarshaller.Node]
Yann Simon
@yanns
Anyone has tried the release for scala 3?
PsyfireX
@PsyfireX
(not yet, although I did just upgrade a bunch of dependencies including Sangria)
PsyfireX
@PsyfireX
I may actually be trying the Scala 3 release very, very soon. I'm trying to upgrade my entire project to Scala 3, but have a massive number of errors to fix before I get to the GraphQL layer. I'll report back if/when I run into anything.
Yann Simon
@yanns
great to hear!
PsyfireX
@PsyfireX
Update: I migrated everything in my app to Scala 3, except the GraphQL layer which I just started.
The first minor obstacle is circe-optics appears to only be available in Scala 2, which it's transitive dependencies are causing conflicts. The fastest workaround will probably be dropping circe-optics, since I only have a few places which use it, although I'm also asking for advice on the circe gitter.
PsyfireX
@PsyfireX
@yanns I haven't yet dove deep into this exception yet, but it looks like I'm running into issues with deriveObjectType and macros.
    implicit val _ot: ObjectType[Ctx, UpdatePostGql] =
      deriveObjectType[Ctx, UpdatePostGql](
        ObjectTypeName("UpdatePost")
      )
Exception occurred while executing macro expansion.
scala.MatchError: OrType(AndType(TypeRef(TermRef(TermRef(TermRef(TermRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object ai),object tagr),object graphql),object tagr),object schema),object types),class BodyInputGql),AppliedType(TypeRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix,module class sangria)),object util),tag),type Tagged),List(TypeRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix,module class sangria)),object marshalling),FromInput),InputObjectResult)))),TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object scala),Null)) (of class dotty.tools.dotc.core.Types$CachedOrType)
    at dotty.tools.dotc.transform.TypeUtils$.companionRef(TypeUtils.scala:91)
    at dotty.tools.dotc.typer.Synthesizer.companionPath(Synthesizer.scala:252)
    at dotty.tools.dotc.typer.Synthesizer.productMirror(Synthesizer.scala:311)
    at dotty.tools.dotc.typer.Synthesizer.$init$$$anonfun$6$$anonfun$1$$anonfun$1$$anonfun$1(Synthesizer.scala:396)
    at dotty.tools.dotc.typer.Synthesizer.makeMirror(Synthesizer.scala:388)
    at dotty.tools.dotc.typer.Synthesizer.$init$$$anonfun$6$$anonfun$1(Synthesizer.scala:396)
    at dotty.tools.dotc.typer.Synthesizer.$init$$$anonfun$8$$anonfun$1(Synthesizer.scala:413)
    at dotty.tools.dotc.typer.Synthesizer.recur$1(Synthesizer.scala:556)
    at dotty.tools.dotc.typer.Synthesizer.tryAll(Synthesizer.scala:561)
    at dotty.tools.dotc.typer.Implicits.inferImplicitArg(Implicits.scala:857)
    at dotty.tools.dotc.typer.Implicits.inferImplicitArg$(Implicits.scala:785)
    at dotty.tools.dotc.typer.Typer.inferImplicitArg(Typer.scala:117)
    at dotty.tools.dotc.typer.Typer.implicitArgs$1(Typer.scala:3451)
    at dotty.tools.dotc.typer.Typer.addImplicitArgs$1(Typer.scala:3487)
    at dotty.tools.dotc.typer.Typer.adaptNoArgsImplicitMethod$1(Typer.scala:3563)
    at dotty.tools.dotc.typer.Typer.adaptNoArgs$1(Typer.scala:3761)
    at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:3995)
    at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:3329)
    at dotty.tools.dotc.typer.Typer.readapt$1(Typer.scala:3340)
    at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:3982)
    at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:3329)
    at dotty.tools.dotc.typer.Implicits.typedImplicit(Implicits.scala:1053)
    at dotty.tools.dotc.typer.Implicits.typedImplicit$(Implicits.scala:785)
    at dotty.tools.dotc.typer.Typer.typedImplicit(Typer.scala:117)
    at dotty.tools.dotc.typer.Implicits$ImplicitSearch.tryImplicit(Implicits.scala:1173)
    at dotty.tools.dotc.typer.Implicits$ImplicitSearch.rank$1(Implicits.scala:1272)
    at dotty.tools.dotc.typer.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1442)
    at dotty.tools.dotc.typer.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:1470)
    at dotty.tools.dotc.typer.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1503)
    at dotty.tools.dotc.typer.Implicits.inferImplicit(Implicits.scala:997)
    at dotty.tools.dotc.typer.Implicits.inferImplicit$(Implicits.scala:785)
    at dotty.tools.dotc.typer.Typer.inferImplicit(Typer.scala:117)
    at dotty.tools.dotc.typer.Implicits.inferImplicitArg(Implicits.scala:851)
    at dotty.tools.dotc.typer.Implicits.inferImplicitArg$(Implicits.scala:785)
    at dotty.tools.dotc.typer.Typer.inferImplicitArg(Typer.scala:117)
    at dotty.tools.dotc.typer.Typer.implicitArgs$1(Typer.scala:3451)
    at dotty.tools.dotc.typer.Typer.addImplicitArgs$1(Typer.scala:3487)
    at dotty.tools.dotc.typer.Typer.adaptNoArgsImplicitMethod$1(Typer.scala:3563)
    at dotty.tools.dotc.typer.Typer.adaptNoArgs$1(Typer.scala:3761)
    at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:3995)
    at dotty.tools.dotc.typer.Typer.adapt(Typer.scala:3329)
    at dotty.tools.dotc.typer.Typer.readapt$1(Typer.scala:3340)
    at dotty.tools.dotc.typer.Typer.adapt1(Typer.scala:3982)
    at dotty.tools.dot
PsyfireX
@PsyfireX
It appears this type of error mostly applies to classes using @GraphQLExclude and @GraphQLField annotations.
  case class UpdatePostGql(
    @GraphQLExclude
    ctx: Ctx,
    @GraphQLExclude
    id: PostId,
  ) {
    @GraphQLField
    def publishDraft(): Future[PostGql] = ???

    @GraphQLField
    def body(body: BodyInputGql): Future[PostGql] = ???

    @GraphQLField
    def publishVersion(index: Int): Future[PostGql] = ???
  }
Yann Simon
@yanns
@PsyfireX very good feedback! Could you open an issue for this?
It seems that you already have found a way to reproduce it. It should help fixing the issue.
PsyfireX
@PsyfireX
Sure, I was about ready to head to bed - so I'll do that when I wake up. I'll also try to distill it into a piece of code that doesn't rely on my project as well, as to make it more reproducable.
PsyfireX
@PsyfireX
I finally was able to make it reproducible without depending on my project:
sangria-graphql/sangria#905
Yann Simon
@yanns
Thanks a lot!
PsyfireX
@PsyfireX

@yanns No problem, a much bigger thank you for maintaining and supporting Sangria.

Do you have any ideas about when you expect the bug to be fixed? I'm just trying to determine whether or not to go through the effort of switching from derived to manual, since the one final place this bug appears is the very top-level query type containing all of the other query types.

PsyfireX
@PsyfireX
(macros are over-my-head, otherwise I'd look into it)
PsyfireX
@PsyfireX
Disregard my above comment, I see you've already started looking at it! (of course that's not an estimate, but perhaps worth waiting a short while instead of doing a rewrite).
Yann Simon
@yanns
@PsyfireX even if I've started working on it, I'm not sure about when I'll have a fix. I've not written the scala 3 macros, and I need time to understand them.
PsyfireX
@PsyfireX
@yanns Update: I created a workaround to the sangria-circe issues in 905, by engaging in some "ImplicitLaundering" by grabbing the implicit in another class which has the import of io.circe.generic.auto and then using that implicit in another class. The bug still persists, but I was able to unblock myself on that front. I essentially have the following code .... but replace fiA with about 100 or so FromInputs for actual GraphQL classes.
case class A(text: String)
object A{
  implicit val _it: InputObjectType[A] = deriveInputObjectType[A]()
}
// This is a hack to workaround https://github.com/sangria-graphql/sangria/issues/905
object ImplicitLaundering{
  // grab the implicits from `io.circe.generic.auto`
  object Generate {
    import io.circe.generic.auto.*
    def getFI[T]()(implicit t:FromInput[T]): FromInput[T] = t

    def fiA = getFI[A]()
  }

  // Make implicits available with `import ImplicitLaundering.Implicits.*` but without `import io.circe.generic.auto.*`
  object Implicits {
    import Generate.*
    implicit val _fiA: FromInput[A] = fiA
  }
}

My server now:
1) SUCCESS: starts, and successfully returns the Schema (introspection).
2) SUCCESS: Processes input, runs my backend code, and then...
3) FAIL: Fails to generate the output on several endpoints, using various ObjectTypes.

"class scala.concurrent.impl.Promise$DefaultPromise cannot be cast to class ai.tagr.graphql.tagr.schema.types.UserGql (scala.concurrent.impl.Promise$DefaultPromise and ai.tagr.graphql.tagr.schema.types.UserGql are in unnamed module of loader 'app') 
java.lang.ClassCastException: class scala.concurrent.impl.Promise$DefaultPromise cannot be cast to class ai.tagr.graphql.tagr.schema.types.UserGql (scala.concurrent.impl.Promise$DefaultPromise and ai.tagr.graphql.tagr.schema.types.UserGql are in unnamed module of loader 'app') 
 ai.tagr.graphql.tagr.schema.types.UserGql$.$init$$$anonfun$1$$anonfun$13(UserGql.scala:59) 
 sangria.execution.Resolver.resolveField(Resolver.scala:1513) 
 sangria.execution.Resolver.collectActionsPar$$anonfun$1(Resolver.scala:713) 
 scala.collection.IterableOnceOps.foldLeft(IterableOnce.scala:646) 
 scala.collection.IterableOnceOps.foldLeft$(IterableOnce.scala:642) 
 scala.collection.AbstractIterable.foldLeft(Iterable.scala:926) 
 sangria.execution.Resolver.collectActionsPar(Resolver.scala:722) 
 sangria.execution.Resolver.resolveValue(Resolver.scala:1331) 
 sangria.execution.Resolver.resolveStandardFieldResolutionSeq(Resolver.scala:441) 
 sangria.execution.Resolver.resolveSingleFieldSeq(Resolver.scala:400) 
 sangria.execution.Resolver.resolveSeq$$anonfun$1$$anonfun$1(Resolver.scala:356) 
 scala.concurrent.impl.Promise$Transformation.run(Promise.scala:470) 
 java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) 
 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) 
 java.base/java.lang.Thread.run(Thread.java:834)"

I'm not really sure what this error means. However, in this example, UserGql is a fairly basic return/output ObjectType and I get the same error on my other endpoints.

PsyfireX
@PsyfireX
Same error, with a very simplified endpoint:
    @GraphQLField
    def ping(in: String): Future[String] = {
      implicit val ec: scala.concurrent.ExecutionContext = scala.concurrent.ExecutionContext.global
      Future.apply(in)
    }
PsyfireX
@PsyfireX
I created a ticket for the above:
sangria-graphql/sangria#906
Yann Simon
@yanns
yes it looks like the issue I had on https://github.com/sangria-graphql/sangria/issues/905#issuecomment-1229833443 where the wrong implicit is searched for.
PsyfireX
@PsyfireX

Issue 905 and 906 look very different. 905 is an implicit resolution issue or conflict with io.circe , which causes compiler errors. 906 appears to be Sangria getting confused about how to render a Future[???] even with simple types like String

(Although as someone not familiar with the code, I guess it's technically possible they could be related, just seems unlikely)

PsyfireX
@PsyfireX
I decided to do a workaround for #906, swapping all endpoints returning Future[T] to just return T instead. I don't know what the performance difference is, but I'm still months away from dealing with any notable traffic. Once 905 and 906 are fixed, I'll remove my workarounds. Anyway, I appear to have a working GraphQL server in Scala 3, and will use the Scala 3 branch as "master." I'll report any other bugs I run into if any.
Yann Simon
@yanns
thanks for your patience, and congrats about being the 1st one to use AFAIK!
PsyfireX
@PsyfireX
Thanks! I'm currently not blocked, and rolling forward with other feature development. I'll revisit cleanup of the workarounds on my project later, after 905 and 906 are fixed. There were a couple other minor issues I ran into around io.circe but they were easy to workaround and not caused by Sangria.
Guillaume Forgeon
@guillaumefgn_twitter

Hi everybody!
I am facing a "problem" with Sangria (I'm new to it AND to Scala so maybe my problem is due to my lack of knowledge !).
If someone can help me... i'm kinda despesperated :)

So here it is:

  • I have a fetcher 'A' which returns a list of ids
  • I have another fetcher 'B' which needs the list of ids returned by the fetcher 'A' and returns a list of 'EntityB'
  • I have a field whose type id a Option[Connection[EntityB]]
  • Then, for now I have something like this in my resolver:
DeferredValue(Fetchers.fetcherA.deferOpt(ctx.value.id))
              .map(entitiesFromA => {
                DeferredValue(
                  Fetchers.fetcherB.deferSeqOpt(entitiesFromA)
                ).map {
                  case Nil => None
                  case entitiesB =>
                    Some(
                      Connection.connectionFromSeq(
                        entitiesB,
                        args,
                        SliceInfo(sliceStart = offet, size = offset + entitesB.size)
                      )
                    )
                }

Of course, it doesn't work. Compiler needs a Option[Connection[EntityB]] and it gets a DeferredValue[Nothing, Option[Connection[EntityB]]].
I think my problem comes from the nested fetcher calls + Connection stuff. I don't really know how to do.
If someone has an idea, do not hesitate to tell me.
Thank you!

Yann Simon
@yanns

From what I understand:

  • FetcherA takes one ID and returns a list of IDs
  • FetcherB can return a list of EntityB based on the previous list of IDs

I'm not very used to use Fetchers, but I think that fetcherA could be a Relation[..., ID] and used like:

Fetchers.fetcherB.deferRelSeq(Fetchers.fetcherA, ctx.value.id)
Yann Simon
@yanns
If people have interest using a sangria server with GraphQL federation: https://sangria-graphql.github.io/learn/#graphql-federation
Yann Simon
@yanns
Sangria now officially supports GraphQL Federation: https://github.com/apollographql/apollo-federation-subgraph-compatibility#scala
Alexandre Lebrun
@xela85

Hello,
I would like to upgrade a project to Sangria 3, and this project uses sangria-relay module.
By looking at https://github.com/sangria-graphql/sangria-relay, I can see that the project is regularly updated (e.g. scala-steward updates).
However, I don't see any new release in Maven or GitHub. I am missing something ?

Thanks in advance :)

Yann Simon
@yanns
Hi @xela85 . You should still be able to upgrade the sangria version.
But I'll cut a release soon to have all dep updated.
Yann Simon
@yanns
Do you need scala 3 support?