Skip to content
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

Reduce the number of requests when reifying items. #1238

Conversation

Nike0
Copy link

@Nike0 Nike0 commented Mar 18, 2020

Hello,

During development, I've found that when we are trying to reify the destroyed record from the versions table, it tries to load this record from the original table twice.
I've added an additional condition for the destroy event and done some code refactoring (Rubocop didn't pass).

I don't know which type is this fix (bug or feature), so I didn't add information to the changelog file.

Copy link
Member

@gurgelrenan gurgelrenan left a comment

Choose a reason for hiding this comment

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

Hello @Nike0 . First, thanks for your time and for this P.R! \o/

I just made a comment in a line of code and I want to know another detail:

Did you know how much queries do you avoid? Like from X queries to Y?

Again, thanks for your time to contribute to PaperTrail!

Comment on lines +60 to +61
model = if options[:dup] == true || destroy_event?(version)
klass.new
Copy link
Member

Choose a reason for hiding this comment

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

The previous verification to return klass.new was:

if options[:dup] || (item_found = klass.unscoped.where(find_cond).first).nil?

I'm not sure that destroy_event?(version) is the same thing here. Could you explain?

Copy link
Author

Choose a reason for hiding this comment

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

Hi @gurgelrenan. I try to explain my changes.
First of all, the count of queries for reifying destroyed objects without option :dup was reduced from 2 to 0.
Here is the first place, when we try to load not existed records from the original table:

if options[:dup] != true && version.item

Second place was here:

if options[:dup] || (item_found = klass.unscoped.where(find_cond).first).nil?

Again, we try to find not existed record from the original table.

The previous verification to return klass.new was:

if options[:dup] || (item_found = klass.unscoped.where(find_cond).first).nil?

I'm not sure that destroy_event?(version) is the same thing here. Could you explain?

Yes, destroy_event?(version) is not the same thing. It was added as a new condition. We don't need to load not existed records. The old condition was moved below into else block.

In the esle block we trying to load item directly, then without scope and if nothing was found, return a new object.

If you want I can create a table to demonstrate all possible test cases for my fix and old solution. My fix affects only items with destroy action. For the create and update actions logic still the same.

@gurgelrenan
Copy link
Member

@Nike0 thanks for your explanation. This LGTM, but I would like @jaredbeck take a look.

@jaredbeck
Copy link
Member

Hi Ilya, thanks for contributing this optimization. Before I review the code changes, what is a good test I can run that demonstrates the unnecessary queries? For example, animal_spec.rb:63 seems to select from animals twice.

  Animal Load (0.2ms)  SELECT "animals".* FROM "animals" WHERE "animals"."id" = $1 LIMIT $2  
[["id", 27], ["LIMIT", 1]]
  Cat Load (0.2ms)  SELECT "animals".* FROM "animals" WHERE "animals"."species" = $1 AND "animals"."id" = $2 ORDER BY "animals"."id" ASC LIMIT $3  
[["species", "Cat"], ["id", 27], ["LIMIT", 1]]

Is this a good example? Is there a better example? Thanks.

@Nike0
Copy link
Author

Nike0 commented Apr 28, 2020

Hi Ilya, thanks for contributing this optimization. Before I review the code changes, what is a good test I can run that demonstrates the unnecessary queries? For example, animal_spec.rb:63 seems to select from animals twice.

  Animal Load (0.2ms)  SELECT "animals".* FROM "animals" WHERE "animals"."id" = $1 LIMIT $2  
[["id", 27], ["LIMIT", 1]]
  Cat Load (0.2ms)  SELECT "animals".* FROM "animals" WHERE "animals"."species" = $1 AND "animals"."id" = $2 ORDER BY "animals"."id" ASC LIMIT $3  
[["species", "Cat"], ["id", 27], ["LIMIT", 1]]

Is this a good example? Is there a better example? Thanks.

Hi Jared.
Yes, this is a good example. There will no longer be unnecessary requests from the animals table with my changes.

Copy link
Member

@jaredbeck jaredbeck left a comment

Choose a reason for hiding this comment

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

LGTM. I've examined some test logs, and there are, as expected, fewer queries after this optimization. Nice work, Ilya!

After merging, I may make some stylistic changes to this. In particular, I might move destroy_event? to VersionConcern.

@jaredbeck jaredbeck merged commit d504c6a into paper-trail-gem:master May 3, 2020
jaredbeck added a commit that referenced this pull request May 3, 2020
jaredbeck added a commit that referenced this pull request May 3, 2020
@Nike0 Nike0 deleted the reduce-number-of-requests-when-reifying-item branch May 4, 2020 09:45
hosamaly added a commit to hosamaly/paper_trail that referenced this pull request Feb 21, 2021
v11.0.0

* tag 'v11.0.0': (56 commits)
  Release 11.0.0
  Lint: Fix RSpec/InstanceVariable
  Lint: Fix RSpec/NestedGroups
  Lint: Fix RSpec/HooksBeforeExamples
  Lint: Fix Layout/ArgumentAlignment
  Lint: Fix Style/ExplicitBlockArgument
  Breaking: privatize VersionConcern#sibling_versions
  rubocop 0.89.1 (was 0.88.0)
  Remove development dependency: PT-AT
  Skip creating version for timestamp when changed attributed is ignored via Hash
  Updates rubocop gems
  Updates Readme ignore and only sections
  Update rubocop to 0.85.1, enable pending cops
  Update Appraisal version constraints
  Convert `item_id` field to bigint (paper-trail-gem#1245)
  rspec-rails 4.0.0 (was 3.9.1)
  Fix deprecation warning re: represent_boolean_as_integer
  rubocop 0.82.0 (was 0.80.1)
  Docs: Changelog entry for paper-trail-gem#1238
  rake 13.0.1 (was 12.3.3)
  ...
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.

3 participants