99designs / gqlgen

go generate based graphql server library
https://gqlgen.com
MIT License
9.86k stars 1.15k forks source link

Using @entityResolver(multi: true) causes "directive entityResolver is not implemented" to be thrown when the entity is used in another Query #3160

Open RyanMcCabe-catapult opened 2 months ago

RyanMcCabe-catapult commented 2 months ago

What happened?

I have a shared entity between two subgraphs, to keep things simple I'll call them the List service and the Item service. Items can be retrieved in 3 ways:

  1. Items may appear as a collection of Items under a List (a federated entity between the List and Item services)
  2. They may be queried for against the Item service using some filters (Query definition: items(filter: ItemsFilter!):ItemPage)
  3. They may be queried for directly against the Item service if the ID is known (Query definition: item(id:ID!): Item)

I've set these up using the directive @key(fields: "id") and everything works as expected. The requests to resolve large lists of items was a performance concern as each item was being resolved with a single request to the Item service, so in order to reduce this to a single call I introduced the @entityResolver(multi: true) directive to the entity definition in the Item service. This worked fine for the federated calls and only a single request was being made to resolve multiple Item IDs (scenario 1). However in scenario 2 and 3 I'm now getting a Failed to query 'items': directive entityResolver is not implemented and a Failed to query 'item': directive entityResolver is not implemented error message for the corresponding queries. From debugging the generated code, it seems that for scenario 2 the correct item filter resolver is called and returns the data, it then tries to resolve the fields and throws the error. For scenario 3, the item by id resolver is never called and the error is thrown.

What did you expect?

I expected the queries in scenarios 2 and 3 above to continue working after the @entityResolver(multi: true) directive was introduced.

Minimal graphql.schema and models to reproduce

If the resolvers are generated for the following, the single resolver query will work as expected, the multi resolver query will show the issue.

type RegularEntity @key(fields: "id") {
    id: ID!
    Name: String!
}

type RegularEntityWrapper {
    id: ID!
    Name: String!
    Entity: RegularEntity!
}

type MultiResolverEntity @key(fields: "id") @entityResolver(multi: true) {
    id: ID!
    Name: String!
}

type MultiResolverEntityWrapper {
    id: ID!
    Name: String!
    Entity: MultiResolverEntity!
}

type Query {
    singleResolver: RegularEntityWrapper
    multiResolver: MultiResolverEntityWrapper
}

versions

markkrijgsman commented 1 month ago

I have the same issue, my minimum schema is as follows:

extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key"])

directive @entityResolver(multi: Boolean) on OBJECT

type RecursiveEntity @key(fields: "id") @entityResolver(multi: true) {
    id: ID!
    children: [RecursiveEntity!]
}

The following query works:

query ($representations: [_Any!]!) {
  _entities(representations: $representations) {
    ... on RecursiveEntity {
      id    
    }
  }
}

But as soon as the children are requested, the request fails:

query ($representations: [_Any!]!) {
  _entities(representations: $representations) {
    ... on RecursiveEntity {
      id
      children {
        id
      }
    }
  }
}

Variables payload is the same for both requests:

{
  "representations": [
    {
    "__typename": "RecursiveEntity",
    "id": "42"
    }
  ]
}

I'm using gqlgen v0.17.43 on Go 1.21.