How to deal with errors when working with two different services

Hi all,

We have a problem that I am wondering how other people solve. E.g. you have two services, let’s say a Search and a Post service, where Post decorates Search.

Search

@key post.id
SearchResult {
  post: [Post!]!
}

Post

Post {
  id: ID! @key
  subject: String
  body: String

Now the Search returns a list of ids, that need to be decorated by the Post service. However lets say for some reason an error is returned on one of the Post entities, how do you deal with that? You would still need to return the Post entity, but now just with a uri and a error in the errors field? How do others deal with decoration errors? In an ideal world, I would prefer to filter out the failing Post entity, however this is not possible because it is already setup in the list and from the Post service I cannot filter it out.

Any ideas? Whats a proper approach here?

Thanks,

Kenneth

GraphQL typically uses an object field resolution method, a la the Visitor pattern.

The normal way to handle errors in GraphQL is to return an object as a field, then return additional fields on that object with separate resolvers, and so on.

For example, if you need to resolve a base object you would use something like __resolveObject to fetch the base object, and for non-trivial fields, use separate resolvers.

const resolvers = {
  Post: {
    __resolveObject: async (parent = {}, fields, ...) => {
      const { id } = parent;
      if (!id) return null;
      return await database.findOne(entities.Post, { id });
    },
    uri: async (parent = {}, args, context, info) => {
      const { id } = parent;
      if (!id) return null;
      return await database.findOne(entities.PostUri, { where: { Post: id }});
    }
  }
}

So in this example if uri errors out, you should expect:

{
  data: {
    post: {
      id: "123",
      subject: "a subject line",
      body: "...",
      uri: null
    }
  },
  errors: [
    {
      path: "post.uri",
      code: "INTERNAL_SERVER_ERROR",
      message: "something went wrong"
    }
  ]
}

If your question is not solved by an approach like that, perhaps the new version of federation has a bug, but I’m pretty sure this convention of partial errors is well-established at this point.

Hi Kevin, thanks for your response! I didnt formulate it properly as I mixed up uri and id. I meant id. So lets say Search returns a bunch of ids, then the decorating service, Post, has one it cannot find, it cannot decorate that and the result should probably be null or even an alternative result, e.g.

what will happen, if id is found but the decorating bits arent, see id: 2

[{
  id: 1
  subject: "whoop",
  body: "whap"
},
{
  id: 2,
  subject: null,
  body: null
}]

what i would like, either it becomes null if the decorating bits arent there, or i would like to filter this out.

[{
  id: 1
  subject: "whoop",
  body: "whap"
},
null
]

Any ideas how to achieve this bit, sorry for the miscommunication

Are you using __resolveObject?

I ask because I think it overrides fields, but I’m not sure.

You could test this behavior by:

  1. provide id for Post
  2. use Post.__resolveObject and return null
  3. check if the object is correctly returned as null, or if it’s “incorrectly” returned as { id: number }.