Correggere il modo RESTfull per aggiornare una risorsa

4

Immagina di avere risorse come reports . Abbiamo una collezione perché ogni rapporto contiene le proprie impostazioni per creare alcuni dati.

Ogni rapporto calcola i suoi valori su base regolare ma non troppo spesso. C'è la possibilità di ricalcolare un rapporto proprio adesso per avere i dati più reali.

La domanda è: quale tipo di richiesta sarebbe il modo più efficace per farlo?

Alcuni dettagli dopo aver ottenuto le prime risposte:

Questo "ricalcolo" richiede relativamente tempo. Quindi questa non può essere una richiesta GET perché non può essere completata più o meno in modo sincrono. E lo scopo del client API non è quello di ottenere un risultato, ma avviare questo processo di aggiornamento.

Un altro esempio. Immagina di avere un database di persone e una collezione relativamente ampia di filtri, ognuno dei quali calcola i dati demografici sulla base di alcuni criteri. Le condizioni sono:

  • È molto costoso ricalcolare questi filtri
  • Solo alcuni filtri dovrebbero fornire regolarmente calcoli aggiornati e solo i client sanno quali sono
  • Il client guida enormi cambiamenti alla tabella delle persone, quindi solo il client sa quando accade e quando ha più senso eseguire un nuovo calcolo
posta Stepan Stepanov 17.05.2016 - 16:35
fonte

3 risposte

1

The question is: what kind of request would be a most RESTfull way to do that

Quindi hai una risorsa di rapporto su qualche URI, diciamo mysite.com/reports/343

Questa risorsa può essere in alcuni stati diversi, può essere aggiornata, può essere rigenerata o può essere rigenerata

Una rappresentazione di tale risorsa potrebbe essere qualcosa di simile a questo

application / vnd.stepanov_report_long-V1 + json

{
  report_state: "not generating",
  report_data: [
     "John Doe": {age: 34},
     "Jane Doe": {age: 35},
     ...
     ...
     "Xan Doe": {age: 32}
 ]
}

potresti anche avere un'altra rappresentazione come questa

application / vnd.stepanov_report_short-V1 + json

{
  report_state: "not generating",
}

La maggior parte delle volte i clienti sono interessati ai dati completi in quel report, che è una rappresentazione dello stato corrente di quel report.

Ma alcune volte i clienti sono interessati a una rappresentazione che dice al cliente se il report è aggiornato o meno, o se viene rigenerato. In questo caso, il client può richiedere la risorsa (nella versione abbreviata utilizzando l'intestazione Accept ). Può quindi aggiornare quella risorsa e inviare al server la nuova versione

Richiesta

GET mysite.com/reports/343
Accept: application/vnd.stepanov_report_short-v1+json

Risposta dal server

{
    report_state: "not generating",
}

Richiesta di nuovo al server

PUT mysite.com/reports/343
Content-Type: application/vnd.stepanov_report_short-v1+json
{
    report_state: "generating"
}

(notare lo stato del report è stato modificato dal client)

Il server vede che il client ha inserito la risorsa nello stato di rigenerazione e un effetto collaterale di ciò è che il server rigenera i dati effettivi.

Questo riduce la necessità di uno schema URI che contenga una logica specifica del dominio. In generale, è meglio mantenere il tuo schema URI limitato alle risorse e inserire la logica specifica del dominio nel tuo formato di rappresentazione (cioè il tuo tipo di contenuto).

    
risposta data 18.05.2016 - 13:53
fonte
9

Chiama GET /reports/{id} con una If-None-Match o If-Unmodified-Since set di intestazione. Il server determina se ha bisogno di ricalcolare o meno. In caso contrario, restituisce un 304 NOT MODIFIED . In tal caso, ricalcola e restituisce il nuovo rapporto nel corpo della risposta.

I should note that in the question, but recalculation takes a time. E.g. up to 10 minutes. So the request cannot be really synchronous. It is not like "I want to get the result right being up to date" but "I want this resource to become up to date right now to get it later"

In tal caso, crea un nuovo endpoint, ad esempio /report-updates/{id} . Chiama POST /report-updates/{id} . Se il rapporto è aggiornato, restituisci un 304 Not Modified . Se il report deve essere ricalcolato, restituire un 202 Accepted . Includere un corpo di risposta con uno stato corrente e un tempo di completamento stimato. Una chiamata GET a /report-updates restituirà 200 OK con lo stato corrente / tempo di completamento o 307 Temporary Redirect con un'intestazione Location impostata su /reports/{id} .

L'altra scelta è quella di fare in modo che il client esegua regolarmente il polling del server. Usa GET /reports/{id} con le intestazioni condizionali come sopra. Restituisci sempre 200 o 304 , ma avvia un ricalcolo ogni volta che i dati del server non sono aggiornati. Quindi tutti i clienti hanno la certezza di ottenere il calcolo più recente.

    
risposta data 17.05.2016 - 16:43
fonte
1

Per le letture: la mia solita risposta è quella traccia di ciascun "report" con diversi ID. Ad esempio

GET /reports/{id}/latest is going to redirect to, say,
GET /reports/{id}/latest?asOf=2016-05-17T12:00:00%20-0500

Queste risorse fanno sempre riferimento a report in cui l'elaborazione è stata completata, quindi non c'è mai alcuna attesa da fare, la rappresentazione del report è memorizzabile nella cache e così via.

Per il processo di esecuzione di un aggiornamento, utilizzerei una risorsa diversa. Come dice Jim Webber, HTTP non è la tua applicazione; lo usi per implementare il tuo protocollo passando documenti in giro.

Quindi PUT un comando (o POST, se la tua rappresentazione di stato è html) per programmare un aggiornamento. Potrebbe essere come:

PUT /reports/{id}/updates/your-guid-here-two-dollah

e se l'applicazione è disposta a pianificare un aggiornamento del report in quel momento, restituisce un 201 creato, con una rappresentazione dello stato dell'applicazione che indica al client come verificare gli aggiornamenti nel processo del report. Nel momento in cui il report è pronto, la rappresentazione dello stato dell'applicazione includerà un collegamento al report che è stato generato.

Se hai un contratto di servizio per il rapporto, puoi giocare con alcuni giochi con le cache per assicurarti che il client possa "aggiornare" senza sovraccaricare il tuo servizio, se pensi che sia importante.

Visualizzazione consigliata: REST in pratica di Jim Webber - specialmente quando si discute dell'implementazione del protocollo Restbucks.

    
risposta data 17.05.2016 - 18:12
fonte

Leggi altre domande sui tag