graphql - armadilhas

Provavelmente não há tecnologias perfeitas. Graphql não é excepção. Se você não teve experiência com essa tecnologia, precisa ter uma boa idéia de quais problemas você pode ter e se preparar para eles com antecedência.

Para começar, direi que sou mais um defensor do que um adversário do uso do graphql sempre que possível. E não vou dissuadir ninguém sobre a adequação do uso dessa tecnologia. E é por isso que eu levanto questões relacionadas a questões não resolvidas na estrutura da tecnologia graphql.

Por exemplo, para alguém, pode ser inesperado que cada objeto no graphql precise ser descrito pelo menos duas vezes: uma vez como o tipo de retorno do objeto e outra vez como o tipo de entrada do objeto (consulte graphql.org/graphql-js/mutations- e tipos de entrada ). No entanto, eu disse isso para começar e nem considero uma desvantagem significativa. Hoje vamos nos concentrar em questões que, em regra, precisam ser resolvidas ao desenvolver um aplicativo usando a tecnologia graphql:

  1. Separação de acesso para usuários e grupos de usuários.
  2. Tratamento de erros.
  3. SELECT N + 1 Problema

Separação de acesso para usuários e grupos de usuários


O graphql não sabe nada sobre o compartilhamento de acesso entre usuários e grupos. Assim, todo o trabalho de compartilhamento de acesso é de responsabilidade do desenvolvedor do aplicativo. O terceiro parâmetro passa o objeto de contexto do aplicativo para a função resolvedor. Portanto, se você, por exemplo, trabalha com a implementação do graphql JavaScript + express, no parâmetro context você pode obter o usuário atual a partir do objeto request express.js. Porém, mais trabalho sobre controle de acesso deve ser realizado diretamente em cada resolvedor:

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, essa abordagem complica o controle de acesso porque não há como definir direitos de acesso de maneira declarativa, e o controle dos direitos é disperso por dezenas (para alguns sistemas grandes, por milhares) de funções do resolvedor. Portanto, há várias bibliotecas que resolvem esse problema. Alguns deles são bastante populares (a julgar pelo número de estrelas no github.com), por exemplo, github.com/maticzav/graphql-shield .

Tratamento de erros


Se o seu front-end requer validação de entrada e geração de mensagens detalhadas para cada campo que não passou na validação, o tratamento de erros no graphql provavelmente parecerá não ser flexível o suficiente para você. Por exemplo, se o parâmetro de entrada foi descrito como uma sequência e um valor numérico foi recebido, a mensagem de erro será de pouca utilidade para isso:

 { "errors": [ { "message": "Expected type String, found 1.", "locations": [ { "line": 2, "column": 15 } ] } ] } 

Se houver um erro grave no tipo de parâmetro de entrada, uma mensagem de erro será gerada automaticamente e não há como controlar esse processo. Se a validação por tipo de parâmetro de entrada foi bem-sucedida, é possível enviar uma mensagem de erro personalizada ao cliente lançando um new Error ('custom message ...') objeto de new Error ('custom message ...') . Não funcionará para adicionar campos personalizados ao objeto de erro (a personalização de erros é implementada nas bibliotecas apollo-server-express e apollo-errors quando usadas juntas). Obviamente, sempre há a oportunidade de serializar o objeto em uma cadeia de message no servidor e desserializar no cliente. Mas é necessário fazê-lo?

SELECT N + 1 Problema


Esse problema foi discutido em detalhes na mensagem .

O graphql é construído sobre as funções do resolvedor. Isso significa que a busca de dados no banco de dados pode causar um problema chamado SELECT N + 1. Suponha que na função resolvedor tenha sido obtida uma lista de objetos em que os dados associados a esse objeto são representados por identificadores (chaves estrangeiras). Para cada um desses identificadores, será chamado seu próprio resolvedor de funções, no qual (em cada) uma solicitação adicional ao banco de dados será feita. Portanto, em vez de uma única consulta ao banco de dados (com SQL JOIN), muitas consultas serão executadas, o que sobrecarrega o banco de dados com consultas.

Para resolver esse problema, o facebook desenvolveu a biblioteca github.com/graphql/dataloader , que usa uma estratégia de solicitação pendente. Em vez de executar a solicitação diretamente no resolvedor de funções, propõe-se acumular identificadores (chaves secundárias) na matriz e recebê-los imediatamente com uma solicitação.

apapacy@gmail.com
13 de maio de 2019

Source: https://habr.com/ru/post/pt451466/


All Articles