Tenemos una tarea asíncrona que realiza un cálculo potencialmente de larga duración para un objeto. El resultado se almacena en caché en el objeto. Para evitar múltiples tareas de repetir el mismo trabajo, hemos añadido bloqueo con una actualización de SQL atómica:Simulando condiciones de carrera en las pruebas de unidades RSpec
UPDATE objects SET locked = 1 WHERE id = 1234 AND locked = 0
El bloqueo es sólo para la tarea asíncrona. El objeto en sí aún puede ser actualizado por el usuario. Si eso sucede, cualquier tarea inacabada para una versión anterior del objeto debería descartar sus resultados, ya que es probable que estén desactualizados. Esto también es bastante fácil de hacer con una actualización de SQL atómica:
UPDATE objects SET results = '...' WHERE id = 1234 AND version = 1
Si el objeto se ha actualizado, su versión no coincidirá y así será descartado los resultados.
Estas dos actualizaciones atómicas deben manejar cualquier condición de carrera posible. La pregunta es cómo verificar eso en pruebas unitarias.
El primer semáforo es fácil de probar, ya que es simplemente una cuestión de configurar dos pruebas diferentes con los dos escenarios posibles: (1) donde el objeto está bloqueado y (2) donde el objeto no está bloqueado. (No es necesario que verifiquemos la atomicidad de la consulta SQL, ya que eso debería ser responsabilidad del proveedor de la base de datos).
¿Cómo se prueba el segundo semáforo? El objeto debe ser cambiado por un tercero un tiempo después del primer semáforo, pero antes del segundo. Esto requeriría una pausa en la ejecución para que la actualización se realice de manera confiable y consistente, pero no conozco ningún soporte para inyectar puntos de interrupción con RSpec. ¿Hay alguna forma de hacer esto? ¿O hay alguna otra técnica que estoy pasando por alto para simular tales condiciones de carrera?
A-ha. Eso lo haría.Aunque en lugar de agregar un gancho explícito, podría usar 'alias_method_chain' para extender la funcionalidad de un método que _haga_ llamado entre los dos semáforos de todos modos: la tarea de larga ejecución. – Ian
Ian, eso lo haría. –
+1 por usar larvas de avispas parásitas en tu símil. – aronchick