activerecord-delay_touching
activerecord-delay_touching copied to clipboard
Add Rails 5 support
This PR adds Rails 5.0 support to the activerecord-delay_touching
gem.
This PR does not break Rails 4.0 compatibility.
Rspec has passed against both latest Rails version 5.2.1 and 4.2.9.
One drawback of this implementation is it does not respect time
in xxx.touch(time: time)
, it will only be filled with current time.
Hi @Kenneth-KT. Our general stance has been that this library will not need to support Rails 5, due to changes being made in Rails core that have similar goals. See https://github.com/godaddy/activerecord-delay_touching/issues/13#issuecomment-285949342.
Is there something that this library does that's missing in the Rails 5 solution, which would make it beneficial for us to support Rails 5?
Hi @Kenneth-KT. Our general stance has been that this library will not need to support Rails 5, due to changes being made in Rails core that have similar goals. See #13 (comment).
Is there something that this library does that's missing in the Rails 5 solution, which would make it beneficial for us to support Rails 5?
@mtuckergd Yes, this library does have features that ActiveRecord 5.0 does not provide.
- It only touches the same record once across multiple transactions.
- It aggregates touch calls of multiple records within the same table in one SQL.
Consider the following code sample:
person = Person.create!
pets = 100.times.collect { Pet.create!(person: person) }
pets.each_slice(10) do |part_of_pets|
ActiveRecord::Base.transaction do
part_of_pets.each { |x| x.touch_later }
end
end
This code sample generates 110 queries:
Query #1: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #2: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #3: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #4: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #5: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #6: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #7: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #8: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #9: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #10: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #11: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #12: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #13: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #14: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #15: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #16: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #17: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #18: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #19: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #20: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #21: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #22: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #23: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #24: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #25: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #26: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #27: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #28: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #29: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #30: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #31: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #32: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #33: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #34: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #35: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #36: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #37: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #38: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #39: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #40: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #41: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #42: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #43: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #44: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #45: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #46: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #47: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #48: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #49: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #50: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #51: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #52: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #53: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #54: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #55: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #56: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #57: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #58: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #59: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #60: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #61: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #62: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #63: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #64: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #65: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #66: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #67: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #68: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #69: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #70: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #71: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #72: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #73: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #74: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #75: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #76: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #77: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #78: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #79: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #80: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #81: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #82: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #83: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #84: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #85: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #86: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #87: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #88: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #89: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #90: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #91: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #92: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #93: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #94: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #95: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #96: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #97: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #98: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #99: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #100: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #101: UPDATE "people" SET "updated_at" = ? WHERE "people"."id" = ?
Query #102: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #103: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #104: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #105: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #106: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #107: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #108: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #109: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
Query #110: UPDATE "pets" SET "updated_at" = ? WHERE "pets"."id" = ?
You can see that the same People
record has got updated 10 times because touch_later
could not work across multiple transactions.
Also, there are 100 updates to pets
because it cannot aggregate multiple record touches within the same table into one single SQL.
If we wrap the code with delay_touching
, as in this code sample:
person = Person.create!
pets = 100.times.collect { Pet.create!(person: person) }
ActiveRecord::Base.delay_touching do
pets.each_slice(10) do |part_of_pets|
ActiveRecord::Base.transaction do
part_of_pets.each { |x| x.touch_later }
end
end
end
It only generates 2 queries:
Query #1: UPDATE "pets" SET "updated_at" = '2018-11-21 13:38:51.589657' WHERE "pets"."id" IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Query #2: UPDATE "people" SET "updated_at" = '2018-11-21 13:38:51.599752' WHERE "people"."id" = ?
We are running a production system that needs to support bulk importing and updating 100k+ record on daily basis, all those queries saved dramatically improved performance of our system.