Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How bad would it be to have nested mutations?

Tags:

graphql

I am aware that it would be considered as an anti-pattern, but why exactly?

mutation {
  createUser(name: "john doe") {
    addToTeam(teamID: "123") {
      name,
      id
    },

    id
  }
}

Wouldn't it be more convenient than two HTTP calls?

mutation {
  createUser(name: "john doe") {
    id, # we store the ID
  }
}

mutation {
  addToTeam(userID: id, teamID: "123") {
    name,
    id,
  }
}
like image 882
Guillaume Badi Avatar asked Dec 19 '22 11:12

Guillaume Badi


2 Answers

If you have a relation between Team and User, you could expose this API:

Create user, relate to existing team

mutation {
  createUser(name: "john doe", teamId: "team-id") {
    id
    team {
      id
    }
  }
}

Create new user and new team

mutation {
  createUser(name: "john doe", team: {name: "New team"}) {    
    id
    team {
      id
    }
  }
}

This is exactly how the Graphcool API handles this as shown in this blog article. You can find another example in the documentation.

like image 93
marktani Avatar answered Feb 01 '23 19:02

marktani


There are two reasons why this is an anti-pattern:

First, there are two atomic operations here, each may involve some extra logic related to authentication, validation, and yield different errors. So mixing them together could lead to some extra complexity.

For example, say a team can only have 10 people, and it has reached its max. Should the compose operation fail altogether? Shall we just add the user but not add it to the team? What the response will look like?

Second, lumping two operations in such way may potentially expose application logic. One can be tempted to use such mutations to perform 'When X happens Y should also happen as well'. For instance, when adding a new line to an invoice, the total should update. This should really happen with one mutation, addLineToInvoice, and have the logic reside on the server.

In a way, the command part of APIs is better being process (or action) centric, rather than data centric. If your API calls are focused on data manipulation, you are risking loading the client with business logic that should live in the server. You may also be losing on quite a few goodies like middleware (which is great for cross-cutting concerns, like permissions and logging).

like image 42
Izhaki Avatar answered Feb 01 '23 19:02

Izhaki