Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Yann Simon
@yanns
See https://sangria-graphql.github.io/learn/#deferred-value-resolution
In your schema, use your own class that extends Deferred.
In your DeferredResolver, you have access to all your accumulated Deferred instances. Based on this input, you can choose how to resolve them. And this can be one by one if you want to.
Yann Simon
@yanns
If you use Fetcher, you might be interested in this change that allows setting the max concurrency: https://github.com/sangria-graphql/sangria/pull/454/files
This PR would need help (rebase on last version I guess) so that it could be integrated.
Witold Soczek
@v-tec2706
thank you @yanns! I'll try that
Justin Reeves
@justinallenreeves

Currently getting an error when returning a large page of results Fetcher has not resolved non-optional ID ‘<SOME_ID>’
I’ve looked at the ids thrown by the error and found the objects/entities they refer to (it’s a nested object inside the object being queried) and they exist
I can do a more narrow query that filters for that specific object and get page with 1 result.
It so far only seems to blow up when I have to many.

Perhaps this is an issue with a the Future for the Field being queried is resolving before the defered resolver finishes?

Yann Simon
@yanns
@justinallenreeves is it a new issue? In which version do you observe that?
Justin Reeves
@justinallenreeves
We’re on 2.0.0 but I’m not sure it’s a bug with Sangria.
I’ve been playing with page sizes all morning trying to reproduce but it looks like it’s related to the data.
I neglected to included the exception, it’s a sangria.execution.deferred.AbsentDeferredValueError
Alexej Haak
@Daxten
FetcherBasedDeferredResolver.scala:245 there is no way to give Fetchers a name or sth right now if understand correctly... I have like 10 fetchers in my project and if one throws that error it's pretty hard to debug which one
Since the thread trampolining removes the stacktrace
Yann Simon
@yanns
Please feel free to add issues with as much info as possible. And we can also help you to make your first PR if you like ;)
Greg Fisher
@gnfisher
I am running into an issue where Sangria is not generating a type as I would like. I've got a Validated[A] type with a GraphQLOutputTypeLookup[Validated[A]] defined thusly:
  implicit def validatedType[A](
      implicit lookup: GraphQLOutputTypeLookup[A]
  ): GraphQLOutputTypeLookup[Validated[A]] =
    new GraphQLOutputTypeLookup[Validated[A]] {
      def graphqlType: OutputType[Validated[A]] =
        ObjectType(
          s"Validated${lookup.graphqlType.namedType.name}",
          fields[Ctx, Validated[A]](
            Field("value", lookup.graphqlType, resolve = _.value.value),
            Field(
              "fatal",
              ListType(FatalType),
              resolve = _.value.status.fatal
            ),
            Field(
              "warning",
              ListType(WarningType),
              resolve = _.value.status.warning
            )
          )
        )
    }
The issue is having both a Validated[String] and Validated[Option[String]]. If only one or the other is present, it works as expected ( in elm I get a Maybe String in the generated graphql object). But if both are present, only one is generated. So in my case, only a ValidatedString type exists, and its not a Maybe String in elm land.
Validated looks like this:
case class Validated[A](value: A, status: Status) {
  def map[B](f: A => B): Validated[B] =
    copy(value = f(value))
}
I think it has something to do with how the type name is generated with this line: s"Validated${lookup.graphqlType.namedType.name}",
so when both are present one overwrites the other and only one version is created.
and that is because lookup.graphqlType.namedType reaches into option to get the wrapped type
Greg Fisher
@gnfisher
I'm trying to find a way to know if the A is an Option so I can insert that into the name...
Greg Fisher
@gnfisher
I am still unable to discover a way to resolve this issue, if anyone has any ideas, I'd appreciate it!
Yann Simon
@yanns

Yes different types should have different names.
A way to fix that would be use a trait like:

trait GraphQLTypeName[A] {
  def typeName: String
}
implicit def validatedType[A](
      implicit lookup: GraphQLOutputTypeLookup[A],
      implicit typeName: GraphQLTypeName[A]
  ): GraphQLOutputTypeLookup[Validated[A]] =
    new GraphQLOutputTypeLookup[Validated[A]] {
      def graphqlType: OutputType[Validated[A]] =
        ObjectType(
          s"Validated${typeName.name}",

Then you would create 2 instances of GraphQLTypeName :

implicit val stringGraphQLTypeName: GraphQLTypeName[String] = ...
implicit def optionGraphQLTypeName[A]: GraphQLTypeName[Option[A]] = ...
Mark Tomko
@mtomko
I'm trying to define an ObjectType and I'd like to put some validation in so that after I've parsed the fields, I can check the value and return a sensible error if they're not compatible, before I try and construct the actual object this represents. Where does logic like that usually live?
Yann Simon
@yanns
@mtomko I'm not sure I understand your question. ObjectType are typed. The scala compiler should check the fields' types for you?
Mark Tomko
@mtomko:matrix.org
[m]
I'm not talking about type checking, I mean consistency.
In this case, the two fields would be dates, and they're not valid unless one is before the other (ie, from is less than or equal to to)
Mark Tomko
@mtomko:matrix.org
[m]
:point_up: Edit: In this case, I'm not thinking of type checking, I mean consistency.
:point_up: Edit: I'm not thinking of type checking, I mean consistency, I should have been more clear.
Yann Simon
@yanns
The consistency could be checked in the data model no? Why do you need this business logic in GraphQL?
If you want to do something in GraphQL, you could add a ValidationRule to your executor.
Mark Tomko
@mtomko:matrix.org
[m]
In this case, the Scala type we're mapping to GraphQL has strict rules prohibiting to prevent an invalid object from being constructed, so I was hoping to be able to put a check in to return a user-facing error rather than relying on the type's constructor to return an error (which would not be suitable to display for a number of reasons). I could add a type in between, but that feels sort of heavy-weight. I can look into a ValidationRule but it also seems not scalable to put validation rules in the executor that affect just one of a myriad number of types that our GraphQL represents.
Thanks for your suggestions.
Yann Simon
@yanns
But how do you create this object first? Load from database?
I'd suggest to put any validation logic where the instance is created first.
Mark Tomko
@mtomko:matrix.org
[m]
No this gets created in a mutation, so it's coming in from the outside world.
Greg Fisher
@gnfisher
@yanns Thanks, I was starting down that path but did not include the GraphQLTypeName[A], which I think is the thing!
Yann Simon
@yanns
@mtomko:matrix.org then your mutation should return a validation of the creation of the instance. You can use exceptions, or Either for that.
Greg Fisher
@gnfisher
@yanns in your example, I will need to make a typeName for String and every other type, correct? I haveValidatedString, ValidatedCurrency etc.
(this is brushing up at the limits of my type knowledge in scala)
Greg Fisher
@gnfisher
The answer was yes, as far as Ive been able to get it to work!
Yann Simon
@yanns
You can also use Either[Error, String], Either[Error, Currency].
PsyfireX
@PsyfireX
Does Sangria have Scala 3 support, or is it likely to get Scala 3 support in the near future?
Shohei Shimomura
@sh0hei
@PsyfireX Of course we plan to support Scala3. I am currently working on it.
PsyfireX
@PsyfireX
@sh0hei That's great to hear & thank you for working on it. Do you have an idea on the approximate timeline (apologies for asking for an estimate, hah), and are there any features on Sangria I should avoid if I intend to minimize migration-pain (like macros?)
Yann Rolland
@TidyMaze

Hello :) I'm trying to use the @GraphQLDescription annotation for arguments. The doc says "@GraphQLDescription - provide a description for a type, field, enum value or an argument", it works perfectly for type, fields, enum but I have no idea if it can work on args. I tried

@GraphQLDescription("My arg description")
    val myArg: Argument[Option[MyClass]] =
      Argument("arg", OptionInputType(MyClassInputType))

    val myArg: Argument[Option[MyClass]] = {
       @GraphQLDescription("My arg description")
      Argument("arg", OptionInputType(MyClassInputType))
}

without Success, and I can't find an example in unit tests. Any help? Thanks for the nice library btw

Yann Simon
@yanns
No need for the annotation on Argument. You can directly set the description field:
Argument("arg", OptionInputType(MyClassInputType), description = "My arg description")
Annotations are only useful when you generate the GraphQL type.
Yann Rolland
@TidyMaze
Hi, thanks for your response, I know it wasn't necessary to use annotation, I wanted to make sure it was possible or not (and if not, what was the meaning of the quoted doc)
When generating GraphQL type you can also add DocumentField(), so annotation are always a bonus, not necessary
PsyfireX
@PsyfireX
I'm trying to implement a GraphQL Interface. I see there's an example of how to do it manually https://sangria-graphql.github.io/learn/#schema-definition but I'm currently using macro-based derivation for each instance of the derivation. (1) Is there a way for me to define the TagInputGql with macros? (2) If [1] is not possible, could I define the interface manually, but somehow keep the macro-based derivation for each instance?
object Example {
  sealed trait TagInputGql

  object TagInputGql{
    implicit val _ot: InterfaceType[Unit, TagInputGql] =
      ???  // <-- what to do here?
  }

  case class CreateTagInputGql(
    //fields
  ) extends TagInputGql

  object CreateTagInputGql{
    implicit val _ot: InputObjectType[CreateTagInputGql] =
      deriveInputObjectType[CreateTagInputGql](
        InputObjectTypeName("CreateTagInput")
      )
  }

  case class MarkTagInputGql(
    // fields
  ) extends TagInputGql

  object MarkTagInputGql{
    implicit val _ot: InputObjectType[MarkTagInputGql] =
      deriveInputObjectType[MarkTagInputGql](
        InputObjectTypeName("MarkTagInput")
      )
  }
}
As your sealed trait does not define any method, the GraphQL interface should not define any fields.
I have not checked if it's compiling, but that would be the direction:
sealed trait TagInputGql

  object TagInputGql{
    implicit val _ot: InterfaceType[Unit, TagInputGql] =
      InterfaceType(
        "TagInputGql",
         "Your description",
        List.empty[Field]
  }
PsyfireX
@PsyfireX
Thank you for the help, I'll give it a try :)
PsyfireX
@PsyfireX
Hmmm, it looks like I'd need to essentially create an DeriveInputObjectSetting equivalent for the Interfaces in DeriveObjectSettings
Which would require an update to DeriveInputObjectTypeMacro (I'm a bit new to macros and Sangria)
PsyfireX
@PsyfireX
It looks like manually defining the input types might be the least complicated route for the moment, based on my current familiarity levels.