Tutorial: Risolver in batch per DynamoDB - AWS AppSync

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Tutorial: Risolver in batch per DynamoDB

Nota

Ora supportiamo principalmente il runtime APPSYNC_JS e la relativa documentazione. Prendi in considerazione l'utilizzo del runtime APPSYNC_JS e delle relative guide qui.

AWS AppSync supporta l'utilizzo di operazioni batch di Amazon DynamoDB su una o più tabelle in una singola regione. Le operazioni supportate sono BatchGetItem, BatchPutItem e BatchDeleteItem. Usando queste caratteristiche in AWS AppSync, è possibile eseguire attività quali ad esempio:

  • Passare un elenco di chiavi in una singola query e restituire i risultati da una tabella

  • Leggere i record da una o più tabelle in un'unica query

  • Scrivere record in blocco in una o più tabelle

  • Scrivere o eliminare in forma condizionata record in più tabelle che possono essere relazionate

L'utilizzo delle operazioni batch con DynamoDB AWS AppSync in è una tecnica avanzata che richiede un po' di riflessione e conoscenza in più delle operazioni di backend e delle strutture delle tabelle. Inoltre, le operazioni di batch in AWS AppSync hanno due differenze chiave rispetto alle operazioni non in batch:

  • Il ruolo dell'origine dati deve disporre delle autorizzazioni per tutte le tabelle a cui il resolver effettua l'accesso.

  • La specifica della tabella per un resolver fa parte del modello di mappatura.

Autorizzazioni

Come altri resolver, è necessario creare un'origine dati in AWS AppSync e creare un ruolo oppure utilizzarne uno esistente. Poiché le operazioni batch richiedono autorizzazioni diverse sulle tabelle DynamoDB, è necessario concedere ai ruoli configurati le autorizzazioni per le azioni di lettura o scrittura:

{ "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/*" ] } ] }

Nota: i ruoli sono legati alle origini dati in AWS AppSync e i resolver sui campi sono richiamati in un'origine dati. Le fonti di dati configurate per il recupero con DynamoDB hanno solo una tabella specificata, per semplificare la configurazione. Pertanto, quando si esegue un'operazione di batch su più tabelle in un singolo resolver, che è una delle attività più avanzate, è necessario concedere il ruolo sull'accesso all'origine dati a tutte le tabelle con cui interagirà il resolver. Questo potrebbe essere fatto nel campo Risorsa nella policy di IAM indicata in precedenza. Viene effettuata la configurazione delle tabelle per effettuare chiamate in batch nel modello di resolver, che verrà descritto di seguito.

Origine dati

Per semplicità, useremo la stessa origine dati per tutti i resolver usati in questo tutorial. Nella scheda Sorgenti dati, crea una nuova origine dati DynamoDB e assegnale un nome. BatchTutorial Per la tabella è possibile specificare un qualsiasi nome, perché i nomi delle tabelle sono specificati come parte del modello di mappatura delle richieste per le operazioni in batch. La tabella si chiamerà empty.

Per questo tutorial, funzionerà qualsiasi ruolo con le seguenti policy inline:

{ "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/*" ] } ] }

Batch a tabella singola

Per questo esempio, si supponga di disporre di una tabella singola denominata Post a cui si desidera aggiungere o rimuovere voci con operazioni in batch. Usare i seguenti schemi, tenendo presente che per la query si trasmetterà un elenco di ID:

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 }

Allegare un resolver al campo batchAdd() con il seguente Modello di mappatura della richiesta. Questo prende automaticamente ogni voce nel tipo input PostInputdi GraphQL e crea una mappa, che è necessaria per l'operazione 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) } }

In questo caso, il Modello di mappatura della risposta è un semplice passaggio, ma notare che il nome della tabella viene aggiunto come ..data.Posts all'oggetto del contesto come segue:

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

Ora accedere alla pagina Query della console di AWS AppSync ed eseguire la seguente mutazione batchAdd:

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

Dovresti vedere i risultati stampati sullo schermo e puoi convalidare in modo indipendente tramite la console DynamoDB che entrambi i valori sono stati scritti nella tabella Posts.

Successivamente, allegare un resolver al campo batchGet() con il seguente Modello di mappatura della richiesta. Questo prende automaticamente ogni voce nel tipo ids:[] di GraphQL e crea una mappa, che risulta necessaria per l'operazione 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"} } } } }

Il Modello di mappatura della risposta è ancora un semplice passaggio, con di nuovo il nome della tabella che viene aggiunto come ..data.Posts all'oggetto del contesto:

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

Ora tornare alla pagina Query della console di AWS AppSync ed eseguire la seguente Query di batchAdd:

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

Questo dovrebbe restituire i risultati per i due valori id aggiunti in precedenza. Si noti che un valore null è stato restituito per id con un valore di 3. Questo perché non era presente nessun record nella tabella Post che avesse ancora tale valore. Inoltre, si noti che AWS AppSync restituisce i risultati nello stesso ordine delle chiavi passate alla query, il che è una caratteristica aggiuntiva eseguita da AWS AppSync a nome del cliente. Pertanto, se si passa a batchGet(ids:[1,3,2), si visualizzerà l'ordine modificato. È inoltre possibile sapere quale id ha restituito un valore null.

Infine, allegare un resolver al campo batchDelete() con il seguente Modello di mappatura della richiesta. Questo prende automaticamente ogni voce nel tipo ids:[] di GraphQL e crea una mappa, che risulta necessaria per l'operazione 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) } }

Il Modello di mappatura della risposta è ancora un semplice passaggio, con di nuovo il nome della tabella che viene aggiunto come ..data.Posts all'oggetto del contesto:

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

Ora tornare alla pagina Query della console di AWS AppSync ed eseguire la seguente mutazione batchDelete:

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

I record con id 1 e 2 dovrebbero essere eliminati. Se si esegue nuovamente la query batchGet() da una versione precedente, questi devono restituire null.

Batch a tabella multipla

AWS AppSync consente inoltre di eseguire operazioni in batch su più tabelle. L'applicazione seguente è più complessa da costruire. Si immagini di creare un'app per la salute degli animali, in cui i sensori segnalano la posizione dell'animale domestico e la temperatura corporea. I sensori sono dotati di batteria e tentano di connettersi alla rete a distanza di pochi minuti. Quando un sensore stabilisce una connessione, invia le letture all'API di AWS AppSync . I trigger quindi analizzano i dati in modo da presentare un pannello di controllo al proprietario dell'animale domestico, focalizzando l'attenzione sulla rappresentazione delle interazioni tra il sensore e l'archivio di dati di back-end.

Come prerequisito, creiamo prima due tabelle DynamoDB; LocationReadings memorizzerà le letture della posizione del sensore e TemperatureReadings memorizzerà le letture della temperatura del sensore. Entrambe le tabelle condividono la stessa struttura della chiave primaria: la chiave di partizione sensorId (String) e la chiave di ordinamento timestamp (String).

Utilizzare il seguente schema di 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 - Registrazione delle letture del sensore

I sensori devono essere in grado di inviare le loro letture una volta stabilita la connessione a Internet. Il campo Mutation.recordReadings di GraphQL è l'API che si userà per farlo. Allegare un resolver per portare alla vita l'API.

Selezionare Attach (Allega) vicino al campo Mutation.recordReadings. Sulla schermata successiva, scegliere la stessa origine dati BatchTutorial creata all'inizio di questo tutorial.

Aggiungere il seguente modello di mappatura della richiesta.

Modello di mappatura della richiesta

## 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) } }

Come si può vedere, l'operazione BatchPutItem consente di specificare più tabelle.

Usare il seguente modello di mappatura della risposta.

Modello di mappatura della risposta

## 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)

Con le operazioni in batch, possono essere presenti entrambi gli errori e i risultati restituiti dalla chiamata. In questo caso, è possibile eseguire liberamente ulteriori operazioni di gestione degli errori.

Nota: l'uso di $utils.appendError() è analogo a quello di $util.error(), con la differenza principale che non interrompe la valutazione del modello di mappatura. Al contrario, segnala che si è verificato un errore con il campo, ma consente al modello di essere valutato e, di conseguenza, di restituire i dati al chiamante. Si consiglia di usare $utils.appendError() quando un'applicazione deve restituire risultati parziali.

Salvare il resolver e passare alla pagina Query della console di AWS AppSync . Inviare alcune letture del sensore.

Eseguire la mutazione seguente:

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 } } }

Sono state inviate 10 letture del sensore in una sola mutazione, con letture suddivise in due tabelle. Utilizza la console DynamoDB per verificare che i dati vengano visualizzati nelle tabelle LocationReadings e Temperaturereadings.

BatchDeleteItem - Eliminazione delle letture del sensore

Analogamente, sarebbe necessario anche eliminare i batch delle letture del sensore. Utilizzare il campo Mutation.deleteReadings di GraphQL per questo scopo. Selezionare Attach (Allega) vicino al campo Mutation.recordReadings. Sulla schermata successiva, scegliere la stessa origine dati BatchTutorial creata all'inizio di questo tutorial.

Utilizzare il seguente modello di mappatura della richiesta.

Modello di mappatura della richiesta

## 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) } }

Il modello di mappatura della risposta è lo stesso utilizzato per Mutation.recordReadings.

Modello di mappatura della risposta

## 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)

Salvare il resolver e passare alla pagina Query della console di AWS AppSync . Ora, eliminare un paio di letture del sensore.

Eseguire la mutazione seguente:

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 } } }

Verifica tramite la console DynamoDB che queste due letture siano state eliminate dalle tabelle LocationReadings e TemperatureReadings.

BatchGetItem - Recupera le letture

Un'altra operazione comune per l'app Pet Health sarebbe quella di recuperare le letture per un sensore in un determinato momento. Allegare un resolver al campo Query.getReadings di GraphQL sullo schema. Selezionare Attach (Allega) e, sulla schermata successiva, scegliere la stessa origine dati BatchTutorial creata all'inizio del tutorial.

Aggiungere il seguente modello di mappatura della richiesta.

Modello di mappatura della richiesta

## 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 } } }

Nota che ora stiamo usando l'BatchGetItemoperazione.

Il modello di mappatura della risposta sarà leggermente diverso perché è stato scelto di restituire un elenco SensorReading. Mappare il risultato della chiamata nella forma desiderata.

Modello di mappatura della risposta

## 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)

Salvare il resolver e passare alla pagina Query della console di AWS AppSync . Ora, recuperare le letture del sensore.

Eseguire la query seguente:

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 } } }

Abbiamo dimostrato con successo l'uso delle operazioni batch di DynamoDB utilizzando. AWS AppSync

Gestione errori

In AWS AppSync, le operazioni di origine dati a volte possono restituire risultati parziali. Risultati parziali è il termine che si userà per indicare quando l'output di un'operazione comprende alcuni dati e un errore. Poiché la gestione degli errori è intrinsecamente specifica dell'applicazione, AWS AppSync offre la possibilità di gestire gli errori nel modello di mappatura della risposta. L'errore di chiamata del resolver, se presente, è disponibile nel contesto come $ctx.error. Gli errori di chiamata comprendono sempre un messaggio e un tipo, accessibili come proprietà $ctx.error.message e $ctx.error.type. Durante la chiamata del modello di mappatura della risposta, è possibile gestire i risultati parziali in tre modi:

  1. assumere l'errore di chiamata semplicemente restituendo i dati

  2. generare un errore (usando $util.error(...)) arrestando la valutazione del modello di mappatura della risposta, che non restituisce nessun dato.

  3. accodare un errore (usando $util.appendError(...)) e restituire anche i dati

Ora è opportuno dimostrare ciascuno dei tre punti sopra indicati con le operazioni in batch di DynamoDB.

Operazioni di batch di DynamoDB

Con le operazioni di batch di DynamoDB, è possibile che un batch sia completato parzialmente. Ovvero, è possibile che alcune delle chiavi o voci richieste non vengano elaborate. Se AWS AppSync non è in grado di completare un batch, le voci non elaborate e un errore di chiamata verranno impostati nel contesto.

La gestione degli errori verrà realizzata tramite la configurazione del campo Query.getReadings dall'operazione BatchGetItem dalla sezione precedente di questo tutorial. In questo momento, è opportuno supporre che durante l'esecuzione del campo Query.getReadings, la tabella temperatureReadings DynamoDB esegua un throughput assegnato. DynamoDB ha generato ProvisionedThroughputExceededExceptionun al secondo tentativo AWS AppSync per elaborare gli elementi rimanenti del batch.

Il seguente JSON rappresenta il contesto serializzato dopo la chiamata del batch di DynamoDB prima che il modello di mappatura della risposta venisse valutato.

{ "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": [] }

Alcune cose da tenere presente in questo contesto:

  • l'errore di invocazione è stato impostato nel contesto in $ctx.error by AWS AppSync e il tipo di errore è stato impostato su DynamoDB:. ProvisionedThroughputExceededException

  • i risultati sono mappati per tabella in $ctx.result.data, anche se è presente un errore

  • le chiavi che non sono state elaborate sono disponibili in $ctx.result.data.unprocessedKeys. Qui, AWS AppSync non è stato in grado di recuperare l'elemento con chiave (sensorId:1, timestamp:2018-02-01T17:21:05.000+08:00) a causa del throughput insufficiente della tabella.

Nota: per BatchPutItem, è $ctx.result.data.unprocessedItems. Per BatchDeleteItem, è $ctx.result.data.unprocessedKeys.

È possibile gestire l'errore in tre modi diversi.

1. Assumere l'errore di chiamata

Restituire i dati senza gestire l'errore di chiamata assume efficacemente l'errore. In questo modo, il risultato per il campo di GraphQL è sempre positivo.

Il modello di mappatura della risposta che viene scritto è familiare e si focalizza solo sui dati del risultato.

Modello di mappatura della risposta:

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

Risposta di 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 } ] } }

Non verrà aggiunto nessun errore alla risposta di errore poiché sono stati eseguiti solo i dati.

2. Generazione di un errore per interrompere l'esecuzione del modello

Quando i guasti parziali devono essere trattati come guasti totali dalla prospettiva del client, è possibile interrompere l'esecuzione del modello per evitare di restituire i dati. Il metodo di utilità $util.error(...) raggiunge esattamente questo comportamento.

Modello di mappatura della risposta:

## 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)

Risposta di 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. (...)" } ] }

Sebbene alcuni risultati possano essere stati restituiti dall'operazione in batch di DynamoDB, si è scelto di generare un errore in modo tale che il campo getReadings di GraphQL sia nullo e l'errore venga aggiunto al blocco di errori della risposta GraphQL.

3. Aggiunta di un errore per restituire sia i dati sia gli errori

In alcuni casi, per fornire una migliore esperienza utente, le applicazioni possono restituire risultati parziali e notificare ai client le voci non elaborate. I client possono decidere di implementare un nuovo tentativo oppure di rimandare l'errore all'utente finale. Il $util.appendError(...) è il metodo di utilità che consente questo comportamento, permettendo al designer dell'applicazione di accodare gli errori nel contesto senza interferire con la valutazione del modello. Dopo aver valutato il modello, AWS AppSync elaborerà eventuali errori di contesto accodandoli al blocco di errori della risposta di GraphQL.

Modello di mappatura della risposta:

#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)

Sono stati inoltrati sia l'errore di chiamata sia l'elemento unprocessedKeys all'interno del blocco di errori della risposta di GraphQL. Anche il campo getReadings restituisce dati parziali dalla tabella locationReadings come è possibile vedere nella risposta di seguito.

Risposta di 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. (...)" } ] }