Aggiornamento collettivo: restituisce tutti i risultati o solo i fallimenti

7

Sto sviluppando un'API che esegue l'aggiornamento collettivo di un numero elevato di elementi in una singola chiamata. Questo codice consisterà in un endpoint REST e nel codice della libreria interna che chiama.

Ci sono alcuni motivi per cui l'aggiornamento di un articolo specifico può fallire (ad esempio, l'elemento è stato cancellato). La domanda che sto discutendo è come restituire il risultato al chiamante.

Sono propenso a restituire una raccolta che contiene solo gli elementi con errori, ma ho potuto vedere scenari in cui sarebbe stato utile restituire il risultato per tutti loro.

In entrambi i casi, la risposta conterrebbe una collezione di oggetti come questa:

class UpdateResponse
{
    int ItemId;
    ResultType Result;
}

Dove ResultType è un'enumerazione che descrive il risultato dell'aggiornamento.

Esistono validi motivi per scegliere una strategia rispetto all'altra (restituire tutti gli errori di restituzione e tutti)?

    
posta Jack A. 03.02.2016 - 13:43
fonte

5 risposte

4

Hai due opzioni. Puoi utilizzare 200 OK o 207 Multi-Status .

Non consiglierei di usare quest'ultimo, poiché è un codice di stato di WebDav (WebDav è un'estensione di HTTP) che ti obbliga a rispondere con un documento XML. Sebbene ti consenta di utilizzare più codici di stato nella tua risposta.

La mia preferenza andrebbe al 200 OK perché significa in sostanza: "sì la tua richiesta è stata completata". Questo è il tuo caso.

La seconda domanda è una scelta tra: "la tua richiesta è stata completata: ecco un riassunto" o "la tua richiesta è stata completata: ecco cosa va storto". La vera domanda è: il cliente ha bisogno di sapere che un oggetto è stato aggiornato con successo?

  • Sì: fornire tutti i risultati.
  • No: fornire solo errori. Eviterà a un cliente di analizzare l'intera risposta con informazioni inutilmente.
risposta data 04.02.2016 - 10:40
fonte
1

There are a few reasons why the update of a specific item may fail (e.g., the item has been deleted). The question I'm debating is how to return the result to the caller.

Touchstone: come lo faresti come pagina web?

Presumibilmente, l'utente inizierà a guardare una pagina web, con un modulo su di essa che le consentirebbe di descrivere l'attività - i lavori nel batch. Il pulsante di invio POSTerebbe il modulo alla risorsa identificata da form.action. La risposta sarebbe un'altra pagina html.

Espressa in termini REST, lo stato iniziale dell'applicazione verrebbe descritto da un documento ipermediale (la pagina html) con controlli ipermediali (collegamenti / moduli). L'applicazione rappresenterebbe i controlli basati sulla sua interpretazione del tipo di media (parametri del modulo). L'utente dovrebbe configurare e scegliere il controllo da attivare, che invierà un messaggio a una risorsa sul server, che risponderebbe con un altro documento ipermediale che descrive lo stato dell'applicazione successivo.

Questo è il livello 3 RMM, comunque. Fino a te quanto vuoi spingere verso questo obiettivo, ma trovo che è più facile lavorare all'indietro da "giusto" a "pratico".

I'm leaning towards returning a collection that contains only the items with failures, but I could see scenarios where it would be helpful to return the result for all of them.

Ancora, come gestiresti questo con le pagine web? Probabilmente rimanderai l'html che è più utile per il caso comune e includi un link ad altre risorse che descrivono il risultato con granularità diversa. Questo ti porterà nella versione 1, ma alla fine scoprirai che alcuni utenti preferiscono sempre la rappresentazione secondaria. Quindi imposterai una nuova risorsa che accetta il batch di lavoro e restituirà la rappresentazione secondaria (probabilmente con un collegamento al primo). La tua pagina web iniziale avrebbe due collegamenti su di essa, ognuno dei quali posterebbe lo stesso lavoro in batch su una risorsa diversa, in modo che l'utente possa esprimere la propria preferenza per una rappresentazione subito, eliminando il clic in più.

Puoi usare lo stesso trucco con altre rappresentazioni. A RMM-3, i tuoi documenti avrebbero controlli ipermediali per connettere l'applicazione ad altre rappresentazioni dei risultati, ma con RMM-2 puoi ottenere due risorse diverse che accettano lo stesso batch di lavoro e producono rapporti diversi.

Il punto chiave qui è che è un problema facile da affrontare in seguito, basta aggiungere un'altra risorsa che fa lo stesso lavoro.

Supponendo che si stia utilizzando HTTP per trasferire i documenti avanti e indietro, è probabile che il codice di stato corretto sia 201 (Creato). Non stai descrivendo il risultato del lavoro nel back-end, stai descrivendo ciò che sta accadendo alle risorse. Qui, presumibilmente stai prendendo la domanda che ha presentato il lavoro a "qualche rappresentazione dei risultati". A meno che non si abbia il viaggio nel tempo, il rapporto dei risultati probabilmente non esisteva prima che la richiesta arrivasse sul tuo server, quindi è naturale che tu stia creando una nuova risorsa (il documento che descrive i risultati).

Non è, per quanto posso vedere, particolarmente critico per farlo bene; restituire un 200 (OK) invece probabilmente va bene. Vi chiamo la vostra attenzione, perché trovo che pensare al documento aiuti a superare il blocco mentale di confondere la "risorsa" con la "cosa che sta effettivamente facendo il lavoro".

Vedi: REST in pratica di Jim Webber.

    
risposta data 05.02.2016 - 05:22
fonte
0

Probabilmente avrai difficoltà a soddisfare questo tipo di richiesta in un approccio REST, poiché è fondamentalmente finalizzato all'accesso a una singola risorsa.

Detto questo, per la risposta vorrei semplicemente restituire 200 OK se alcuni errori non significano fallimento globale e 409 Conflict se lo fa. Puoi inserire tutto ciò che desideri nel corpo di queste risposte, quindi è meglio essere esaurienti e menzionare i successi e gli errori.

    
risposta data 03.02.2016 - 17:14
fonte
0

Direi che dovresti restituire un identificatore batch di qualche tipo e fornire un altro endpoint che l'utente può chiamare per ottenere le informazioni che vogliono sul batch. Ciò sarebbe particolarmente utile se il batch contiene un numero elevato di elementi che richiedono un po 'di tempo per essere elaborati, in quanto consentirebbe di restituire immediatamente una risposta di 202 Accepted con l'ID di lotto (quindi la richiesta non scade), quindi restituire i dati in una chiamata successiva. Quindi si dovrebbe accettare un POST a /api/batch per inviare il batch, restituire un 202 con un ID batch, quindi fornire anche la possibilità per l'utente di inviare un GET a /api/batch/:id/failures per ottenere i record non riusciti o /api/batch/:id/processed per ottenere tutti quelli di successo, ecc.

    
risposta data 03.02.2016 - 17:27
fonte
0

So come lo farei in un servizio WCF.

class UpdateResponse
{
    int ItemId;
    ResultType Result;
}

Class Result
{
   Status   //"success"     = ALL items were successfully updated
            //"fail"    = At least 1 item in list failed

           //If status = "sucess" then ItemResponse will be empty
           //If status = "fail", this will contain an entry for EVERY 
           //item that was in the original request 
   List<UpdateResponse> ItemUpdateResponse          
}

Il ragionamento per avere ogni elemento nell'elenco restituito in caso di errore è così che se l'utente della tua API vuole mettere in relazione il loro elenco originale con l'elenco restituito, possono farlo utilizzando la posizione ordinale.

    
risposta data 05.02.2016 - 13:06
fonte

Leggi altre domande sui tag