우리는 객체에 대해 잠재적으로 장기 실행 계산을 수행하는 비동기 태스크를 가지고 있습니다. 그런 다음 결과가 개체에 캐시됩니다. 여러 작업이 동일한 작업을 반복하지 않도록하기 위해 원자 적 SQL 업데이트로 잠금을 추가했습니다.RSpec 단위 테스트의 경쟁 조건 시뮬레이션
UPDATE objects SET locked = 1 WHERE id = 1234 AND locked = 0
잠금은 비동기 작업에만 적용됩니다. 개체 자체는 여전히 사용자가 업데이트 할 수 있습니다. 이런 경우 이전 버전의 객체에 대한 완료되지 않은 작업은 결과가 유효하지 않을 수 있으므로 결과를 폐기해야합니다. 이것은 또한 원자 SQL 업데이트와는 꽤 쉽게 : 객체가 업데이트되었습니다
UPDATE objects SET results = '...' WHERE id = 1234 AND version = 1
경우, 그 버전이 일치하지 않습니다 그래서 결과가 삭제됩니다.
이러한 두 개의 원자 적 업데이트는 가능한 모든 경쟁 조건을 처리해야합니다. 문제는 단위 테스트에서 그것을 확인하는 방법입니다.
첫 번째 세마포는 테스트가 쉽습니다. 두 가지 가능한 시나리오, 즉 (1) 개체가 잠긴 위치와 (2) 개체가 잠겨 있지 않은 위치의 두 가지 테스트를 설정하는 것만 큼 쉽습니다. (우리는 SQL 쿼리의 원 자성을 데이터베이스 공급 업체의 책임으로 테스트 할 필요가 없습니다.)
두 번째 세마포는 어떻게 테스트합니까? 객체는 첫 번째 세마포어 이후 몇 번째 시간이지만 두 번째 전에 변경되어야합니다. 이렇게하면 업데이트가 안정적이고 일관되게 수행 될 수 있도록 실행이 일시 중지되어야하지만 RSpec을 사용하여 중단 점을 주입하는 것은 지원되지 않습니다. 이것을 할 수있는 방법이 있습니까? 또는 그러한 경쟁 조건을 시뮬레이션하기 위해 간과할만한 다른 기술이 있습니까?
A-ha. 그렇게 할 것입니다.명시 적 후크를 추가하는 대신, 나는 단지'alias_method_chain'을 사용하여 두 개의 세마포어 사이에서 호출되는 메소드의 기능을 확장 할 수 있습니다. 장기 실행 태스크. – Ian
이안, 그럴거야. –
+1 당신의 직유에 기생 말벌 유충을 사용합니다. – aronchick