feat: scope advisory lock names by scope column values#490
Open
zakky21 wants to merge 1 commit intoClosureTree:masterfrom
Open
feat: scope advisory lock names by scope column values#490zakky21 wants to merge 1 commit intoClosureTree:masterfrom
zakky21 wants to merge 1 commit intoClosureTree:masterfrom
Conversation
When `scope:` option is configured (e.g., `scope: :company_id`),
advisory lock names now include the scope values from the instance.
This prevents unnecessary lock contention across different tenants
in multi-tenant environments.
Previously, all operations shared a single lock per model class
(`ct_{CRC32(class_name)}`). Now, scoped models use per-scope locks
(e.g., `ct_{CRC32(class_name)}_{company_id}`), allowing concurrent
operations on different tenants.
- Add `advisory_lock_name_for(instance)` to SupportAttributes
- Update `with_advisory_lock` to accept an optional instance argument
- Pass `self` at all instance-method call sites (5 locations)
- Class-method call sites pass `nil` (fallback to model-wide lock)
- Fully backward compatible: no change for unscoped models or
existing callers without the instance argument
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scope:option is configured (e.g.,scope: :company_id), advisory lock names now include the scope values from the instancect_{CRC32(class_name)}). Now, scoped models use per-scope locks (e.g.,ct_{CRC32(class_name)}_{company_id})Changes
advisory_lock_name_for(instance)method toSupportAttributesthat appends scope values to the base lock namewith_advisory_lockinSupportto accept an optionalinstanceargumentselfat all 5 instance-method call sites (_ct_before_destroy,rebuild!,delete_hierarchy_references,add_sibling,find_or_create_by_path)rebuild!,find_or_create_by_path) passnil, falling back to model-wide lockBackward Compatibility
instanceargument defaults tonil— existing callers are unaffectedadvisory_lock_nameoption is preserved as the base nameTest plan
scope: :user_id) generates lock name with scope value suffixscope: [:user_id, :group_id]) includes all scope valuesnilinstance returns base lock name (class-method fallback)Related: #240 (deadlocks during concurrent operations)