Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Nick Hudkins
@nickhudkins
  object ActivityRef {
    implicit val fromInput: FromInput[ActivityRef] =
      new FromInput[ActivityRef] {
        override val marshaller: ResultMarshaller =
          CoercedScalaResultMarshaller.default
        override def fromResult(node: marshaller.Node): ActivityRef =
          ActivityRef(3456L)
      }
    val activityRefArg: Argument[ActivityRef] =
      Argument("activityRef", inputType)
  }

  object Args {
    import ActivityRef._
    val activityRefArgs = activityRefArg :: Nil
  }
    // Do something which (apparently) mutates global state somewhere in sangria
    ObjectType(
      "Activity",
      fields[Unit, QueryableProject](
        Field(
          "activityRef",
          LongType,
          arguments = ActivityRef.activityRefArg :: Nil,
          resolve = _ => 123L // The resolve function is irrelevant to this test
        )
      )
    )

    val query = ObjectType(
      name = "Query",
      fields = fields[POWContext, Unit](
        Field(
          name = "project",
          fieldType = ObjectType[Unit, QueryableProject](
            name = "Project",
            fields = fields[Unit, QueryableProject](
              Field(
                "activityRef",
                LongType,
                arguments = Args.activityRefArgs,
                resolve =
                  _ => 123L // The resolve function is irrelevant to this test
              )
            )
          ),
          resolve =
            _ => QueryableProject.empty // The resolve function is irrelevant to this test
        )
      )
    )
class SchemaInitTest extends AnyFunSuite {

  import SchemaInitTest._

  test(
    "ObjectType() and Schema() should not have any kind of weird side effects when sharing an argument"
  ) {
    // Do something which (apparently) mutates global state somewhere in sangria

    println(ActivityRef.arg :: Nil) // List(Good stuff!)
    println(activityRefArgs) // List(null)
    assert(true)
  }
}
Nick Hudkins
@nickhudkins
for context ^^ the issue is that activityRefArgs is List(null) , which means Sangria ends up throwing a null pointer exception. I suspect flattening out some of your objects might help this
Nick Hudkins
@nickhudkins
Does that help @TrasheRacer ?
TrasheRacer
@TrasheRacer
Yes, that helps enormously! Thanks :pray:
I'll keep looking into the bug - if it turns out to be a Sangria bug, I'll open an issue
TrasheRacer
@TrasheRacer

Regarding the above mentioned bug involving Argument()

I'm think that this is a Sangria-related issue, as opposed to simply a Scala issue.
When I get rid of all the Sangria code (instead just constructing a list containing some case class), the null disappears.

import org.scalatest.funsuite.AnyFunSuite
import sangria.schema.{Argument, EnumType, EnumValue, OptionInputType}

object SchemaInitTest {
  sealed trait Episode
  object Episode {
    final case object EPISODE_1 extends Episode
  }

  case class Test(string: String)

  val EpisodeEnum = EnumType(
    "Episode",
    Some("One of the films in the Star Wars Trilogy"),
    List(EnumValue("NEWHOPE", value = Episode.EPISODE_1, description = Some("Released in 1977.")))
  )

  object EpisodeArgs {
//    val arg = Test("test") // test passes when we don't use Sangria code at all!
    val arg = Argument("activityRef", OptionInputType(EpisodeEnum)) // but this fails!
  }

  val episodeArgs = EpisodeArgs.arg :: Nil
}

class SchemaInitTest extends AnyFunSuite {

  import SchemaInitTest._

  test("A list of args should be the same, regardless of where it is initialised") {
//    assert(episodeArgs == EpisodeArgs.arg :: Nil) // this passes for some reason!
    assert(EpisodeArgs.arg :: Nil == episodeArgs) // but this fails!
  }
}

Another thing I noticed is that changing the order we compare for equality in the assert also makes the problem go away.

macchiatow
@macchiatow
please please help me to find out the way to register subscription via FieldResolver. I build scheme from ast from text file by use of ResolverBasedAstSchemaBuilder. Yet the only way to make a subscription is via Field::sub which creates a field, where I'm trying to create a resolver
  private def builder: ResolverBasedAstSchemaBuilder[UserContext] =
    AstSchemaBuilder.resolverBased[UserContext](
      riFieldResolver.resolvers :+ FieldResolver.defaultInput[UserContext, JsValue]: _*
    )

  private val schemaString = Source.fromResource("schema.graphql").mkString
  private val schemaAst = QueryParser.parse(schemaString).get

  val schema: Schema[UserContext, Any] = Schema.buildFromAst(schemaAst, builder.validateSchemaWithException(schemaAst))
macchiatow
@macchiatow
  private val riThreadResolver = FieldResolver[UserContext] {
    case (TypeName("Subscription"), FieldName("fi_thread")) =>
      Field.subs("allEvents", null, resolve = { _: Context[UserContext, _] =>
        Source(1 to 10)
          .map { _ =>
            s"""{
                  "data": {
                    "fi_thread": "${LocalTime.now().toString}",
                    "fi_thread2": "${LocalTime.now().toString}"

                  }
                  }"""
          }
          .map(Action(_))
      }).resolve
  }
macchiatow
@macchiatow
        private[sangria] case class SubscriptionValue[Ctx, Val, S[_]](source: Val, stream: SubscriptionStream[S]) extends LeafAction[Ctx, Val] {
        override def map[NewVal](fn: Val => NewVal)(implicit ec: ExecutionContext): SubscriptionValue[Ctx, NewVal, S] =
        throw new IllegalStateException("`map` is not supported subscription actions. Action is only intended for internal use.")
        }
    this is probably useful implicit but it's private
Nick Hudkins
@nickhudkins
Hey @TrasheRacer if you replace EnumType with StringType, this also passes... so, down the rabbit hole I go. I suspect this has something to do with needing to render EnumValues out, but not sure yet :)
If I am SUPERRRR honest, I can't stand all of these nested objects as is, and simply taking these objects and flattening them out also behaves as expected. I am however, fascinated by the behavior. I still am convinced this is a Scala semantics thing that is way over my head. But I am happy to keep seeing if I can find what is happening.
Nick Hudkins
@nickhudkins
Current hunch is: https://github.com/sangria-graphql/sangria/blob/master/modules/core/src/main/scala/sangria/schema/Schema.scala#L890-L893, those lazy vals are used in the coercions. Running some tests as we speak
NOPE! Alright and with that I am tapping out on this one. Please re-organize all of your code :P
Nick Hudkins
@nickhudkins
Ok cool it happens with any Schema type that extends with NullableType, any non simple scalars do the trick :) I have this funny feeling that it's nearly impossible to get into this state in a RealLifeApplication™ but, maybe you already said you have this in a real app?
Nick Hudkins
@nickhudkins
Regarding the switching left / right hand comparison, the reason that works is that it forces coercion. I have never looked deeply into what all goes on behind the scenes in sangria, so maybe it's time. As I looked deeper, it looks like the nullability come from a A <: Null type constraint, and that's deep in Tree (part of the Ast code) That said... I am currently fully unqualified to fix any of this, but I would encourage you to fix it in user land at the moment (a small re-organization), but I'll see if I can get some failing test cases added and maybe someone could look deeper
danielbussone
@danielbussone
Can anyone point me to an example of implementing a filter on a subscription? I would like a user to be able to subscribe to project update events using something like projectUpdated(projectId: "someProjectId") where only events with an id matching the subscribed projectId are returned to the subscriber.
Yann Simon
@yanns
@danielbussone about subscription (https://sangria-graphql.github.io/learn/#stream-based-subscriptions): in the resolve function, you can access the arguments to push only desired events I think.
Justin Reeves
@justinallenreeves
Does anyone have some examples of PartialValue or PartialFutureValue ? I’m serving up some graphql over graphql, and I want to preserve the upstream errors
Justin Reeves
@justinallenreeves

Trying some tests, able to make PartialValue work okay

val Food: Field[Context, Val] = {
    Field(
      name = “Food",
      fieldType = OptionType(StringType),
      resolve = _ => PartialValue(Some("Waffles"), Vector(new Exception("Pancakes"))
    )
  }

This works as expected

But PartialFutureValue won’t compile

val Food: Field[Context, Val] = {
    Field(
      name = “Food",
      fieldType = OptionType(StringType),
      resolve = _ => PartialFutureValue(Future.successful(PartialValue(Some("Waffles"), Vector(new Exception("Pancakes”)))))
    )
  }

There’s type mismatch, it’s looking for sangria.schema.Action[Any,Option[String]]

Yann Simon
@yanns
Maybe the type inference is not working. The guideline you send contains types to help the inference: PartialValue[Unit, Option[String]]
abhishekvaidprophecy
@abhishekvaidprophecy
In my production setup I want to avoid people from introspecting my GraphQL definitions using Apollo plugin. Is there a way to do this with Sangria ?
Justin Reeves
@justinallenreeves
@abhishekvaidprophecy you can check if the incoming request is introspection on the Context[Ctx, Val]
and just refuse the request by whatever mechanism (like throw an exception or returns a Forbidden)
Nick Isaacs
@nicky-isaacs
Hi folks. I have a question about sangria marshalling. I am playing around with attempting to make a marshaller which marshals results to Thrift, but one sticking point is that it appears that ResultMarshaller (https://github.com/sangria-graphql/sangria-marshalling-api/blob/master/src/main/scala/sangria/marshalling/ResultMarshaller.scala) does not hint at which arm of a union is being marshalled, thus I cannot seem to figure out how to render a more refined type other than key/value pairs. Does anyone have any ideas for how I could attempt to solve for this?
1 reply
Mads Saustrup Fox
@MadsSaustrupFox
Hey, wanting to implement pagination in the plural GQL queries. Does anybody know if it's already part of the Sangria lib or can anybody point me to a resource about how to implement it.
Have read this:
https://graphql.org/learn/pagination/
and following their advice i would like to implement cursor based pagination
Justin Reeves
@justinallenreeves
@MadsSaustrupFox Sangria doesn’t have anything to implement because it’s not responsible for subsetting or sorting your data, only resolving it. I use limit/offset arguments for pagination. A cursor would work similarly.
1 reply
Basically, same as you would if it was a simple REST service
Alexej Haak
@Daxten
Hidiho guys, just found out that I can't use Interfaces/Unions as InputTypes in graphQl (buuuuh!), is there a way to create sth like ScalarAliases for InputTypes?
Problem I want to solve is: I have a @GraphQLField which takes a sealed trait as a Parameter. Now I want to create an InputObject which has every implementation of the sealed trait as a property and then create an alias which fails if not exactly one property is Some
to somehow emulate a Union/Interface
I'm also not sure if I can write the mapping of InputFields to Scala class by hand somehow? There seems to be a lot of macro / reflection magic involved here?
Alexej Haak
@Daxten
Okay this is cool imo, I added implicit conversions for SumEmulationOfUnionType => UnionType and vice versa and all the macros etc. work with the implicit conversions
At least I think... it compiles so far lets say :P
Alexej Haak
@Daxten
meh no that doesn't work
so anyway to create an Input type by mapping an already existing InputType? Or by doing the deserialization myself (e.g. MyClass(arg("a"), arg("b")))
Alexej Haak
@Daxten
Okay now I understand one thing more: deriveInputObject actually derives 2 things, the InputObject and FromInput
I thought the FromInput stuff is happening "somehow" in InputObject... so with these 2 combined I can write my own deserialization, nice!
Christian Kjær
@Tehnix
Does anyone have good examples of setting up UnionTypes? Been running into UndefinedConcreteTypeError: Can't find appropriate subtype of a union type and for the love of god I can't find a fix for it :/
Christian Kjær
@Tehnix
...nevermind, apparently I was returning it in a effect which we'd normally do, but it fail until runtime with a very unhelpful error message 😅
Daan Debie
@DandyDev
Hey all! I have a question to which I couldn't find the answer: is Sangria compatible with Scala 3 yet? Is it on the way?
Yann Simon
@yanns
@DandyDev there were no efforts into porting Sangria to Scala 3 yet. If you are motivated, you're welcome to help. Development efforts are coordinated on #sangria-dev.
Shohei Shimomura
@sh0hei
@yanns @DandyDev I plan to make sangria compatible with scala3 :thumbsup: Currently working :muscle: Welcome your help at any time.
1 reply
Yann Simon
@yanns

@yanns @DandyDev I plan to make sangria compatible with scala3 :thumbsup: Currently working :muscle: Welcome your help at any time.

🤩

alex-gaiduchok
@alex-gaiduchok

hey guys, need your advice:
switched sangria to 2.1.0
PR looks like this

    "org.sangria-graphql" %% "sangria" % "1.4.2" =>  "2.1.0",
    "org.sangria-graphql" %% "sangria-relay" % "1.4.2" =>  "2.1.0", 
    "org.sangria-graphql" %% "sangria-circe" % "1.2.1" =>  "1.3.1",
    "org.sangria-graphql" %% "sangria-slowlog" % "0.1.8" =>  "2.0.1",

nothing else was changed.

And faced a memory leak 6 hours after the update (maybe related to traffic).

Maybe someone also faced mem leak at sangria 2.10 ?

alex-gaiduchok
@alex-gaiduchok
platform is graalvm 20