Skip to content

Comments

Fix infinite loop issue in identity comparison#1

Closed
krainboltgreene wants to merge 16 commits intogoatapp:masterfrom
krainboltgreene:patch-1
Closed

Fix infinite loop issue in identity comparison#1
krainboltgreene wants to merge 16 commits intogoatapp:masterfrom
krainboltgreene:patch-1

Conversation

@krainboltgreene
Copy link

@krainboltgreene krainboltgreene commented Aug 8, 2018

See: godaddy#14 for more details.

Solution:

  1. At the beginning of application (after transaction end) rehash the sets and remove any non-persisted records
  2. When checking for more records also ensure that the values are empty ({nil => Set.new}.present? == true)


def remove_unpersisted_records!
@records.each do |_, set|
set.instance_variable_get(:@hash).rehash
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this may rely on ActiveRecord's sync_with_transaction_state being invoked upstream. From the AR source, that method is lazily executed, and if it's not run, I think rehash will have no effect.

For that reason, I think it's clearer to invoke explicitly here (as suggested in godaddy#14), whether it's via the private method itself or some public API.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'm surprised this works? Hmm.

# Apply the touches that were delayed.
def self.apply
begin
# If we don't do this then an infinite loop is possible due to how Set#subtract and ActiveRecord::Core#== work
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to nit pick, but I think Set#subtract and ActiveRecord::Core#== work as expected (even together), it's just that the object unintuitively changes in memory after it was used as a hash key. The fact that Hash#rehash already exists means that it's not that uncommon an issue; the problem here is that effects of the id-unsetting logic in ActiveRecord are not immediately obvious.

Would be in favor of clarifying this comment (or clarifying it and moving it to the definition of remove_unpersisted_records).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point.

@oehlschl oehlschl closed this Jan 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants