2017-01-13 1 views
1

Je souhaite utiliser une base de données Datomic sans déclencher d'effets secondaires. L'objectif est de travailler sur une version "alternative" de la base de données actuelle, et de valider les données si la création de la version alternative a réussi. Sinon, la connexion à la base de données doit rester dans son état actuel.Datomic: Comment synchroniser les datoms entre une connexion et (datomic.api/with db)?

J'ai trouvé que datomic.api/with convient bien à mon problème, mais je ne sais pas quel serait le meilleur moyen d'ajouter les datoms créés dans la version alternative à la connexion Datomic.

Voici ma procédure actuelle:

(defn operation [conn] 
    (let [db (d/db conn) 
     current-t (d/basic-t db) 
     new-db (create-alternative-version db)] 
    (d/transact conn (d/datoms (d/since new-db current-t) :eavt)))) 

En ce moment, je reçois l'erreur suivante:

ClassCastException datomic.db$datoms$reify__1559 
cannot be cast to java.util.List datomic.api/transact 

Pensez-vous que cette approche a du sens? S'il y a une meilleure solution?

J'ai également regardé l'API de synchronisation, mais cela ne semble pas adapté à cette fin.

Merci pour votre aide

Répondre

1

Pas de synchronisation entre un avec-db et db sur un transactor est en vigueur. Un avec-db est une réalité alternative et ne détient aucun verrou sur la connexion du transacteur ou la base de données en cours sur le transactor. Pour un exemple, considérez que vous effectuez une transaction par d/avec et que vous obtenez en retour une valeur avec-db, un état de base de données spéculative avec la transaction appliquée. Ensuite, vous vérifiez si l'état de la base de données résultante est "réussi" (vous n'avez pas précisé ce que signifie "réussi", mais je suppose qu'il nécessite de vérifier des parties de l'état db résultant). Il n'y a aucune garantie que la même transaction aboutirait au même état de la base de données réelle puisqu'une autre transaction pourrait se produire entre les deux.

La solution typique à ce problème de synchronisation consiste à identifier la vérification minimale de «succès» et à l'implémenter dans une fonction de transaction. Dans une fonction de transaction, vous pouvez accéder à un état de base de données cohérent avant la transaction. Les fonctions de transaction s'exécutent de manière isolée pendant une transaction et peuvent être utilisées pour laisser la transaction échouer si elle n'aboutit pas à un état de base de données "réussi". Une alternative à l'échec des transactions consiste à injecter des données à partir de l'état de la base de données avant la transaction. Si nécessaire, vous pouvez utiliser d/with à partir d'une fonction de transaction.

Voici la documentation des fonctions de transaction: http://docs.datomic.com/database-functions.html


Votre exemple ne fonctionne pas parce que les rendements d/datoms eavt tuples, alors qu'une transaction nécessiterait tuples d'affirmation commençant par :db/add, :db/retract ou ident d'un fonction de transaction, ou des cartes pour l'upsertion. Vous pourriez bien sûr transformer les tuples eavt en de tels tuples d'assertion mais vous auriez manqué des rétractions (pourrait travailler avec d/history, IDK). Il serait plus facile de simplement appliquer la même transaction que vous avez appliquée à d/with à d/transact. Néanmoins, cela ne vous donnerait aucune garantie de synchronisation comme expliqué ci-dessus.