オブジェクトに対して長時間実行される可能性のある計算を実行する非同期タスクがあります。結果はオブジェクトにキャッシュされます。複数のタスクが同じ作業を繰り返さないようにするために、アトミック SQL 更新によるロックを追加しました。
UPDATE objects SET locked = 1 WHERE id = 1234 AND locked = 0
ロックは非同期タスク専用です。オブジェクト自体は、ユーザーによって更新される可能性があります。その場合、オブジェクトの古いバージョンの未完了のタスクは、古い可能性があるため、その結果を破棄する必要があります。これも、アトミック SQL 更新を使用すると非常に簡単に実行できます。
UPDATE objects SET results = '...' WHERE id = 1234 AND version = 1
オブジェクトが更新されている場合、そのバージョンは一致しないため、結果は破棄されます。
これら 2 つのアトミックな更新は、考えられる競合状態を処理する必要があります。問題は、単体テストでそれを確認する方法です。
最初のセマフォは、(1) オブジェクトがロックされている場合と (2) オブジェクトがロックされていない場合の 2 つのシナリオで 2 つの異なるテストをセットアップするだけなので、簡単にテストできます。(SQL クエリの原子性をテストする必要はありません。それはデータベース ベンダーの責任です。)
2 番目のセマフォをどのようにテストしますか? オブジェクトは、最初のセマフォの後、2 番目のセマフォの前に、第三者によって変更される必要があります。これには、更新が確実かつ一貫して実行されるように実行を一時停止する必要がありますが、RSpec でブレークポイントを挿入するサポートがないことを私は知っています。これを行う方法はありますか?または、そのような競合状態をシミュレートするために見落としている他の手法はありますか?