From 1d5d9b41b2b32407f06a69d5697c7a639d12216d Mon Sep 17 00:00:00 2001 From: Abdelkader Boudih Date: Mon, 12 Feb 2024 01:39:08 +0100 Subject: [PATCH] chore: Refactor and optimize MySQL advisory lock handling This commit removes unused MySQL lock variables, --- Makefile | 14 ++++++++++++++ docker-compose.yml | 20 ++++++++++++++++++++ lib/with_advisory_lock/mysql.rb | 14 ++++++++------ test/with_advisory_lock/shared_test.rb | 4 ++-- test/with_advisory_lock/thread_test.rb | 4 ++-- 5 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 Makefile create mode 100644 docker-compose.yml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dc1fe05 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +.PHONY: test-pg test-mysql + +test-pg: + docker compose up -d pg + sleep 10 # give some time for the service to start + DATABASE_URL=postgres://with_advisory:with_advisory_pass@localhost/with_advisory_lock_test appraisal activerecord-7.1 rake test + +test-mysql: + docker compose up -d mysql + sleep 10 # give some time for the service to start + DATABASE_URL=mysql2://with_advisory:with_advisory_pass@0.0.0.0:3306/with_advisory_lock_test appraisal activerecord-7.1 rake test + + +test: test-pg test-mysql diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2440305 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.9" +services: + pg: + image: postgres:16 + environment: + POSTGRES_USER: with_advisory + POSTGRES_PASSWORD: with_advisory_pass + POSTGRES_DB: with_advisory_lock_test + ports: + - "5432:5432" + mysql: + image: mysql:8 + environment: + MYSQL_USER: with_advisory + MYSQL_PASSWORD: with_advisory_pass + MYSQL_DATABASE: with_advisory_lock_test + MYSQL_RANDOM_ROOT_PASSWORD: "yes" + MYSQL_ROOT_HOST: '%' + ports: + - "3306:3306" diff --git a/lib/with_advisory_lock/mysql.rb b/lib/with_advisory_lock/mysql.rb index bdb35e7..3ca8ef9 100644 --- a/lib/with_advisory_lock/mysql.rb +++ b/lib/with_advisory_lock/mysql.rb @@ -2,10 +2,8 @@ module WithAdvisoryLock class MySQL < Base - # Caches nested lock support by MySQL reported version - @@mysql_nl_cache = {} - @@mysql_nl_cache_mutex = Mutex.new - # See https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock + # See https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html + # See https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html def try_lock raise ArgumentError, 'shared locks are not supported on MySQL' if shared raise ArgumentError, 'transaction level locks are not supported on MySQL' if transaction @@ -18,8 +16,12 @@ def release_lock end def execute_successful?(mysql_function) - sql = "SELECT #{mysql_function} AS #{unique_column_name}" - connection.select_value(sql).to_i.positive? + execute_query(mysql_function) == 1 + end + + def execute_query(mysql_function) + sql = "SELECT #{mysql_function}" + connection.query_value(sql) end # MySQL wants a string as the lock key. diff --git a/test/with_advisory_lock/shared_test.rb b/test/with_advisory_lock/shared_test.rb index 7cd23a4..f2b0ba1 100644 --- a/test/with_advisory_lock/shared_test.rb +++ b/test/with_advisory_lock/shared_test.rb @@ -24,7 +24,7 @@ def cleanup! private def work - ApplicationRecord.connection_pool.with_connection do + Tag.connection_pool.with_connection do Tag.with_advisory_lock('test', timeout_seconds: 0, shared: @shared) do @locked = true sleep 0.01 until @cleanup @@ -117,7 +117,7 @@ class PostgreSQLTest < SupportedEnvironmentTest end def pg_lock_modes - ApplicationRecord.connection.select_values("SELECT mode FROM pg_locks WHERE locktype = 'advisory';") + Tag.connection.select_values("SELECT mode FROM pg_locks WHERE locktype = 'advisory';") end test 'allows shared lock to be upgraded to an exclusive lock' do diff --git a/test/with_advisory_lock/thread_test.rb b/test/with_advisory_lock/thread_test.rb index 2c86be0..4e00f27 100644 --- a/test/with_advisory_lock/thread_test.rb +++ b/test/with_advisory_lock/thread_test.rb @@ -10,7 +10,7 @@ class SeparateThreadTest < GemTestCase @t1_return_value = nil @t1 = Thread.new do - ApplicationRecord.connection_pool.with_connection do + Label.connection_pool.with_connection do @t1_return_value = Label.with_advisory_lock(@lock_name) do @mutex.synchronize { @t1_acquired_lock = true } sleep @@ -21,7 +21,7 @@ class SeparateThreadTest < GemTestCase # Wait for the thread to acquire the lock: sleep(0.1) until @mutex.synchronize { @t1_acquired_lock } - ApplicationRecord.connection.reconnect! + Label.connection.reconnect! end teardown do