Skip to content

Required fields not received by federated service from Gateway #7

Open
jgautheron/graphgate
#1
@jregistr

Description

@jregistr

Hello!
First, thank you for creating this Gateway.

I'm creating this issue for something I think I've found that's a bug behavior when running GraphGate against some federated services.

For context, I'm using the services under Apollo's Federation Demo
which consist of 4 services: [accounts,reviews,products,inventory].

Here's the query I'm using

query topProds {
  topProducts(first: 1) {
    upc
    inStock
    shippingEstimate
  } 
}

And for context, the shippingEstimate field is declared on the Inventory service extending the Product type and depends on the price and weight field on Product Type.

shippingEstimate: Int @requires(fields: "price weight")

Bug

I noticed the entity resolver for the Inventory service was receiving an object that only has the __typename and upc from graphgate when I selected the shippingEstimate.

 { __typename: 'Product', upc: '1' }

In contrast, when I run the same query but through Apollo's Node Gateway,
the Inventory service receives the price and weight as expected since they are labeled required by shippingEstimate.

{ __typename: 'Product', upc: '1', price: 899, weight: 100 }

Interestingly, I noticed this only happens when I select more than 1 field that come from the Inventory service(inStock).
Ex: When I use this query,

query topProds {
  topProducts(first: 1) {
    upc
    shippingEstimate
  } 
}

graphgate sends the full expected object

{ __typename: 'Product', price: 899, upc: '1', weight: 100 }

Since price and weight are missing, the resolver for shippingEstimate can't resolve.

Expected Behavior

Graphgate should send the Inventory service the price and weight field that are required for the shippingEstimate field.

Actual Behavior

In some situations, the required fields are missing in the object sent to the Federated service.

Steps to Reproduce the Problem

  1. Clone Apollo's federation demo, run npm install and then npm run start-services

  2. Configure graphgate with the following toml config.

    bind = "0.0.0.0:8000"
    
    forward_headers = []
    [jaeger]
    agent_endpoint = "127.0.0.1:6831"
    service_name = "graphgate"
    
    [[services]]
    name = "accounts"              
    addr = "127.0.0.1:4001"      
    query_path = "/"                
    subscribe_path = "/"            
    introspection_path = "/"      
    websocket_path = "/"            
    
    [[services]]
    name = "reviews"
    addr = "127.0.0.1:4002"
    
    
    [[services]]
    name = "products"
    addr = "127.0.0.1:4003"
    
    
    [[services]]
    name = "inventory"
    addr = "127.0.0.1:4004"
    
  3. Run the following query

    query topProds {
      topProducts(first: 1) {
        upc
        inStock
        shippingEstimate
      } 
    }

Your data should have an error.

{
  "data": {
    "topProducts": [
      {
        "upc": "1"
      }
    ]
  },
  "errors": [
    {
      "message": "Int cannot represent non-integer value: NaN",
      "path": [
        "topProducts",
        0,
        0,
        "shippingEstimate"
      ]
    }
  ]
}

Specifications

  • GraphGate Version: 0.5.1
  • Platform: MacOS Catalina
  • Federation Demo Commit Hash: e24d9aca9d7a8fe9490ab53efeddc2ef8152f4a1
  • Node Version: v14.17.0
  • NPM Version: 7.14.0

Additional details.

I captured 3 print outs of Query plans.
The first one is the Query Plan from Apollo's Node Gateway.
_query_plan_node_gateway.txt

This query plan is from GraphGate. I got it by adding this println!("{:#?}", plan); to shared_route_table.rs#169.
In this query plan, the RequiredRef { in the first fetchNode only has upc.
_query_plan_graphgate_missing_fields.txt

And lastly, this GraphGate query plan print out is when I don't query for the inStock field. Notably, the required RequiredRef { now has price and weight, and upc.

_query_plan_graphgate_has_price_weight.txt

Thanks! Please let me know if there's any other info I can provide that can help recreate the bug or invalidate this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions