Firebase permet à une ressource d’être mise à jour de manière transactionnelle . Si je comprends bien, le client achète des requêtes au serveur en disant: “Si l’ancienne valeur est X, définissez la nouvelle valeur Y”. En cas de conflit, le serveur peut rejeter plusieurs mises à jour du client jusqu’à ce que l’une d’elles soit acceptée.
Maintenant, que faire si je veux mettre à jour plusieurs ressources de manière atomique?
Que se passe-t-il si la première mise à jour est acceptée, puis le client est déconnecté avant que la deuxième mise à jour ne soit acceptée. Est-il possible d’inclure plusieurs mises à jour dans une transaction atomique? Sinon, existe-t-il une solution idiomatique à ce problème?
METTRE À JOUR
Il est maintenant possible de mettre à jour plusieurs emplacements de manière atomique. Voir ce blog pour plus de détails.
var mergedUpdate = {}; mergedUpdate[ 'users/' + userId + '/widgets/' + widgetId ] = true; mergedUpdate[ 'widgets/' + widgetId ] = widgetData; var ref = new Firebase("https://.firebaseio.com/"); ref.update(mergedUpdate);
Cela n’applique pas les données transactionnelles (si la valeur est actuellement X, faites-en Y), mais cette partie peut être déplacée vers les règles de sécurité . Par exemple, si nous voulons mettre à jour deux compteurs en même temps, nous pourrions append des règles comme suit:
{ "counter1": { ".validate": "newData.val() === (data.val()||0)+1" }, "counter2"1 { ".validate": "newData.val() === (data.val()||0)+1" } }
Maintenant, nous pouvons tenter la même mise à jour multi-chemins que ci-dessus. Si les valeurs ont changé depuis leur dernière lecture depuis le serveur, la tentative échouera. Nous pouvons vérifier if( error.code === 'PERMISSION_DENIED' ) { ... }
pour voir si l’échec était dû à la validation, et réessayez en conséquence.
POSTE ORIGINAL
La seule façon de procéder consiste à exécuter une transaction sur un ancêtre commun.
Par exemple, si vous souhaitez mettre à jour / a / b / c et / a / x / y, vous pouvez exécuter une transaction sur / a et modifier les deux valeurs.
L’inconvénient de cette approche est qu’elle peut être coûteuse avec les E / S réseau, car toutes les données contenues dans la transaction doivent être téléchargées et renvoyées au serveur.
Une approche plus compliquée mais potentiellement plus puissante que vous pourriez envisager est de restructurer vos données afin que, plutôt que de stocker les valeurs réelles, vous stockiez un historique des modifications. Par exemple, si vous stockez des informations sur le solde bancaire, vous pouvez enregistrer un historique des repositorys et des retraits. Ensuite, lorsque vous souhaitez obtenir le solde, vous pouvez lire l’historique complet et calculer le solde final.
La beauté de cette approche est qu’elle vous permet de faire des mises à jour atomiques. Par exemple, si vous transférez de l’argent du compteA vers AccountB, vous devez simplement append un élément à la fin du journal en indiquant “transférer du compte A au compte N dollars”. Ajouter cet élément unique est une opération atomique.
C’est l’approche que nous prenons avec Firepad , notre éditeur de texte collaboratif.
il y a un autre moyen … très fastidieux … et pas vraiment des transactions …
Comme Firebase autorise des modifications atomiques sur une valeur, vous pouvez créer un verrou ou un sémaphore avec la signification de “lancé une transaction sur les ressources x, y et z” … bien sûr, ce n’est pas une transaction réelle bloquer les ressources, une partie du verrou. Nous pourrions appeler cela une transaction par convention. Les clients doivent savoir que lorsque le verrou est occupé, ils ne doivent pas modifier les ressources x, y et z ….