# frozen_string_literal: true

require 'test_helper'

class SeparateThreadTest < GemTestCase
  setup do
    @lock_name = 'testing 1,2,3' # OMG COMMAS
    @mutex = Mutex.new
    @t1_acquired_lock = false
    @t1_return_value = nil

    @t1 = Thread.new do
      ActiveRecord::Base.connection_pool.with_connection do
        @t1_return_value = Label.with_advisory_lock(@lock_name) do
          @mutex.synchronize { @t1_acquired_lock = true }
          sleep
          't1 finished'
        end
      end
    end

    # Wait for the thread to acquire the lock:
    sleep(0.1) until @mutex.synchronize { @t1_acquired_lock }
    ActiveRecord::Base.connection.reconnect!
  end

  teardown do
    @t1.wakeup if @t1.status == 'sleep'
    @t1.join
  end

  test '#with_advisory_lock with a 0 timeout returns false immediately' do
    response = Label.with_advisory_lock(@lock_name, 0) do
      raise 'should not be yielded to'
    end
    assert_not(response)
  end

  test '#with_advisory_lock yields to the provided block' do
    assert(@t1_acquired_lock)
  end

  test '#advisory_lock_exists? returns true when another thread has the lock' do
    assert(Tag.advisory_lock_exists?(@lock_name))
  end

  test 'can re-establish the lock after the other thread releases it' do
    @t1.wakeup
    @t1.join
    assert_equal('t1 finished', @t1_return_value)

    # We should now be able to acquire the lock immediately:
    reacquired = false
    lock_result = Label.with_advisory_lock(@lock_name, 0) do
      reacquired = true
    end

    assert(lock_result)
    assert(reacquired)
  end
end
