En supposant un système où il y a une application Web avec une ressource et une référence à une application distante avec une autre ressource similaire, comment représentez-vous une action de synchronisation bidirectionnelle qui synchronise la ressource `` locale '' avec la ressource `` distante ''?
Exemple:
J'ai une API qui représente une liste de tâches.
GET / POST / PUT / DELETE / todos /, etc.
Cette API peut référencer des services TODO distants.
GET / POST / PUT / DELETE / todo_services /, etc.
Je peux manipuler les todos du service distant via mon API en tant que proxy via
GET / POST / PUT / DELETE / todo_services / abc123 /, etc.
Je veux pouvoir effectuer une synchronisation bidirectionnelle entre un ensemble local de todos et l'ensemble distant de TODOS.
D'une manière rpc, on pourrait faire
POST / todo_services / abc123 / sync /
Mais, dans l'idée "les verbes sont mauvais", existe-t-il une meilleure façon de représenter cette action?
la source
GET /todo/1/
etPOST
cela à/todo_services/abc123/
Mais, la 2 façon - je ne prends pas un ensemble de données et ne le mets PAS dans une ressource, l'action que je prends entraîne en fait la modification potentielle de deux ressources. Je suppose que je pourrais me rabattre sur le fait que les "todo syncronisations" soient ellesPOST /todo_synchronizations/ {"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now"}
GET /todo_synchronizations/1
=>{"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now","ran_at":"datetime","result":"success"}
Réponses:
Où et quelles sont les ressources?
REST consiste à adresser les ressources de manière apatride et détectable. Il n'a pas besoin d'être implémenté sur HTTP, ni de s'appuyer sur JSON ou XML, bien qu'il soit fortement recommandé d'utiliser un format de données hypermédia (voir le principe HATEOAS ) car les liens et les identifiants sont souhaitables.
Alors, la question devient: comment penser la synchronisation en termes de ressources?
Qu'est-ce que la synchronisation bidirectionnelle? **
La synchronisation bidirectionnelle est le processus de mise à jour des ressources présentes sur un graphe de nœuds afin qu'à la fin du processus, tous les nœuds aient mis à jour leurs ressources conformément aux règles régissant ces ressources. En règle générale, cela signifie que tous les nœuds disposeraient de la dernière version des ressources telles qu'elles sont présentes dans le graphique. Dans le cas le plus simple, le graphique se compose de deux nœuds: local et distant. Local lance la synchronisation.
Ainsi, la ressource clé qui doit être adressée est un journal des transactions et, par conséquent, un processus de synchronisation peut ressembler à ceci pour la collection "items" sous HTTP:
Étape 1 - Local récupère le journal des transactions
Local:
GET /remotehost/items/transactions?earliest=2000-01-01T12:34:56.789Z
À distance: 200 OK avec un corps contenant le journal des transactions contenant des champs similaires à celui-ci.
itemId
- un UUID pour fournir une clé primaire partagéeupdatedAt
- horodatage pour fournir un point coordonné lors de la dernière mise à jour des données (en supposant qu'aucun historique de révision n'est requis)fingerprint
- un hachage SHA1 du contenu des données pour une comparaison rapide enupdateAt
quelques secondesitemURI
- un URI complet à l'élément pour permettre une récupération ultérieureÉtape 2 - Local compare le journal des transactions distant avec le sien
Il s'agit de l'application des règles commerciales de synchronisation. En règle générale, le
itemId
identifie la ressource locale, puis compare l'empreinte digitale. S'il y a une différence, une comparaisonupdatedAt
est effectuée. Si ceux-ci sont trop proches pour être appelés, une décision devra être prise pour tirer en fonction de l'autre nœud (peut-être que c'est plus important), ou pour pousser vers l'autre nœud (ce nœud est plus important). Si la ressource distante n'est pas présente localement, une entrée push est effectuée (elle contient les données réelles pour l'insertion / la mise à jour). Toutes les ressources locales non présentes dans le journal des transactions distant sont supposées être inchangées.Les demandes d'extraction sont effectuées sur le nœud distant afin que les données existent localement à l'aide de
itemURI
. Ils ne sont appliqués localement que plus tard.Étape 3 - Envoyer le journal des transactions de synchronisation locale à distance
Local:
PUT /remotehost/items/transactions
avec corps contenant le journal des transactions de synchronisation local.Le nœud distant peut traiter cela de manière synchrone (s'il est petit et rapide) ou asynchrone (pensez 202 ACCEPTÉ ) s'il est susceptible d'entraîner une surcharge importante. En supposant une opération synchrone, le résultat sera soit 200 OK ou 409 CONFLIT selon le succès ou l'échec. Dans le cas d'un 409 CONFLICT , alors le processus doit être redémarré car il y a eu une défaillance de verrouillage optimiste au niveau du nœud distant (quelqu'un a changé les données pendant la synchronisation). Les mises à jour à distance sont traitées dans le cadre de leur propre transaction d'application.
Étape 4 - Mettre à jour localement
Les données extraites à l'étape 2 sont appliquées localement dans le cadre d'une transaction d'application.
Bien que ce qui précède ne soit pas parfait (il existe plusieurs situations où local et distant peuvent avoir des problèmes et avoir des données d'extraction à distance du local est probablement plus efficace que de les mettre dans un gros PUT), il montre comment REST peut être utilisé pendant un bi- processus de synchronisation directionnelle.
la source
Je considérerais une opération de synchronisation comme une ressource accessible (GET) ou créée (POST). Dans cet esprit, l'URL de l'API pourrait être:
(L'appeler "synchronisation", pas "sync" pour qu'il soit clair que ce n'est pas un verbe)
Alors fais:
Pour lancer une synchronisation. Étant donné qu'une opération de synchronisation est une ressource, cet appel peut potentiellement renvoyer un ID qui peut ensuite être utilisé pour vérifier l'état de l'opération:
la source
C'est un problème difficile. Je ne pense pas que REST soit un niveau approprié pour implémenter la synchronisation. Une synchronisation robuste devrait essentiellement être une transaction distribuée. REST n'est pas l'outil pour ce travail.
(Hypothèse: par "synchronisation", vous indiquez que l'une ou l'autre ressource peut changer indépendamment de l'autre à tout moment, et vous voulez pouvoir les réaligner sans perdre les mises à jour.)
Vous voudrez peut-être envisager de faire de l'un "maître" et de l'autre "esclave" afin de pouvoir assommer l'esclave périodiquement en toute confiance avec les données du maître.
Vous pouvez également envisager l'utilisation de Microsoft Sync Framework si vous avez absolument besoin de prendre en charge des magasins de données à modification indépendante. Cela ne fonctionnerait pas via REST, mais dans les coulisses.
la source
Apache CouchDB est une base de données basée sur REST, HTTP et JSON. Les développeurs effectuent des opérations CRUD de base sur HTTP. Il fournit également un mécanisme de réplication qui est peer-to-peer en utilisant uniquement des méthodes HTTP.
Pour fournir cette réplication, CouchDB doit avoir certaines conventions spécifiques à CouchDB. Aucun de ceux-ci n'est opposé au REST. Il fournit à chaque document (c'est-à-dire une ressource REST dans une base de données) un numéro de révision . Cela fait partie de la représentation JSON de ce document, mais se trouve également dans l'en-tête HTTP ETag. Chaque base de données possède également un numéro de séquence qui permet de suivre les modifications apportées à la base de données dans son ensemble.
Pour la résolution des conflits , ils notent simplement qu'un document est en conflit et conservent les versions en conflit, le laissant aux développeurs utilisant la base de données pour fournir un algorithme de résolution des conflits.
Vous pouvez soit utiliser CouchDB en tant qu'API REST, ce qui vous donnera une synchronisation prête à l'emploi, ou jeter un œil à la façon dont il fournit la réplication pour fournir un point de départ pour créer votre propre algorithme.
la source
Vous pouvez résoudre le problème "les verbes sont mauvais" avec un simple changement de nom - utilisez "mises à jour" au lieu de "synchronisation".
Le processus de synchronisation envoie en fait la liste des mises à jour locales effectuées depuis la dernière synchronisation et reçoit une liste des mises à jour effectuées sur le serveur en même temps.
la source