-
Notifications
You must be signed in to change notification settings - Fork 73
Fix MySQL release_advisory_lock signature compatibility with Rails 7.2+ #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…7.2+ Rails 7.2+ changed the signature of release_advisory_lock to require a lock_name: keyword argument. This causes an ArgumentError when migrations run: "missing keyword: :lock_name". This commit updates MySQL's implementation to handle both signatures, similar to how PostgreSQL already does it. The method now checks if it's being called with ActiveRecord's signature (single positional arg, no kwargs) or the gem's signature (lock_keys positional arg with keyword args). Fixes #126
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a signature compatibility issue with MySQL's release_advisory_lock method that causes Rails 7.2+ migrations to fail. The problem occurs because Rails calls the method with a single positional argument while the gem expects keyword arguments.
- Updated MySQL's
release_advisory_lockto handle both Rails' positional signature and the gem's keyword signature - Added comprehensive test coverage for both signature variants and error handling scenarios
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| lib/with_advisory_lock/mysql_advisory.rb | Modified release_advisory_lock method to accept both Rails' positional signature and gem's keyword signature |
| test/with_advisory_lock/mysql_release_lock_test.rb | Added comprehensive test suite covering both signature variants and error handling |
Comments suppressed due to low confidence (1)
test/with_advisory_lock/mysql_release_lock_test.rb:114
- The error handling test doesn't actually test the error handling path described in the comment. It only verifies that certain error messages don't appear, but doesn't simulate actual connection errors. Consider using a mock or stub to actually test the error handling behavior, or remove this test if it cannot meaningfully test the intended scenario.
refute_match(/Lost connection|MySQL server has gone away|Connection refused/i, e.message)
|
|
||
| execute_successful?("GET_LOCK(#{quote(lock_keys.first)}, #{mysql_timeout})") | ||
| end | ||
|
|
Copilot
AI
Jul 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method lacks documentation explaining the dual signature support. Consider adding a comment above the method explaining it handles both Rails' release_advisory_lock(lock_id) signature and the gem's release_advisory_lock(lock_keys, lock_name:, **) signature for Rails 7.2+ compatibility.
| # This method supports two signatures for compatibility: | |
| # 1. Rails' ActiveRecord signature: release_advisory_lock(lock_id) | |
| # - Used by Rails migrations with a single positional argument. | |
| # 2. Gem's custom signature: release_advisory_lock(lock_keys, lock_name:, **) | |
| # - Allows releasing locks using lock keys and additional options. | |
| # The method determines the signature based on the arguments passed. |
|
|
||
| # Acquire lock using SQL (ActiveRecord doesn't provide get_advisory_lock method) | ||
| lock_keys = model_class.connection.lock_keys_for(lock_name) | ||
| result = model_class.connection.select_value("SELECT GET_LOCK(#{model_class.connection.quote(lock_keys.first)}, 0)") |
Copilot
AI
Jul 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The direct SQL query construction is duplicated on lines 72, 81, and 85. Consider extracting this into a helper method like acquire_lock_sql(lock_key) and release_lock_sql(lock_key) to reduce duplication and improve maintainability.
| result = model_class.connection.select_value("SELECT GET_LOCK(#{model_class.connection.quote(lock_keys.first)}, 0)") | |
| result = model_class.connection.select_value(acquire_lock_sql(lock_keys.first)) |
|
Tested this branch, and passed ✅ Confirm fixed. 👍 |
Summary
This PR fixes the
ArgumentError: missing keyword: :lock_nameerror that occurs when running Rails migrations with MySQL on Rails 7.2+.Problem
Rails calls
release_advisory_lockwith a single positional argument during migrations:However, the gem's MySQL implementation was expecting keyword arguments:
This mismatch caused migrations to fail with the error reported in #126.
Solution
Updated MySQL's
release_advisory_lockmethod to handle both signatures:release_advisory_lock(lock_id)- single positional argumentrelease_advisory_lock(lock_keys, lock_name:, **)- with keyword argumentsThe implementation now matches PostgreSQL's approach, which already handles both signatures correctly.
Testing
Fixes #126
@luciiii6 @luk4s Could you please test this fix with your Rails 7.2 applications to confirm it resolves the migration issue?