Skip to content

federation: queries for interface types require knowledge of concrete implementations #336

@lennyburdette

Description

@lennyburdette

Version: @apollo/gateway@0.6.6
Reproduction: https://github.com/apollographql/federation-demo/compare/master...lennyburdette:interfaces?expand=1
Related issues: apollographql/apollo-server#2848

I changed the federation-demo to use an interface for the Product type. I could get it to work, but not without some hacks that won't work in the real world.

The Reviews service has to know about Product implementations (Book and Furniture), even though it only knows about Product.id.

For this query:

{
  me {
    reviews {
      product {
        id # doesn't work without https://github.com/apollographql/apollo-server/pull/2848
	name
        price
        inStock
        ... on Furniture {
          shippingEstimate
        }
      }
    }
  }
}

I see this in the query plan:

Fetch(service: "reviews") {
  {
    ... on User {
      __typename
      id
    }
  } =>
  {
    ... on User {
      reviews {
        product {
          __typename
          id
          ... on Book {
            __typename
            id
          }
          ... on Furniture {
            __typename
            id
          }
        }
      }
    }
  }
},

Because the Gateway fetches __typename, I have to implement Product.__resolveType (in a gross way.)

This is often very hard and sometimes impossible, depending on how much information the service stores. Reviews doesn't know anything about Products other than the id, so there's no way for it to return the correct __typename.

Ideally, the query to Reviews would be:

{
  ... on User {
    reviews {
      body
      product {
        # ideally we wouldn't subselect __typename here so that the Reviews service
        # doesn't have to care about interface implementations
        id
      }
    }
  }
}

This is less of a problem for the Inventory service because:

  • We use the ids from Reviews to call the Products service, which can return __typenames.
  • We fetch Inventory fields using references ({ __typename: "Furniture", id: "1" }), so Inventory can just return the given __typename.

(There's also some unfortunate redundancy in Reviews and Inventory—we have to repeat __resolveReference functions for each interface implementation, but I can solve that on my side.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions