AWS AppSync: Retornando valores nullables em resolvers aninhados

Image for post
Image for post

Enquanto trabalhava em um projeto de um cliente, encontrei um problema interessante com o AppSync, que não consegui encontrar uma resposta depois de pesquisar bastante. Espero que este artigo possa te poupar a mesma dor, caso você encontre o mesmo problema.

O problema é que, quando você tem um campo aninhado anulável, e que você deseja expandir seu tipo, precisamos manipular os valores nulos no modelo VTL e ignorá-los. Não era óbvio como fazer isso em um sistema gerenciado como o AppSync.

Para ter uma idéia melhor do que estou falando, aqui está uma versão drasticamente simplificada do esquema GraphQL.

type University {
name: String!
categories: [Category!]
}
type Category {
name: String!
sports: [CategorySport!]
}
type CategorySport {
name: String!
description: String
coach: Coach # in the DynamoDB table, this is stored as a String
}
type Coach {
id: ID!
firstName: String!
lastName: String!
}
Image for post
Image for post

Na tabela DynamoDB, as universidades são armazenadas na tabela University e os usuários na tabela User. Categorias e esportes são modelados como propriedades de uma universidade para minimizar o número de leituras no DynamoDB. E o campo CategorySport.coach é o ID do perfil de um usuário na tabela User.

Image for post
Image for post

Para tornar mais fácil para a interface do usuário consumir os dados, expandimos o campo CategorySport.coach para ser um tipo Coach completo.

Então, configurei o resolver para esse campo aninhado e apontei para a tabela User.

Nota: Estou usando Serverless Framework com o excelente plugin serverless-appsync para me ajudar a configurar tudo isso.

mappingTemplates:
- type: CategorySport
field: coach
dataSource: userTable

dataSources:
- type: AMAZON_DYNAMODB
name: userTable
config:
tableName: !Ref UserTable

E eu configurei os modelos de VTL para a solicitação e resposta.

Solicitação:

{
"version" : "2017-02-28",
"operation" : "GetItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($context.source.coach)
}
}

Resposta:

$util.toJson($context.result)

E tudo funciona muito bem, exceto quando CategorySport.coach é null.

Image for post
Image for post

O que eu precisava era de uma maneira de fazer um curto-circuito na solicitação DynamoDB.GetItem quando CategorySport.coach for null. Depois de muita pesquisa, meu googling não deu em nada e eu me virei para o meu bom amigo Heitor Lessa. Ele me indicou este útil artigo, que mencionava a palavra-chave #returnque permite fazer um curto-circuito na execução do resolver e retornar mais cedo.

O uso de #return no modelo de mapeamento de uma função retornará esses dados da função. Se você usá-lo em um modelo de mapeamento de solicitação, o modelo de mapeamento de resposta será ignorado. Da mesma forma, o uso de #return no modelo de mapeamento de um resolver retornará esses dados do resolver, encerrando prematuramente a execução do resolver.

Com isso, pude solucionar o problema adicionando apenas 3 linhas de código ao meu modelo de solicitação.

#if ($util.isNullOrEmpty($context.source.coach))
#return
#end
{
"version" : "2017-02-28",
"operation" : "GetItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($context.source.coach)
}
}

Uma coisa a observar é que você não pode ter #return(null) mas #return seria null como resultado do resolver e pula a operação do DynamoDB.GetItem e o modelo de resposta por completo.

Gostou deste artigo? Apoie-me no Patreon e obtenha ajuda direta de mim por meio de um canal privado do Slack ou por 1–2–1.

Créditos

Written by

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store