Probablemente no haya tecnologías perfectas. Graphql no es una excepción. Si no ha tenido experiencia con esta tecnología, debe tener una buena idea de los problemas que puede tener y prepararse para ellos con anticipación.
Para empezar, diré que soy más partidario que adversario del uso de graphql cuando sea posible. Y no voy a disuadir a nadie sobre la conveniencia de usar esta tecnología. Y es por eso que planteo preguntas relacionadas con problemas no resueltos en el marco de la tecnología graphql.
Por ejemplo, para alguien puede ser inesperado que cada objeto en graphql tenga que describirse al menos dos veces: una como el tipo de retorno del objeto y una vez más como el tipo de entrada del objeto (ver
graphql.org/graphql-js/mutations- y-input-types ). Sin embargo, dije esto para empezar y ni siquiera lo considero un inconveniente significativo. Hoy nos centraremos en cuestiones que, por regla general, deben resolverse al desarrollar una aplicación que utiliza la tecnología graphql:
- Separación de acceso para usuarios y grupos de usuarios.
- Manejo de errores
- SELECCIONE N + 1 Problema
Separación de acceso para usuarios y grupos de usuarios.
graphql no sabe nada acerca de compartir el acceso entre usuarios y grupos. Por lo tanto, todo el trabajo de compartir el acceso es responsabilidad del desarrollador de la aplicación. El tercer parámetro pasa el objeto de contexto de la aplicación a la función de resolución. Por lo tanto, si, por ejemplo, trabaja con la implementación de graphql JavaScript + express, en el parámetro de contexto puede obtener el usuario actual del objeto de solicitud express.js. Pero el trabajo adicional sobre el control de acceso debe llevarse a cabo directamente en cada resolutor:
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; } }); }
Naturalmente, este enfoque complica el control de acceso porque no hay forma de establecer derechos de acceso de manera declarativa, y el control de los derechos se dispersa en docenas (para algunos sistemas grandes, más de miles) de funciones de resolución. Por lo tanto, hay varias bibliotecas que resuelven este problema. Algunos de ellos son bastante populares (a juzgar por el número de estrellas en github.com), por ejemplo
github.com/maticzav/graphql-shield .
Manejo de errores
Si su interfaz requiere validación de entrada y la generación de mensajes detallados para cada campo que no ha pasado la validación, entonces el manejo de errores en graphql probablemente no le parecerá lo suficientemente flexible. Por ejemplo, si el parámetro de entrada se describió como una cadena y se recibió un valor numérico, entonces el mensaje de error será de poca utilidad para esto:
{ "errors": [ { "message": "Expected type String, found 1.", "locations": [ { "line": 2, "column": 15 } ] } ] }
Si hay un error grave en el tipo de parámetro de entrada, se generará automáticamente un mensaje de error y no hay forma de controlar este proceso. Si la validación por tipo de parámetro de entrada fue exitosa, entonces es posible enviar un mensaje de error personalizado al cliente lanzando un
new Error ('custom message ...')
objeto de
new Error ('custom message ...')
. No funcionará agregar campos personalizados al objeto de error (la personalización de errores se implementa en las bibliotecas apollo-server-express y apollo-errors cuando se usan juntas). Por supuesto, siempre existe la oportunidad de serializar el objeto en una cadena de
message
en el servidor y deserializarlo en el cliente. ¿Pero es necesario hacerlo?
SELECCIONE N + 1 Problema
Este problema se discutió en detalle en el mensaje .
Graphql se basa en funciones de resolución. Esto significa que recuperar datos de la base de datos puede causar un problema llamado SELECT N + 1. Suponga que en la función de resolución se obtuvo una lista de objetos en la que los datos asociados con este objeto están representados por identificadores (claves foráneas). Para cada uno de estos identificadores, se llamará a su propio resolutor de funciones, en el cual (en cada uno) se realizará una solicitud adicional a la base de datos. Por lo tanto, en lugar de una única consulta de base de datos (con SQL JOIN), se ejecutarán muchas consultas, lo que sobrecargará la base de datos con consultas.
Para resolver este problema, Facebook desarrolló la biblioteca
github.com/graphql/dataloader , que utiliza una estrategia de solicitud pendiente. En lugar de ejecutar la solicitud directamente en el solucionador de funciones, se propone acumular identificadores (claves secundarias) en la matriz y luego recibirlos inmediatamente con una solicitud.
apapacy@gmail.com
13 de mayo de 2019