with_advisory_lock 7.0.0 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2af1c67f9aa840ba30d4c1a280a74a02bd46e83cef6ee426a59e16d77afaf99f
4
- data.tar.gz: 055c8a8f251605c01d91fb4ead5f5cd3ab31b4327ee1bdb2b5fbd7b24cd0e455
3
+ metadata.gz: f594bf1ed9b20028febee227bd33eddf70f2c3deb42ae7e8a4d83d794125281d
4
+ data.tar.gz: 6882cea1e84d517bdf847b8f66b7dd6bb7b6c93de09c156b459019aab324ace0
5
5
  SHA512:
6
- metadata.gz: 9ea47f0a89759ee4573b7c0bf7a481e48bf7e5e6feac6b132ee42a5441478bb0d02840f1e40d5963ebc5c5bc93af47a21e4f58337e33c42091d07160994a0821
7
- data.tar.gz: b584c732c8fd97dd74cc6c92286d19ef9f79fbb9911a626c092c0197028cc99540f3af5dce34fbc9579fd1c01d207c7426e57b91c0928cbb4ff3620f62bd0995
6
+ metadata.gz: a89eff2b9fccadd2f64ac7467c9daf19156fbac5196358b9ce7089c2d743c353e4fbb8b993d2c0440b0f253c78a56620a603cd9d41dd0e3f027e02b5f901f72c
7
+ data.tar.gz: 02b5903b081175e8f7ce07450738fd88d8f0f92dfc52fbb6901e9738aa90312313c3313c70ccfcdab998aa799399a173215edf913145b72d56958042681fb4e6
@@ -1 +1 @@
1
- {".":"7.0.0"}
1
+ {".":"7.0.1"}
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## Changelog
2
2
 
3
+ ## [7.0.1](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v7.0.0...with_advisory_lock/v7.0.1) (2025-07-21)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * handle ActiveRecord's release_advisory_lock signature for Rails 7.2+ ([#127](https://github.com/ClosureTree/with_advisory_lock/issues/127)) ([94253ca](https://github.com/ClosureTree/with_advisory_lock/commit/94253ca2af7f684a3c99645765853546c3da8e02)), closes [#126](https://github.com/ClosureTree/with_advisory_lock/issues/126)
9
+
3
10
  ## [7.0.0](https://github.com/ClosureTree/with_advisory_lock/compare/with_advisory_lock/v6.0.0...with_advisory_lock/v7.0.0) (2025-07-05)
4
11
 
5
12
 
@@ -25,8 +25,17 @@ module WithAdvisoryLock
25
25
  execute_successful?("GET_LOCK(#{quote(lock_keys.first)}, #{mysql_timeout})")
26
26
  end
27
27
 
28
- def release_advisory_lock(lock_keys, lock_name:, **)
29
- execute_successful?("RELEASE_LOCK(#{quote(lock_keys.first)})")
28
+ def release_advisory_lock(*args, **kwargs)
29
+ # Handle both signatures - ActiveRecord's built-in and ours
30
+ if args.length == 1 && kwargs.empty?
31
+ # ActiveRecord's signature: release_advisory_lock(lock_id)
32
+ # Called by Rails migrations with a single positional argument
33
+ super
34
+ else
35
+ # Our signature: release_advisory_lock(lock_keys, lock_name:, **)
36
+ lock_keys = args.first
37
+ execute_successful?("RELEASE_LOCK(#{quote(lock_keys.first)})")
38
+ end
30
39
  rescue ActiveRecord::StatementInvalid => e
31
40
  # If the connection is broken, the lock is automatically released by MySQL
32
41
  # No need to fail the release operation
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WithAdvisoryLock
4
- VERSION = Gem::Version.new('7.0.0')
4
+ VERSION = Gem::Version.new('7.0.1')
5
5
  end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class MySQLReleaseLockTest < GemTestCase
6
+ self.use_transactional_tests = false
7
+
8
+ def model_class
9
+ MysqlTag
10
+ end
11
+
12
+ def setup
13
+ super
14
+ begin
15
+ skip unless model_class.connection.adapter_name =~ /mysql/i
16
+ MysqlTag.delete_all
17
+ rescue ActiveRecord::NoDatabaseError
18
+ skip "MySQL database not available. Please create the database first."
19
+ rescue StandardError => e
20
+ skip "MySQL connection failed: #{e.message}"
21
+ end
22
+ end
23
+
24
+ test 'release_advisory_lock handles gem signature with lock_keys' do
25
+ lock_name = 'test_gem_signature'
26
+ lock_keys = model_class.connection.lock_keys_for(lock_name)
27
+
28
+ # Acquire the lock
29
+ result = model_class.connection.try_advisory_lock(
30
+ lock_keys,
31
+ lock_name: lock_name,
32
+ shared: false,
33
+ transaction: false
34
+ )
35
+ assert result, 'Failed to acquire lock'
36
+
37
+ # Release using gem signature
38
+ released = model_class.connection.release_advisory_lock(
39
+ lock_keys,
40
+ lock_name: lock_name,
41
+ shared: false,
42
+ transaction: false
43
+ )
44
+ assert released, 'Failed to release lock using gem signature'
45
+
46
+ # Verify lock is released by trying to acquire it again
47
+ result = model_class.connection.try_advisory_lock(
48
+ lock_keys,
49
+ lock_name: lock_name,
50
+ shared: false,
51
+ transaction: false
52
+ )
53
+ assert result, 'Lock was not properly released'
54
+
55
+ # Clean up
56
+ model_class.connection.release_advisory_lock(
57
+ lock_keys,
58
+ lock_name: lock_name,
59
+ shared: false,
60
+ transaction: false
61
+ )
62
+ end
63
+
64
+ test 'release_advisory_lock handles ActiveRecord signature' do
65
+ # Rails calls release_advisory_lock with a positional argument (lock_id)
66
+ # This test ensures our override doesn't break Rails' migration locking
67
+
68
+ lock_name = 'test_rails_signature'
69
+
70
+ # Acquire lock using SQL (ActiveRecord doesn't provide get_advisory_lock method)
71
+ lock_keys = model_class.connection.lock_keys_for(lock_name)
72
+ result = model_class.connection.select_value("SELECT GET_LOCK(#{model_class.connection.quote(lock_keys.first)}, 0)")
73
+ assert_equal 1, result, 'Failed to acquire lock using SQL'
74
+
75
+ # Release using ActiveRecord signature (positional argument, as Rails does)
76
+ released = model_class.connection.release_advisory_lock(lock_keys.first)
77
+ assert released, 'Failed to release lock using ActiveRecord signature'
78
+
79
+ # Verify lock is released
80
+ lock_keys = model_class.connection.lock_keys_for(lock_name)
81
+ result = model_class.connection.select_value("SELECT GET_LOCK(#{model_class.connection.quote(lock_keys.first)}, 0)")
82
+ assert_equal 1, result, 'Lock was not properly released'
83
+
84
+ # Clean up
85
+ model_class.connection.select_value("SELECT RELEASE_LOCK(#{model_class.connection.quote(lock_keys.first)})")
86
+ end
87
+
88
+ test 'release_advisory_lock handles connection errors gracefully' do
89
+ lock_name = 'test_connection_error'
90
+ lock_keys = model_class.connection.lock_keys_for(lock_name)
91
+
92
+ # Acquire the lock
93
+ result = model_class.connection.try_advisory_lock(
94
+ lock_keys,
95
+ lock_name: lock_name,
96
+ shared: false,
97
+ transaction: false
98
+ )
99
+ assert result, 'Failed to acquire lock'
100
+
101
+ # Simulate connection error handling
102
+ # The method should handle various connection error types without raising
103
+ begin
104
+ # Try to release - even if we can't simulate a real connection error,
105
+ # the code path exists and should work
106
+ model_class.connection.release_advisory_lock(
107
+ lock_keys,
108
+ lock_name: lock_name,
109
+ shared: false,
110
+ transaction: false
111
+ )
112
+ rescue StandardError => e
113
+ # Should not raise connection-related errors
114
+ refute_match(/Lost connection|MySQL server has gone away|Connection refused/i, e.message)
115
+ raise
116
+ end
117
+ end
118
+ end
119
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: with_advisory_lock
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew McEachen
@@ -157,6 +157,7 @@ files:
157
157
  - test/with_advisory_lock/concern_test.rb
158
158
  - test/with_advisory_lock/lock_test.rb
159
159
  - test/with_advisory_lock/multi_adapter_test.rb
160
+ - test/with_advisory_lock/mysql_release_lock_test.rb
160
161
  - test/with_advisory_lock/parallelism_test.rb
161
162
  - test/with_advisory_lock/postgresql_race_condition_test.rb
162
163
  - test/with_advisory_lock/shared_test.rb