Rest chiama le API con effetti collaterali su altre risorse

4

Diciamo che ho un'app mobile, Android / iOS e un backend java Spring. Data la connettività mobile, il numero di round trip della rete deve essere limitato, idealmente, 1 o meno per schermo.

Ora, supponiamo di voler aggiungere / riscrivere alcune funzionalità di messaggistica quando 2+ utenti di app possono inviarsi reciprocamente messaggi.

Ci sono 2 tabelle / risorse (semplificate qui). "Conversazione" e "Messaggio". Ogni conversazione contiene più messaggi.

conversation 
-----------------
id 
type 
last_message_test
last_message_username
message_count
etc

message
------------
id
conversation_id 
user_id
user name 
text
timestamp 

I record di conversazione contengono alcune informazioni sull'ultimo messaggio che è stato fatto in modo che una schermata che elenca solo l'intestazione di molte conversazioni possa mostrare il suo contenuto più recente senza dover interrogare la tabella dei messaggi effettiva (anche il numero dei messaggi).

idealmente ci sarebbero chiamate come questa:

POST /api/conversation                                 => create a new conversation 
POST /api/conversation/1234/message                    => post a new message in conversation 1234
GET  /api/conversation?searchparam1=1&searchparam2=2   => retrieve certain conversation without their full actual content
GET  /api/converstaion/1234/message                    => retrieve all the messages of a given conversation, 1234

Ecco i problemi però:

problema A) Quando si postula un nuovo messaggio, questo crea una nuova risorsa di messaggio ma è anche l'effetto collaterale di un aggiornamento (asincrono / di messaggistica) sul corrispondente record di "conversazione". Quindi, il POST di una nuova risorsa di tipo A attiva un PATCH di un'altra risorsa di tipo B. Va bene?

problema B) Quando si postula il primo messaggio, non c'è ancora un record di conversazione. Entrambi devono essere creati, prima il record "conversazione", quindi il record "messaggio" che conterrà il nuovo ID conversazione (idealmente in una transazione). Come farlo in un modo di riposo senza dover fare 2 chiamate api?

Fondamentalmente cercando di trovare il giusto compromesso tra:

  • numero di chiamate di riposo
  • campi db duplicati e query
  • stile di riposo dell'API orientata alle risorse

Forse non è davvero possibile senza aggiungere nuove risorse artificiali o operazioni / punti finali "batch / bundle / aggregati"? qualsiasi raccomandazione apprezzata, grazie!

    
posta MikaelW 02.08.2016 - 19:00
fonte

2 risposte

6

Problema A) Sì, va bene. REST ful POST s sono autorizzati a generare effetti collaterali su altre risorse. Suggerirei di scomporre i messaggi dalle conversazioni nella gerarchia URI in questo caso o di consentire ai client di inviare una risorsa di messaggio a /conversations per creare una nuova conversazione. Potrebbe rispondere con un Conversation Message con un URI "self" che punta alla conversazione e al messaggio appena creati.

Problema B) Quando POST un nuovo messaggio, se non contiene un ID di conversazione, fare in modo che il livello di servizio avvii una transazione che crea una nuova conversazione, quindi crea il messaggio con l'id di conversazione. La tua risposta da quel POST può contenere l'id di conversazione per le chiamate future.

Penso che parte del tuo problema sia l'unione di una tabella di database con una risorsa. È spesso il caso che il modello di database e il modello di risorse dovrebbero essere diversi, e penso che questo sia un buon esempio.

Se si desidera essere in grado di aggiornare lo schermo in una chiamata, capire quali informazioni devono essere presenti nella risposta a quella chiamata. Rendi la tua risorsa. I clienti possono POST a /messages e ottenere una risposta contenente qualcosa che non è un messaggio.

Ciò che REST sta cercando di spingerti verso è una macchina a stati, dove le risorse sono stati, le richieste sono gli input che determinano la transizione che fai e la risposta contiene il nuovo stato dopo aver completato la transizione.

Non correlato ma forse utile - è uno standard (allentato) per utilizzare plurali per le risorse di raccolta, quindi mi aspetto di vedere /conversations e /messages .

    
risposta data 02.08.2016 - 19:18
fonte
-2

REST in realtà non si presta all'elaborazione transazionale quindi è necessario riunire tutti gli oggetti in un bundle di transazione e quindi separare l'aspetto lato server in mapping di tipi JSON in Jackson. link

    
risposta data 02.08.2016 - 19:03
fonte

Leggi altre domande sui tag