LoginSignup
7
2

More than 3 years have passed since last update.

Rspecで悲観的ロックをテストする

Last updated at Posted at 2017-11-18

悲観的ロックのテストを書くことがあって調べたら、それっぽい記事を発見したが、ペーペーは読んで??だったから、自分用に噛み砕いたものをメモ。

記事の例として挙げられている、銀行口座のように、同一のデータに対して、複数のユーザーから更新処理が実行される場合に、どちらかの処理をブロックしてデータの競合を避ける必要がある。

  • 複数のユーザーがログインしている状態を実現するために、usersをmapしてuser毎に作成したThreadの配列を生成。
  • Threadの配列をeachして、Thread#joinで処理が終了するのを待ち、終わったらThreadをdeadにするようにする。
  • Mutex#syncronizeでマルチスレッド時の処理を同期実行するようにしたけど、これだとテストできてないのか? ><
  • ロックが効いてて、データが更新されていないことを確認する。

describe 'Transaction Lock' do
  # ロールバックせずに保存するようにする
  self.use_transactional_fixtures = false

  mutex = Mutex.new

  describe '悲観ロックのテスト' do
    it 'お金消えたり増えたりしてないよね' do
      users.map { |user|
        Thread.new {
          # マルチスレッドで複数の処理が競合しないようにMutex#syncronizeで処理をブロックする。
          # mutex使っちゃったらマルチスレッドの意味無くなるのかな。。。分かる方教えてください m__m
          mutex.synchronize do
            # スレッド毎にDB接続
            ActiveRecord::Base.connection_pool.with_connection do
              # 悲観的ロック
            end
          end
        }
      }.each(&:join)

      # お金消えたり増えたりしてないことを確認
      expect(...).to eq(...)
    end
  end
end

参考
RubyのThread
Thread#join
Rubyで基礎的なマルチスレッドプログラミングをするためのサンプル
RubyのThread、Fiber、Kernel、forkで並列処理やプロセスの深淵へ
RubyのThreadを利用したWebサーバーを作る
RubyでThreadを使う
irbから学ぶRubyの並列処理 ~ forkからWebSocketまで

7
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2