Nous avons une tâche asynchrone qui effectue un calcul potentiellement long pour un objet. Le résultat est ensuite mis en cache sur l'objet. Pour éviter des tâches multiples de répéter le même travail, nous avons ajouté de verrouillage avec une mise à jour de SQL atomique:Simulation des conditions de concurrence dans les tests unitaires RSpec
UPDATE objects SET locked = 1 WHERE id = 1234 AND locked = 0
Le verrouillage est uniquement pour la tâche asynchrone. L'objet lui-même peut encore être mis à jour par l'utilisateur. Si cela se produit, toute tâche inachevée pour une ancienne version de l'objet doit ignorer ses résultats car ils sont probablement périmés. Ceci est également assez facile à faire avec une mise à jour de SQL atomique:
UPDATE objects SET results = '...' WHERE id = 1234 AND version = 1
Si l'objet a été mis à jour, sa version ne correspond pas à si bien que les résultats seront mis au rebut.
Ces deux mises à jour atomiques doivent gérer toutes les conditions de concurrence possibles. La question est de savoir comment vérifier cela dans les tests unitaires. Le premier sémaphore est facile à tester, puisqu'il suffit de configurer deux tests différents avec les deux scénarios possibles: (1) où l'objet est verrouillé et (2) où l'objet n'est pas verrouillé. (Nous n'avons pas besoin de tester l'atomicité de la requête SQL car cela devrait être la responsabilité du fournisseur de la base de données.)
Comment tester le second sémaphore? L'objet doit être changé par un tiers quelque temps après le premier sémaphore mais avant le second. Cela nécessiterait une pause dans l'exécution afin que la mise à jour puisse être effectuée de manière fiable et cohérente, mais je ne connais aucun support pour l'injection de points d'arrêt avec RSpec. Y a-t-il un moyen de faire cela? Ou y a-t-il une autre technique que je néglige pour simuler de telles conditions de course?
A-ha. Cela le ferait.Bien que plutôt que d'ajouter un hook explicite, je pourrais juste utiliser 'alias_method_chain' pour étendre la fonctionnalité d'une méthode qui doit être appelée entre les deux sémaphores de toute façon - la tâche de longue durée. – Ian
Ian, ça le ferait. –
+1 pour l'utilisation de la larve de guêpe parasite dans votre comparaison. – aronchick