# frozen_string_literal: true require 'test_helper' class TransactionScopingTest < GemTestCase def supported? %i[postgresql jdbcpostgresql].include?(env_db) end test 'raises an error when attempting to use transaction level locks if not supported' do skip if supported? Tag.transaction do exception = assert_raises(ArgumentError) do Tag.with_advisory_lock 'test', transaction: true do raise 'should not get here' end end assert_match(/#{Regexp.escape('not supported')}/, exception.message) end end class PostgresqlTest < TransactionScopingTest setup do skip unless env_db == :postgresql @pg_lock_count = lambda do ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM pg_locks WHERE locktype = 'advisory';").to_i end end test 'session locks release after the block executes' do Tag.transaction do assert_equal(0, @pg_lock_count.call) Tag.with_advisory_lock 'test' do assert_equal(1, @pg_lock_count.call) end assert_equal(0, @pg_lock_count.call) end end test 'session locks release when transaction fails inside block' do Tag.transaction do assert_equal(0, @pg_lock_count.call) exception = assert_raises(ActiveRecord::StatementInvalid) do Tag.with_advisory_lock 'test' do Tag.connection.execute 'SELECT 1/0;' end end assert_match(/#{Regexp.escape('division by zero')}/, exception.message) assert_equal(0, @pg_lock_count.call) end end test 'transaction level locks hold until the transaction completes' do Tag.transaction do assert_equal(0, @pg_lock_count.call) Tag.with_advisory_lock 'test', transaction: true do assert_equal(1, @pg_lock_count.call) end assert_equal(1, @pg_lock_count.call) end assert_equal(0, @pg_lock_count.call) end end end