Quanto rappresenti meglio una sincronizzazione bidirezionale in una API REST?

20

Supponendo un sistema in cui è presente un'applicazione Web con una risorsa e un riferimento a un'applicazione remota con un'altra risorsa simile, come si rappresenta un'azione di sincronizzazione bidirezionale che sincronizza la risorsa "locale" con la risorsa "remota" ?

Esempio:

Ho un'API che rappresenta un elenco di cose da fare.

GET / POST / PUT / DELETE / todos /, ecc.

Tale API può fare riferimento ai servizi TODO remoti.

GET / POST / PUT / DELETE / todo_services /, ecc.

Posso manipolare tutti i todos dal servizio remoto tramite la mia API come proxy tramite

GET / POST / PUT / DELETE / todo_services / abc123 /, ecc.

Voglio la possibilità di eseguire una sincronizzazione bidirezionale tra un insieme locale di todos e il set remoto di TODOS.

In una sorta di rpc, si potrebbe fare

POST / todo_services / abc123 / sync /

Ma, nell'idea dei "verbi sono cattivi", c'è un modo migliore per rappresentare questa azione?

    
posta Edward M Smith 16.02.2012 - 17:16
fonte

5 risposte

17

Dove e quali sono le risorse?

REST si basa sull'indirizzamento delle risorse in modo stateless e rilevabile. Non deve essere implementato su HTTP, né deve fare affidamento su JSON o XML, sebbene sia strongmente raccomandato l'uso di un formato di dati ipermediali (vedere HATEOAS principio) poiché i collegamenti e gli ID sono desiderabili.

Quindi, la domanda diventa: come si può pensare alla sincronizzazione in termini di risorse?

Che cos'è la sincronizzazione bidirezionale? **

La sincronizzazione bidirezionale è il processo di aggiornamento delle risorse presenti su un grafico di nodi in modo che, alla fine del processo, tutti i nodi abbiano aggiornato le proprie risorse in conformità con le regole che governano tali risorse. In genere, si intende che tutti i nodi abbiano l'ultima versione delle risorse presente nel grafico. Nel caso più semplice il grafico è costituito da due nodi: locale e remoto. Local avvia la sincronizzazione.

Quindi la risorsa chiave che deve essere indirizzata è un log delle transazioni e, pertanto, un processo di sincronizzazione potrebbe essere simile alla raccolta "items" sotto HTTP:

Passaggio 1 - Local recupera il log delle transazioni

Locale: GET /remotehost/items/transactions?earliest=2000-01-01T12:34:56.789Z

Remoto: 200 OK con il corpo contenente il log delle transazioni contenente campi simili a questo.

  • itemId - un UUID per fornire una chiave primaria condivisa

  • updatedAt - timestamp per fornire un punto coordinato al momento dell'ultimo aggiornamento dei dati (presupponendo che non sia richiesta una cronologia delle revisioni)

  • fingerprint - un hash SHA1 del contenuto dei dati per un confronto rapido se updateAt è pochi secondi fuori

  • itemURI - un URI completo dell'elemento per consentire il recupero più tardi

Passaggio 2: locale confronta il registro delle transazioni remote con il proprio

Questa è l'applicazione delle regole aziendali di come sincronizzare. In genere, itemId identifica la risorsa locale, quindi confronta l'impronta digitale. Se c'è una differenza, viene eseguito un confronto di updatedAt . Se questi sono troppo vicini, è necessario prendere una decisione per eseguire il pull in base all'altro nodo (forse è più importante) o per passare all'altro nodo (questo nodo è più importante). Se la risorsa remota non è presente localmente, viene effettuata una immissione push (che contiene i dati effettivi per inserimento / aggiornamento). Si presume che tutte le risorse locali non presenti nel log delle transazioni remote siano invariate.

Le richieste pull vengono eseguite sul nodo remoto in modo che i dati esistano localmente utilizzando itemURI . Non vengono applicati localmente fino a un momento successivo.

Passaggio 3: invio del log delle transazioni di sincronizzazione locale su remoto

Locale: PUT /remotehost/items/transactions con il corpo contenente il log delle transazioni di sincronizzazione locale.

Il nodo remoto potrebbe elaborarlo in modo sincrono (se è piccolo e veloce) o in modo asincrono (pensa 202 ACCETTATO ) se è probabile che si verifichi un sovraccarico. Assumendo un'operazione sincrona, il risultato sarà 200 OK o 409 CONFLICT a seconda del successo o dell'errore. Nel caso di un 409 CONFLICT , il processo deve essere riavviato poiché si è verificato un errore di blocco ottimistico sul nodo remoto (qualcuno ha modificato i dati durante la sincronizzazione). Gli aggiornamenti remoti vengono elaborati con la propria transazione applicativa.

Passaggio 4: aggiornamento locale

I dati estratti nel passaggio 2 vengono applicati localmente in una transazione di applicazione.

Sebbene quanto sopra non sia perfetto (ci sono diverse situazioni in cui locali e remote possono mettersi nei guai e avere dati di pull remoti da locali è probabilmente più efficiente che inserirli in un grosso PUT) dimostra come REST può essere usato durante un processo di sincronizzazione bidirezionale.

    
risposta data 19.04.2012 - 11:19
fonte
4

Questo è un problema difficile. Non credo che REST sia un livello appropriato per implementare la sincronizzazione. Una sincronizzazione solida dovrebbe essenzialmente essere una transazione distribuita. REST non è lo strumento per quel lavoro.

(Presupposto: per "sincronizzazione" si intende che entrambe le risorse possono cambiare indipendentemente dall'altra in qualsiasi momento e si desidera la possibilità di riallinearle senza perdere gli aggiornamenti.)

Potresti considerare di crearne uno come "principale" e l'altro come "schiavo" in modo da poter tranquillamente clobare lo schiavo periodicamente con i dati del master.

Potresti anche prendere in considerazione il Microsoft Sync Framework se hai assolutamente bisogno di supportare in modo indipendente la modifica dei dati I negozi. Questo non funzionerebbe attraverso REST, ma dietro le quinte.

    
risposta data 19.02.2012 - 04:37
fonte
4

Considererei un'operazione di sincronizzazione come una risorsa accessibile (GET) o creata (POST). Con questo in mente, l'URL dell'API potrebbe essere:

/todo_services/abc123/synchronization

(Chiamandolo "sincronizzazione", non "sincronizzazione" per chiarire che non è un verbo)

Quindi fai:

POST /todo_services/abc123/synchronization

Per avviare una sincronizzazione. Poiché un'operazione di sincronizzazione è una risorsa, questa chiamata potrebbe potenzialmente restituire un ID che può essere utilizzato per verificare lo stato dell'operazione:

GET /todo_services/abc123/synchronization?id=12345
    
risposta data 20.05.2012 - 09:11
fonte
2

Apache CouchDB è un database basato su REST, HTTP e JSON. Gli sviluppatori eseguono operazioni CRUD di base su HTTP. Fornisce anche un meccanismo di replica che è peer-to-peer usando solo i metodi HTTP.

Per fornire questa replica, CouchDB deve avere alcune convenzioni specifiche per CouchDB. Nessuno di questi è contrario al REST. Fornisce ogni documento (ovvero una risorsa REST all'interno di un database) con un numero di revisione . Questo fa parte della rappresentazione JSON di quel documento, ma è anche nell'intestazione HTTP ETag. Ogni database ha anche un numero di sequenza che consente di tenere traccia delle modifiche al database nel suo complesso.

Per la risoluzione dei conflitti , si limitano a notare che un documento è in conflitto e conserva le versioni in conflitto, lasciandolo agli sviluppatori utilizzando il database per fornire un algoritmo di risoluzione dei conflitti.

Puoi usare CouchDB come API REST, che ti darà la sincronizzazione pronta per l'uso, o dare un'occhiata a come fornisce la replica per fornire un punto di partenza per creare il tuo algoritmo.

    
risposta data 26.07.2013 - 18:01
fonte
-1

Puoi risolvere il problema dei "verbi sono cattivi" con una semplice ridenominazione: usa "aggiornamenti" invece di "sincronizzazione".

Il processo di sincronizzazione sta effettivamente inviando un elenco di aggiornamenti locali effettuati dall'ultima sincronizzazione e ricevendo un elenco di aggiornamenti effettuati sul server nello stesso momento.

    
risposta data 20.03.2012 - 09:53
fonte

Leggi altre domande sui tag