Probably there is no perfect technology. Not an exception and graphql. If you have not yet had experience with this technology, then you need to be well aware of what problems you may have and prepare in advance for them.
To begin with, I’ll say that I’m rather a supporter than an adversary, using graphql terms and conditions whenever possible. And I am absolutely not going to dissuade anyone from the expediency of using this technology. And that is why I raise questions that relate to outstanding issues within the graphql technology.
For example, it may be unexpected for someone that each object in graphql will have to be described at least twice: once as the return type of the object, and once more as the input type of the object (see
graphql.org/graphql-js/mutations- and-input-types ). However, I told this to begin with and do not even consider it a significant drawback. Today we will discuss such issues, which, as a rule, have to be solved when developing an application using graphql technology:
- Separate access for users and user groups.
- Error processing.
- SELECT N + 1 Problem
Separate access for users and user groups
graphql knows nothing about sharing access for users and groups. Thus, all work on sharing access to the responsibility of the application developer. In the resolver function, the third parameter is the application context object. Therefore, if you, for example, work with the graphql JavaScript + express implementation, then in the context parameter you will be able to get the current user from the request express.js object. But further work on access control should be carried out directly in each resolver:
')
function(root, {id}, ctx) { return DB.Lists.get(id) .then( list => { if(list.owner_id && list.owner_id != ctx.userId){ throw new Error("Not authorized to see this list"); } else { return list; } }); }
Naturally, this approach complicates the control of access rights, since there is no possibility to set access rights in a declarative manner and control of rights is dispersed among dozens (for some large systems by thousands) of resolver functions. Therefore, there are a number of libraries that solve this problem. Some of them are quite popular (judging by the number of stars on github.com), for example
github.com/maticzav/graphql-shield .
Error processing
If your frontend requires input validation and the formation of detailed messages for each field that has not passed validation, then error handling in graphql will most likely seem to you not flexible enough. For example, if the input parameter was described as a string, and a numeric value arrived, then an error message would not be suitable for this:
{ "errors": [ { "message": "Expected type String, found 1.", "locations": [ { "line": 2, "column": 15 } ] } ] }
If there is a gross error in the type of the input parameter, then an error message will be generated automatically and there is no possibility to control this process. If validation on the input parameter type is successful, then there is an opportunity to send a custom error message to the client, throwing out the
new Error ('custom message ...')
object. Add custom fields to the error object will not work (error customization is implemented in the apollo-server-express and apollo-errors libraries when used together). Of course, there is always the possibility of serializing an object into the
message
string on the server and deserializing on the client. But is it necessary to do so?
SELECT N + 1 Problem
This problem was discussed in detail in the message .
graphql is built on resolver functions. This means that fetching data from a database can cause a problem called SELECT N + 1. Suppose that in the resolver function a list of objects was obtained, in which the data associated with this object is represented by identifiers (foreign keys). For each such identifier, its own resolver function will be called, in which (in each) a database query will be additionally made. Thus, instead of a single database query (with SQL JOIN), many queries will be executed, which overloads the database with queries.
To solve this problem, facebook has developed the
github.com/graphql/dataloader library, which uses a pending query strategy. Instead of executing the query directly in the resolver function, it is proposed to accumulate identifiers (secondary keys) in the array, and then receive them immediately in one query.
apapacy@gmail.com
May 13, 2019