Usando operações em lote do DynamoDB em AWS AppSync - AWS AppSync

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Usando operações em lote do DynamoDB em AWS AppSync

nota

Agora, oferecemos suporte principalmente ao tempo de execução APPSYNC _JS e sua documentação. Considere usar o tempo de execução APPSYNC _JS e seus guias aqui.

AWS AppSync suporta o uso de operações em lote do Amazon DynamoDB em uma ou mais tabelas em uma única região. As operações compatíveis são BatchGetItem, BatchPutItem e BatchDeleteItem. Ao usar esses recursos no AWS AppSync, você pode realizar tarefas como:

  • Enviar uma lista de chaves em uma única consulta e retornar os resultados de uma tabela

  • Ler os registros de uma ou mais tabelas em uma única consulta

  • Gravar registros em lote em uma ou mais tabelas

  • Gravar ou excluir registros condicionalmente em várias tabelas que podem ter uma relação

Usar operações em lote com o DynamoDB AWS AppSync in é uma técnica avançada que exige um pouco mais de reflexão e conhecimento sobre suas operações de back-end e estruturas de tabelas. Além disso, as operações em lote AWS AppSync têm duas diferenças principais em relação às operações sem lote:

  • A função da fonte de dados deve ter permissões para todas as tabelas acessadas pelo resolvedor.

  • A especificação de tabela para um resolvedor faz parte do modelo de mapeamento.

Permissões

Como outros resolvedores, você precisa criar uma fonte de dados AWS AppSync e criar uma função ou usar uma existente. Como operações em lote exigem diferentes permissões em tabelas do DynamoDB, é necessário conceder as permissões de função configuradas para ações de leitura e gravação:

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:account:table/TABLENAME", "arn:aws:dynamodb:region:account:table/TABLENAME/*" ] } ] }

Observação: as funções estão vinculadas às fontes de dados em AWS AppSync, e os resolvedores nos campos são invocados em relação a uma fonte de dados. As fontes de dados configuradas para buscar no DynamoDB têm apenas uma tabela especificada, para manter a configuração simples. Portanto, ao executar uma operação em lote para várias tabelas em um único resolvedor, que é uma tarefa mais avançada, é necessário conceder acesso à função na fonte de dados para qualquer tabela com a qual o resolvedor interage. Isso seria feito no campo Recurso na IAM política acima. A configuração das tabelas para realizar chamadas de lote é feita no modelo de resolvedor, descrita abaixo.

Fonte de dados

Para simplificar, usaremos a mesma fonte de dados para todos os resolvedores usados neste tutorial. Na guia Fontes de dados, crie uma nova fonte de dados do DynamoDB e nomeie-a. BatchTutorial O nome da tabela pode ser qualquer coisa pois os nomes de tabelas são especificados como parte do modelo de mapeamento da solicitação para operações em lote. Chamaremos a tabela de empty.

Para esse tutorial, qualquer função com a seguinte política em linha funcionará:

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:account:table/Posts", "arn:aws:dynamodb:region:account:table/Posts/*", "arn:aws:dynamodb:region:account:table/locationReadings", "arn:aws:dynamodb:region:account:table/locationReadings/*", "arn:aws:dynamodb:region:account:table/temperatureReadings", "arn:aws:dynamodb:region:account:table/temperatureReadings/*" ] } ] }

Lote de tabela única

Atenção

BatchPutIteme não BatchDeleteItem são compatíveis quando usados com detecção e resolução de conflitos. Essas configurações devem ser desativadas para evitar possíveis erros.

Para este exemplo, digamos que tenha uma única tabela chamada Publicações à qual você deseja adicionar e remover itens com operações em lote. Use o esquema a seguir, observando que, para a consulta, passaremos uma lista deIDs:

type Post { id: ID! title: String } input PostInput { id: ID! title: String } type Query { batchGet(ids: [ID]): [Post] } type Mutation { batchAdd(posts: [PostInput]): [Post] batchDelete(ids: [ID]): [Post] } schema { query: Query mutation: Mutation }

Anexe um resolvedor ao campo batchAdd() com o seguinte Modelo de mapeamento da solicitação. Isso recebe automaticamente cada item no tipo input PostInput do GraphQL e cria um mapa, que é necessário para a operação BatchPutItem:

#set($postsdata = []) #foreach($item in ${ctx.args.posts}) $util.qr($postsdata.add($util.dynamodb.toMapValues($item))) #end { "version" : "2018-05-29", "operation" : "BatchPutItem", "tables" : { "Posts": $utils.toJson($postsdata) } }

Nesse caso, o Modelo de mapeamento da resposta é uma simples passagem, mas observe que o nome da tabela está anexado como ..data.Posts ao objeto de contexto:

$util.toJson($ctx.result.data.Posts)

Agora, navegue até a página Consultas do AWS AppSync console e execute a seguinte batchAddmutação:

mutation add { batchAdd(posts:[{ id: 1 title: "Running in the Park"},{ id: 2 title: "Playing fetch" }]){ id title } }

Veja os resultados impressos na tela e valide-os de forma independente por meio do console do DynamoDB que ambos os valores gravaram na tabela Publicações.

Em seguida, anexe um resolvedor ao campo batchGet() com o seguinte Modelo de mapeamento da solicitação. Isso recebe automaticamente cada item no tipo ids:[] do GraphQL e cria um mapa, que é necessário para a operação BatchGetItem:

#set($ids = []) #foreach($id in ${ctx.args.ids}) #set($map = {}) $util.qr($map.put("id", $util.dynamodb.toString($id))) $util.qr($ids.add($map)) #end { "version" : "2018-05-29", "operation" : "BatchGetItem", "tables" : { "Posts": { "keys": $util.toJson($ids), "consistentRead": true, "projection" : { "expression" : "#id, title", "expressionNames" : { "#id" : "id"} } } } }

O Modelo de mapeamento da resposta é novamente uma simples passagem, de novo com o nome da tabela anexado como ..data.Posts ao objeto de contexto:

$util.toJson($ctx.result.data.Posts)

Agora, volte para a página Consultas do AWS AppSync console e execute a seguinte batchGet consulta:

query get { batchGet(ids:[1,2,3]){ id title } }

Isso deve retornar os resultados para os dois valores id adicionados anteriormente. Observe que um valor null foi retornado para o id com um valor de 3. Isso ocorre porque não havia registro na tabela Publicações com esse valor ainda. Observe também que AWS AppSync retorna os resultados na mesma ordem das chaves passadas para a consulta, que é um recurso adicional que AWS AppSync funciona em seu nome. Portanto, se você alternar para batchGet(ids:[1,3,2), verá a ordem alterada. Você também saberá qual id retornou um valor null.

Finalmente, anexe um resolvedor ao campo batchDelete() com o seguinte Modelo de mapeamento da solicitação. Isso recebe automaticamente cada item no tipo ids:[] do GraphQL e cria um mapa, que é necessário para a operação BatchGetItem:

#set($ids = []) #foreach($id in ${ctx.args.ids}) #set($map = {}) $util.qr($map.put("id", $util.dynamodb.toString($id))) $util.qr($ids.add($map)) #end { "version" : "2018-05-29", "operation" : "BatchDeleteItem", "tables" : { "Posts": $util.toJson($ids) } }

O Modelo de mapeamento da resposta é novamente uma simples passagem, de novo com o nome da tabela anexado como ..data.Posts ao objeto de contexto:

$util.toJson($ctx.result.data.Posts)

Agora, volte para a página de consultas do AWS AppSync console e execute a seguinte batchDeletemutação:

mutation delete { batchDelete(ids:[1,2]){ id } }

Os registros com id, 1 e 2 devem ser excluídos agora. Se você executar novamente a consulta batchGet() de anteriormente, eles devem retornar null.

Lote de várias tabelas

Atenção

BatchPutIteme não BatchDeleteItem são compatíveis quando usados com detecção e resolução de conflitos. Essas configurações devem ser desativadas para evitar possíveis erros.

AWS AppSync também permite que você execute operações em lote nas tabelas. Vamos criar um aplicativo mais complexo. Imagine que estamos criando um aplicativo de Saúde do animal de estimação, onde sensores relatam a localização do animal e a temperatura do corpo. Os sensores são alimentados por bateria e tentam se conectar à rede a cada cinco minutos. Quando um sensor estabelece a conexão, ele envia suas leituras para o nosso. AWS AppSync API Em seguida, os gatilhos analisam os dados para que um painel seja apresentado ao dono do animal. Vamos nos concentrar na representação das interações entre o sensor e o armazenamento de dados de back-end.

Como pré-requisito, vamos primeiro criar duas tabelas do DynamoDB; armazenará as leituras da localização do sensor e locationReadingsarmazenará as leituras da temperatura do sensor. temperatureReadings Ambas as tabelas compartilham a mesma estrutura de chave primária: sensorId (String) sendo a chave de partição e timestamp (String) a chave de classificação.

Vamos usar o seguinte esquema do GraphQL:

type Mutation { # Register a batch of readings recordReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult # Delete a batch of readings deleteReadings(tempReadings: [TemperatureReadingInput], locReadings: [LocationReadingInput]): RecordResult } type Query { # Retrieve all possible readings recorded by a sensor at a specific time getReadings(sensorId: ID!, timestamp: String!): [SensorReading] } type RecordResult { temperatureReadings: [TemperatureReading] locationReadings: [LocationReading] } interface SensorReading { sensorId: ID! timestamp: String! } # Sensor reading representing the sensor temperature (in Fahrenheit) type TemperatureReading implements SensorReading { sensorId: ID! timestamp: String! value: Float } # Sensor reading representing the sensor location (lat,long) type LocationReading implements SensorReading { sensorId: ID! timestamp: String! lat: Float long: Float } input TemperatureReadingInput { sensorId: ID! timestamp: String value: Float } input LocationReadingInput { sensorId: ID! timestamp: String lat: Float long: Float }

BatchPutItem - Gravação de leituras do sensor

Nossos sensores precisam ser capazes de enviar suas leituras assim que se conectarem à internet. O campo GraphQL Mutation.recordReadings é o API que eles usarão para fazer isso. Vamos conectar um resolvedor para dar vida API ao nosso.

Selecione Anexar ao lado do campo Mutation.recordReadings. Na próxima tela, escolha a mesma fonte de dados BatchTutorial criada no início do tutorial.

Vamos adicionar o seguinte modelo de mapeamento da solicitação:

Modelo de mapeamento da solicitação

## Convert tempReadings arguments to DynamoDB objects #set($tempReadings = []) #foreach($reading in ${ctx.args.tempReadings}) $util.qr($tempReadings.add($util.dynamodb.toMapValues($reading))) #end ## Convert locReadings arguments to DynamoDB objects #set($locReadings = []) #foreach($reading in ${ctx.args.locReadings}) $util.qr($locReadings.add($util.dynamodb.toMapValues($reading))) #end { "version" : "2018-05-29", "operation" : "BatchPutItem", "tables" : { "locationReadings": $utils.toJson($locReadings), "temperatureReadings": $utils.toJson($tempReadings) } }

Como você pode ver, a operação BatchPutItem nos permite especificar várias tabelas.

Vamos usar o seguinte modelo de mapeamento da resposta.

Modelo de mapeamento da resposta

## If there was an error with the invocation ## there might have been partial results #if($ctx.error) ## Append a GraphQL error for that field in the GraphQL response $utils.appendError($ctx.error.message, $ctx.error.message) #end ## Also returns data for the field in the GraphQL response $utils.toJson($ctx.result.data)

Com operações em lote, podem haver erros e resultados retornados na invocação. Nesse caso, podemos fazer uma manipulação de erros adicional.

Observação: o uso de $utils.appendError() é semelhante ao $util.error(), com a principal distinção de que ele não interrompe a avaliação do modelo de mapeamento. Em vez disso, ele sinaliza que ocorreu um erro com o campo, mas permite que o modelo seja avaliado e, consequentemente, retorne dados ao chamador. Recomendamos que você use $utils.appendError() quando o aplicativo precisar retornar resultados parciais.

Salve o resolvedor e navegue até a página Consultas do AWS AppSync console. Vamos enviar algumas leituras do sensor!

Execute a seguinte mutação:

mutation sendReadings { recordReadings( tempReadings: [ {sensorId: 1, value: 85.5, timestamp: "2018-02-01T17:21:05.000+08:00"}, {sensorId: 1, value: 85.7, timestamp: "2018-02-01T17:21:06.000+08:00"}, {sensorId: 1, value: 85.8, timestamp: "2018-02-01T17:21:07.000+08:00"}, {sensorId: 1, value: 84.2, timestamp: "2018-02-01T17:21:08.000+08:00"}, {sensorId: 1, value: 81.5, timestamp: "2018-02-01T17:21:09.000+08:00"} ] locReadings: [ {sensorId: 1, lat: 47.615063, long: -122.333551, timestamp: "2018-02-01T17:21:05.000+08:00"}, {sensorId: 1, lat: 47.615163, long: -122.333552, timestamp: "2018-02-01T17:21:06.000+08:00"} {sensorId: 1, lat: 47.615263, long: -122.333553, timestamp: "2018-02-01T17:21:07.000+08:00"} {sensorId: 1, lat: 47.615363, long: -122.333554, timestamp: "2018-02-01T17:21:08.000+08:00"} {sensorId: 1, lat: 47.615463, long: -122.333555, timestamp: "2018-02-01T17:21:09.000+08:00"} ]) { locationReadings { sensorId timestamp lat long } temperatureReadings { sensorId timestamp value } } }

Enviamos dez leituras do sensor em uma mutação, com as leituras divididas em duas tabelas. Use o console do DynamoDB para validar se os dados aparecem nas tabelas e. locationReadingstemperatureReadings

BatchDeleteItem - Excluindo leituras do sensor

Da mesma forma, também será necessário excluir lotes de leituras do sensor. Vamos usar o campo do GraphQL Mutation.deleteReadings para essa finalidade. Selecione Anexar ao lado do campo Mutation.recordReadings. Na próxima tela, escolha a mesma fonte de dados BatchTutorial criada no início do tutorial.

Vamos usar o seguinte modelo de mapeamento da solicitação.

Modelo de mapeamento da solicitação

## Convert tempReadings arguments to DynamoDB primary keys #set($tempReadings = []) #foreach($reading in ${ctx.args.tempReadings}) #set($pkey = {}) $util.qr($pkey.put("sensorId", $reading.sensorId)) $util.qr($pkey.put("timestamp", $reading.timestamp)) $util.qr($tempReadings.add($util.dynamodb.toMapValues($pkey))) #end ## Convert locReadings arguments to DynamoDB primary keys #set($locReadings = []) #foreach($reading in ${ctx.args.locReadings}) #set($pkey = {}) $util.qr($pkey.put("sensorId", $reading.sensorId)) $util.qr($pkey.put("timestamp", $reading.timestamp)) $util.qr($locReadings.add($util.dynamodb.toMapValues($pkey))) #end { "version" : "2018-05-29", "operation" : "BatchDeleteItem", "tables" : { "locationReadings": $utils.toJson($locReadings), "temperatureReadings": $utils.toJson($tempReadings) } }

O modelo de mapeamento da resposta é o mesmo usado para Mutation.recordReadings.

Modelo de mapeamento da resposta

## If there was an error with the invocation ## there might have been partial results #if($ctx.error) ## Append a GraphQL error for that field in the GraphQL response $utils.appendError($ctx.error.message, $ctx.error.message) #end ## Also return data for the field in the GraphQL response $utils.toJson($ctx.result.data)

Salve o resolvedor e navegue até a página Consultas do AWS AppSync console. Agora, vamos excluir algumas leituras do sensor!

Execute a seguinte mutação:

mutation deleteReadings { # Let's delete the first two readings we recorded deleteReadings( tempReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}] locReadings: [{sensorId: 1, timestamp: "2018-02-01T17:21:05.000+08:00"}]) { locationReadings { sensorId timestamp lat long } temperatureReadings { sensorId timestamp value } } }

Valide, por meio do console do DynamoDB, se essas duas leituras foram excluídas das tabelas e. locationReadingstemperatureReadings

BatchGetItem - Recuperar leituras

Outra operação comum para o nosso aplicativo de Saúde do animal de estimação seria recuperar as leituras de um sensor em um determinado momento. Vamos anexar um resolvedor ao campo do GraphQL Query.getReadings em nosso esquema. Selecione Anexar, e na próxima tela escolha a mesma fonte de dados BatchTutorial criada no início do tutorial.

Vamos adicionar o seguinte modelo de mapeamento da solicitação.

Modelo de mapeamento da solicitação

## Build a single DynamoDB primary key, ## as both locationReadings and tempReadings tables ## share the same primary key structure #set($pkey = {}) $util.qr($pkey.put("sensorId", $ctx.args.sensorId)) $util.qr($pkey.put("timestamp", $ctx.args.timestamp)) { "version" : "2018-05-29", "operation" : "BatchGetItem", "tables" : { "locationReadings": { "keys": [$util.dynamodb.toMapValuesJson($pkey)], "consistentRead": true }, "temperatureReadings": { "keys": [$util.dynamodb.toMapValuesJson($pkey)], "consistentRead": true } } }

Observe que agora estamos usando a BatchGetItemoperação.

Nosso modelo de mapeamento da resposta será um pouco diferente, pois escolhemos retornar uma lista SensorReading. Vamos mapear o resultado da invocação no formato desejado.

Modelo de mapeamento da resposta

## Merge locationReadings and temperatureReadings ## into a single list ## __typename needed as schema uses an interface #set($sensorReadings = []) #foreach($locReading in $ctx.result.data.locationReadings) $util.qr($locReading.put("__typename", "LocationReading")) $util.qr($sensorReadings.add($locReading)) #end #foreach($tempReading in $ctx.result.data.temperatureReadings) $util.qr($tempReading.put("__typename", "TemperatureReading")) $util.qr($sensorReadings.add($tempReading)) #end $util.toJson($sensorReadings)

Salve o resolvedor e navegue até a página Consultas do AWS AppSync console. Agora, vamos recuperar as leituras do sensor!

Execute a seguinte consulta:

query getReadingsForSensorAndTime { # Let's retrieve the very first two readings getReadings(sensorId: 1, timestamp: "2018-02-01T17:21:06.000+08:00") { sensorId timestamp ...on TemperatureReading { value } ...on LocationReading { lat long } } }

Demonstramos com sucesso o uso das operações em lote do DynamoDB usando. AWS AppSync

Como tratar erros

Em AWS AppSync, as operações da fonte de dados às vezes podem retornar resultados parciais. Resultados parciais será o termo usado para indicar quando a saída de uma operação for composta por alguns dados e um erro. Como o tratamento de erros é inerentemente específico do aplicativo, AWS AppSync você tem a oportunidade de lidar com erros no modelo de mapeamento de respostas. O erro de invocação do resolvedor, se presente, está disponível no contexto como $ctx.error. Os erros de invocação sempre incluem uma mensagem e um tipo, acessível como propriedades $ctx.error.message e $ctx.error.type. Durante a invocação do modelo de mapeamento da resposta, você pode lidar com resultados parciais de três maneiras:

  1. engolir o erro de invocação apenas retornando dados

  2. gerar um erro (usando $util.error(...)) ao interromper a avaliação do modelo de mapeamento da resposta, que não retornará quaisquer dados.

  3. anexar um erro (usando $util.appendError(...)) e também retornar dados

Vamos demonstrar cada um dos três pontos acima com operações em lote do DynamoDB!

Operações em lote do DynamoDB

Com as operações em lote do DynamoDB, é possível que um lote seja concluído parcialmente. Ou seja, é possível que alguns dos itens solicitados ou chaves não seja processados. Se não AWS AppSync for possível concluir um lote, os itens não processados e um erro de invocação serão definidos no contexto.

Vamos implementar a manipulação de erros usando a configuração de campo Query.getReadings da operação BatchGetItem da seção anterior desse tutorial. Dessa vez, vamos fingir que ao executar o campo Query.getReadings, a tabela do DynamoDB temperatureReadings esgotou sua throughput provisionada. O DynamoDB gerou ProvisionedThroughputExceededExceptionum na segunda tentativa AWS AppSync de processar os elementos restantes no lote.

O seguinte JSON representa o contexto serializado após a invocação em lote do DynamoDB, mas antes da avaliação do modelo de mapeamento de resposta.

{ "arguments": { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" }, "source": null, "result": { "data": { "temperatureReadings": [ null ], "locationReadings": [ { "lat": 47.615063, "long": -122.333551, "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ] }, "unprocessedKeys": { "temperatureReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ], "locationReadings": [] } }, "error": { "type": "DynamoDB:ProvisionedThroughputExceededException", "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)" }, "outErrors": [] }

Algumas observações sobre o contexto:

  • o erro de invocação foi definido no contexto em $ctx.error by AWS AppSync e o tipo de erro foi definido como DynamoDB:. ProvisionedThroughputExceededException

  • os resultados são mapeados por tabela em $ctx.result.data, mesmo que haja um erro presente

  • as chaves não processadas estão disponíveis em $ctx.result.data.unprocessedKeys. Aqui, não AWS AppSync foi possível recuperar o item com a chave (:1, timestamp:2018-02-01T sensorId 17:21:05.000 + 08:00) devido à taxa de transferência insuficiente da tabela.

Observação: em BatchPutItem, é $ctx.result.data.unprocessedItems. Em BatchDeleteItem, é $ctx.result.data.unprocessedKeys.

Vamos lidar com esse erro de três maneiras diferentes.

1. Absorção do erro de invocação

Retornar dados sem manipular o erro de invocação efetivamente absorve o erro, tornando o resultado para o determinado campo do GraphQL sempre bem-sucedido.

O modelo de mapeamento da resposta gravado é familiar e se concentra apenas nos dados do resultado.

Modelo de mapeamento da resposta:

$util.toJson($ctx.result.data)

Resposta do GraphQL:

{ "data": { "getReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00", "lat": 47.615063, "long": -122.333551 }, { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00", "value": 85.5 } ] } }

Nenhum erro será adicionado à resposta do erro uma vez que apenas dados foram modificados.

2. Geração de um erro para abortar a execução do modelo

Quando falhas parciais devem ser tratadas como falhas completas do ponto de vista do cliente, você pode abortar a execução do modelo para evitar o retorno de dados. O método utilitário $util.error(...) atinge exatamente esse comportamento.

Modelo de mapeamento da resposta:

## there was an error let's mark the entire field ## as failed and do not return any data back in the response #if ($ctx.error) $util.error($ctx.error.message, $ctx.error.type, null, $ctx.result.data.unprocessedKeys) #end $util.toJson($ctx.result.data)

Resposta do GraphQL:

{ "data": { "getReadings": null }, "errors": [ { "path": [ "getReadings" ], "data": null, "errorType": "DynamoDB:ProvisionedThroughputExceededException", "errorInfo": { "temperatureReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ], "locationReadings": [] }, "locations": [ { "line": 58, "column": 3 } ], "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)" } ] }

Embora alguns resultados possam ter sido retornados da operação em lote do DynamoDB, escolhemos gerar um erro tal que o campo do GraphQL getReadings seja nulo e o erro seja adicionado ao bloco erros da resposta do GraphQL.

3. Anexar um erro para retornar dados e erros

Em alguns casos, para oferecer uma experiência melhor ao usuário, os aplicativos podem retornar resultados parciais e notificar seus clientes sobre os itens não processados. Os clientes podem decidir implementar uma nova tentativa ou traduzir o erro de volta para o usuário final. O $util.appendError(...) é o método utilitário que permite esse comportamento, permitindo que o designer do aplicativo anexe erros no contexto sem interferir na avaliação do modelo. Depois de avaliar o modelo, AWS AppSync processará quaisquer erros de contexto anexando-os ao bloco de erros da resposta do GraphQL.

Modelo de mapeamento da resposta:

#if ($ctx.error) ## pass the unprocessed keys back to the caller via the `errorInfo` field $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.data.unprocessedKeys) #end $util.toJson($ctx.result.data)

Encaminhamos o erro de invocação e o unprocessedKeys elemento dentro do bloco de erros da resposta do GraphQL. O getReadings campo também retorna dados parciais da locationReadingstabela, como você pode ver na resposta abaixo.

Resposta do GraphQL:

{ "data": { "getReadings": [ null, { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00", "value": 85.5 } ] }, "errors": [ { "path": [ "getReadings" ], "data": null, "errorType": "DynamoDB:ProvisionedThroughputExceededException", "errorInfo": { "temperatureReadings": [ { "sensorId": "1", "timestamp": "2018-02-01T17:21:05.000+08:00" } ], "locationReadings": [] }, "locations": [ { "line": 58, "column": 3 } ], "message": "You exceeded your maximum allowed provisioned throughput for a table or for one or more global secondary indexes. (...)" } ] }