profusion / sgqlc

Simple GraphQL Client
https://sgqlc.readthedocs.io/
ISC License
513 stars 85 forks source link

Nested Nodes aren't being appended to the Query #222

Closed BrennonLee closed 1 year ago

BrennonLee commented 1 year ago

🐜 Bug Report

I have two layers of nested Node types that I expect to be appended to the query but aren't. Here's a simplified example of what the node relationship looks like:

class UserNode(Type):
  id = ID
  firstName = String
  lastName = String

class FamilyMemberNode(Type):
    id = ID
    role = String
    user = UserNode

class FamilyNode(Type):
    id = ID
    familyMembers = list_of(FamilyMemberNode)

# Queries
class Query(Type):
    getUsers = Field(list_of(UserNode))
    getFamily = Field(FamilyNode, args={"id": String, "userId": String})

The code to call the query against my API is like this

  def make_api_call(query):
        headers = {"x-api-key": API_KEY}

        endpoint = HTTPEndpoint(API_URL, headers)

        return endpoint(query=query)

  def get_family(self, user_id):
        # Get the family
        query = Operation(Query)
        query.getFamily(userId=user_id)

        log.info(query)
        response = make_api_call(query)

        error = get_error(response)

        if error:
            raise Error(error)

        return response["data"]["getFamily"]

Expected Behavior

I expect the query to look like this when I print it out above right before making the api call:

query {
  getFamily(userId: "<UUID>") {
    id
    familyMembers {
      id
      role
      user {
        id
        firstName
        lastName
       }
    }
  }
}

Current Behavior

However this is what is currently being logged. Notice the node nested in the second layer (i.e. the UserNode) is missing. I can use AppSync to hit the same query and it's working as expected. Otherwise, I've been able to trace it to here right before the API call is made. It looks like it skips appended the UserNode relationship to the query.

query {
  getFamily(userId: "<UUID>") {
    id
    familyMembers {
      id
      role
    }
  }
}
barbieri commented 1 year ago

in GraphQL you're supposed to select all members you want. You're not selecting anything from getFamily and you're getting the auto-selection behavior that is depth-limited. See the section at https://sgqlc.readthedocs.io/en/latest/sgqlc.operation.html#selecting-to-generate-queries

I added this auto-select stuff to help some manual testing, but it turns its my biggest source of issues in this repo :-D On one hand, Python and REST people are not aware of GraphQL recommendation, they see it "just works!" and get going, but it's against GraphQL principles... so more often than not I regret having added that one.

Also take a look at https://sgqlc.readthedocs.io/en/latest/sgqlc.operation.html#sgqlc.operation.SelectionList.__fields__

nikaswoon commented 1 year ago

I have the same problem, but there is one thing i noticed, when i run my test in debug mode and go step by step in query 'building' digging inside of sgqlc lib, then i get result which i expected (with all nested nodes) but when i just run it(or debugging too fast) - then nested nodes are missing

looks like some part is not waiting enough to load nested nodes Exactly if i stop insidedef __getitem__(self, name) and waiting for selection to load before return - then everything works well

barbieri commented 1 year ago

I don't think it's related to waiting, there is nothing async. The behavior difference between the prompt and the script execution is keeping some variables/object alive, also when running in the prompt it will call repr() on the statement result, this causes the auto-selection...

barbieri commented 1 year ago

closing as it doesn't look like an issue, please reopen with more info if still an issue