Registro de alterações do modelo de mapeamento do resolvedor do AWS AppSync
nota
Agora, oferecemos suporte principalmente ao runtime do APPSYNC_JS e sua documentação. Considere usar o runtime do APPSYNC_JS e seus guias disponíveis aqui.
Os resolvedores e modelos de mapeamento de função são versionados. A versão do modelo de mapeamento, como 2018-05-29
, determina o seguinte:
-
A forma esperada da configuração de solicitação de fonte de dados fornecida pelo modelo de solicitação
-
O comportamento de execução do modelo de mapeamento de solicitação e o modelo de mapeamento de resposta
Versões são representadas usando o formato YYYY-MM-DD, uma data posterior corresponde a uma versão mais recente. Esta página lista as diferenças entre as versões do modelo de mapeamento atualmente compatíveis com o AWS AppSync.
Tópicos
Disponibilidade de operação da fonte de dados por matriz de versão
Operação/versão compatível | 2017-02-28 | 2018-05-29 |
---|---|---|
AWS Lambda Invocar |
Sim |
Sim |
BatchInvoke AWS Lambda |
Sim |
Sim |
Fonte de dados "none (nenhum)" |
Sim |
Sim |
Amazon OpenSearch GET |
Sim |
Sim |
Amazon OpenSearch POST |
Sim |
Sim |
Amazon OpenSearch PUT |
Sim |
Sim |
Amazon OpenSearch DELETE |
Sim |
Sim |
Amazon OpenSearch GET |
Sim |
Sim |
GetItem do DynamoDB |
Sim |
Sim |
Scan do DynamoDB |
Sim |
Sim |
Query do DynamoDB |
Sim |
Sim |
DeleteItem do DynamoDB |
Sim |
Sim |
PutItem do DynamoDB |
Sim |
Sim |
BatchGetItem do DynamoDB |
Não |
Sim |
BatchPutItem do DynamoDB |
Não |
Sim |
BatchDeleteItem do DynamoDB |
Não |
Sim |
HTTP |
Não |
Sim |
Amazon RDS |
Não |
Sim |
Observação: somente a versão 2018-05-29 é compatível com as funções no momento.
Alterar a versão em um modelo de mapeamento do resolvedor de unidade
Para resolvedores de unidade, a versão é especificada como parte do corpo do modelo de mapeamento de solicitação. Para atualizar a versão, basta atualizar o campo version
para a nova versão.
Por exemplo, para atualizar a versão no modelo do AWS Lambda:
{ "version": "2017-02-28", "operation": "Invoke", "payload": { "field": "getPost", "arguments": $utils.toJson($context.arguments) } }
Você precisa atualizar o campo de versão de 2017-02-28
para 2018-05-29
da seguinte maneira:
{ "version": "2018-05-29", ## Note the version "operation": "Invoke", "payload": { "field": "getPost", "arguments": $utils.toJson($context.arguments) } }
Alterar a versão em uma função
Para funções, a versão é especificada como o campo functionVersion
no objeto de função. Para atualizar a versão, basta atualizar functionVersion
. Observação: no momento, somente a versão 2018-05-29
é compatível com a função.
Veja a seguir um exemplo de um comando da CLI para atualizar uma versão de função existente:
aws appsync update-function \ --api-id REPLACE_WITH_API_ID \ --function-id REPLACE_WITH_FUNCTION_ID \ --data-source-name "PostTable" \ --function-version "2018-05-29" \ --request-mapping-template "{...}" \ --response-mapping-template "\$util.toJson(\$ctx.result)"
Observação: é recomendável omitir o campo de versão do modelo de mapeamento de solicitação de função, pois ele não terá efeito. Se você especificar uma versão dentro de um modelo de mapeamento de solicitação de função, o valor da versão será substituído pelo valor do campo functionVersion
.
2018-05-29
Alteração de comportamento
-
Se o resultado da invocação da fonte de dados for
null
, o modelo de mapeamento de resposta será executado. -
Se a invocação da fonte de dados gerar um erro, agora caberá a você lidar com o erro, o resultado avaliado do modelo de mapeamento de resposta será sempre colocado dentro do bloco
data
de resposta do GraphQL.
Reasoning
-
Um resultado de invocação
null
tem significado e, em alguns casos de uso do aplicativo, podemos manipular os resultadosnull
de maneira personalizada. Por exemplo, um aplicativo pode verificar se existe um registro em uma tabela do Amazon DynamoDB para executar alguma verificação de autorização. Nesse caso, um resultado de invocaçãonull
significa que o usuário pode não ser autorizado. Agora, a execução do modelo de mapeamento de resposta fornece a capacidade de gerar um erro não autorizado. Esse comportamento fornece maior controle para o designer da API.
Considerando o seguinte modelo de mapeamento de resposta:
$util.toJson($ctx.result)
Antes, com a versão 2017-02-28
, se $ctx.result
retornasse nulo, o modelo de mapeamento de resposta não seria executado. Agora, com a versão 2018-05-29
, podemos lidar com esse cenário. Por exemplo, podemos optar por gerar um erro de autorização da seguinte forma:
# throw an unauthorized error if the result is null #if ( $util.isNull($ctx.result) ) $util.unauthorized() #end $util.toJson($ctx.result)
Observação: os erros que retornam de uma fonte de dados às vezes não são fatais nem esperados, é por isso que o modelo de mapeamento de resposta deve ter a flexibilidade de tratar o erro de invocação e decidir se deve ignorá-lo, criá-lo novamente ou gerar um erro diferente.
Considerando o seguinte modelo de mapeamento de resposta:
$util.toJson($ctx.result)
Antes, com a versão 2017-02-28
, no caso de um erro de invocação, o modelo de mapeamento de resposta era avaliado e o resultado era colocado automaticamente no bloco errors
da resposta do GraphQL. Agora, com a versão 2018-05-29
, você pode escolher o que fazer com o erro, criá-lo novamente, gerar um erro diferente ou anexar o erro ao retornar os dados.
Criar novamente um erro de invocação
No modelo de resposta a seguir, criamos o mesmo erro que retornou da fonte de dados.
#if ( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #end $util.toJson($ctx.result)
No caso de um erro de invocação, por exemplo, $ctx.error
estar presente, a resposta será semelhante à seguinte:
{ "data": { "getPost": null }, "errors": [ { "path": [ "getPost" ], "errorType": "DynamoDB:ConditionalCheckFailedException", "message": "Conditional check failed exception...", "locations": [ { "line": 5, "column": 5 } ] } ] }
Criar um erro diferente
No modelo de resposta a seguir, criamos nosso próprio erro personalizado depois de processar o erro que retornou da fonte de dados.
#if ( $ctx.error ) #if ( $ctx.error.type.equals("ConditionalCheckFailedException") ) ## we choose here to change the type and message of the error for ConditionalCheckFailedExceptions $util.error("Error while updating the post, try again. Error: $ctx.error.message", "UpdateError") #else $util.error($ctx.error.message, $ctx.error.type) #end #end $util.toJson($ctx.result)
No caso de um erro de invocação, por exemplo, $ctx.error
estar presente, a resposta será semelhante à seguinte:
{ "data": { "getPost": null }, "errors": [ { "path": [ "getPost" ], "errorType": "UpdateError", "message": "Error while updating the post, try again. Error: Conditional check failed exception...", "locations": [ { "line": 5, "column": 5 } ] } ] }
Anexar um erro para retornar dados
No modelo de resposta a seguir, acrescentamos o mesmo erro que retornou da fonte de dados ao retornar os dados de volta à resposta. Isso também é conhecido como uma resposta parcial.
#if ( $ctx.error ) $util.appendError($ctx.error.message, $ctx.error.type) #set($defaultPost = {id: "1", title: 'default post'}) $util.toJson($defaultPost) #else $util.toJson($ctx.result) #end
No caso de um erro de invocação, por exemplo, $ctx.error
estar presente, a resposta será semelhante à seguinte:
{ "data": { "getPost": { "id": "1", "title: "A post" } }, "errors": [ { "path": [ "getPost" ], "errorType": "ConditionalCheckFailedException", "message": "Conditional check failed exception...", "locations": [ { "line": 5, "column": 5 } ] } ] }
Migração da versão 2017-02-28 para a 2018-05-29
A migração da versão 2017-02-28 para a 2018-05-29 é simples. Altere o campo de versão no modelo de mapeamento de solicitação do resolvedor ou no objeto de versão da função. No entanto, observe que a execução da 2018-05-29 se comporta de maneira diferente da 2017-02-28, as alterações estão descritas aqui.
Como preservar o mesmo comportamento de execução da versão 2017-02-28 na 2018-05-29
Em alguns casos, é possível reter o mesmo comportamento de execução da versão 2017-02-28 durante a execução de um modelo com versão 2018-05-29.
Exemplo: PutItem do DynamoDB
Considerando o seguinte modelo de solicitação PutItem do DynamoDB 2017-02-28:
{ "version" : "2017-02-28", "operation" : "PutItem", "key": { "foo" : ... typed value, "bar" : ... typed value }, "attributeValues" : { "baz" : ... typed value }, "condition" : { ... } }
E o seguinte modelo de resposta:
$util.toJson($ctx.result)
A migração para 2018-05-29 altera esses modelos da seguinte maneira:
{ "version" : "2018-05-29", ## Note the new 2018-05-29 version "operation" : "PutItem", "key": { "foo" : ... typed value, "bar" : ... typed value }, "attributeValues" : { "baz" : ... typed value }, "condition" : { ... } }
E altera o modelo de resposta da seguinte forma:
## If there is a datasource invocation error, we choose to raise the same error ## the field data will be set to null. #if($ctx.error) $util.error($ctx.error.message, $ctx.error.type, $ctx.result) #end ## If the data source invocation is null, we return null. #if($util.isNull($ctx.result)) #return #end $util.toJson($ctx.result)
Agora que é sua responsabilidade lidar com os erros, optamos por criar o mesmo erro usando o $util.error()
que foi retornado do DynamoDB. Você pode adaptar esse snippet para converter seu modelo de mapeamento para 2018-05-29. Observe que, se seu modelo de resposta for diferente, será necessário considerar as alterações de comportamento da execução.
Exemplo: GetItem do DynamoDB
Considerando o seguinte modelo de solicitação GetItem do DynamoDB 2017-02-28:
{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "foo" : ... typed value, "bar" : ... typed value }, "consistentRead" : true }
E o seguinte modelo de resposta:
## map table attribute postId to field Post.id $util.qr($ctx.result.put("id", $ctx.result.get("postId"))) $util.toJson($ctx.result)
A migração para 2018-05-29 altera esses modelos da seguinte maneira:
{ "version" : "2018-05-29", ## Note the new 2018-05-29 version "operation" : "GetItem", "key" : { "foo" : ... typed value, "bar" : ... typed value }, "consistentRead" : true }
E altera o modelo de resposta da seguinte forma:
## If there is a datasource invocation error, we choose to raise the same error #if($ctx.error) $util.error($ctx.error.message, $ctx.error.type) #end ## If the data source invocation is null, we return null. #if($util.isNull($ctx.result)) #return #end ## map table attribute postId to field Post.id $util.qr($ctx.result.put("id", $ctx.result.get("postId"))) $util.toJson($ctx.result)
Na versão 2017-02-28, se a invocação da fonte de dados fosse null
, significando que não há nenhum item na tabela do DynamoDB que corresponda à chave, o modelo de mapeamento de resposta não seria executado. Pode ser aceitável para a maioria dos casos, mas se você esperava que o $ctx.result
não fosse null
, agora precisará lidar com esse cenário.
2017-02-28
Características
-
Se o resultado da invocação da fonte de dados for
null
, o modelo de mapeamento de resposta não será executado. -
Se a invocação da fonte de dados gerar um erro, o modelo de mapeamento de resposta será executado e o resultado avaliado será colocado dentro do bloco
errors.data
de resposta do GraphQL.