Fix deadlock in belongs_to/has_many :through; support polymorphic source_type#336
Fix deadlock in belongs_to/has_many :through; support polymorphic source_type#336kbrock wants to merge 3 commits into
Conversation
b3a12f3 to
9a3f665
Compare
|
update: removed class load |
There was a problem hiding this comment.
@kbrock Sorry for not reviewing this earlier. It looks good, I left one comment about whether using :source_type will generate N+1 queries, but I think we can just collapse that to a where(id: ids).
| klass = source_type.safe_constantize | ||
| if klass < ActiveHash::Base | ||
| ids = send(options[:through]).map { |jm| jm.send(source_foreign_key) }.compact.uniq | ||
| ids.flat_map { |id| klass.find_by_id(id) }.compact |
There was a problem hiding this comment.
This could potentially make a lot of queries. Could we instead do:
| ids.flat_map { |id| klass.find_by_id(id) }.compact | |
| klass.where(id: ids) |
? If we need to keep the order we could do something like this to keep it to a single query:
records = klass.where(id: ids).index_by(&:id)
ids.filter_map { |id| records[id] }There was a problem hiding this comment.
Thanks. This is accessing a Ruby hash, so I'm pretty sure it is reading from memory and basically does the same thing under the covers, but I like how the where clause reads, and it allows a user to use order(:id).
We undefine these classes in the after {}
So in theory, they should not be a duplicate.
rspec often uses stub_const, but active record has issues with this since
they dig into the class.name and stuff
Move class resolution out of definition time and into method bodies. Call super first so AR registers reflections (preserving eager loading support), then override accessors with runtime ActiveHash checks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When source_type is present, resolve the class at runtime and look up by foreign key directly, bypassing AR's polymorphic belongs_to which does not work with ActiveHash. Fixes active-hash#334. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
update: fixed N+1 entry and ensure it is exposing a relation instead of an array. |
Resolving classes at definition time can deadlock in production. AR holds a schema lock and a class-load lock. Loading one class that triggers loading another will hit both locks and hang.
belongs_toandhas_many :throughnow resolve ActiveHash classes at runtime, avoiding the deadlockhas_many :throughwithsource_type(fixes Polymorphichas_manywith asource_typeraise an exception in ActiveHash 4.0 #334)Note:
belongs_to_active_hashis unchanged and still available for direct use.Thank you, @alexgriff, for the reproducer.