Scope clear_search_records to the account being destroyed (#2847)
Account::Searchable#clear_search_records called Search::Record.for(id).destroy_all which deleted every row in the shard's table, wiping search records belonging to every other account that happened to hash to the same shard. ref: https://3.basecamp.com/2914079/buckets/27/card_tables/cards/9782824728
This commit is contained in:
@@ -9,6 +9,6 @@ module Account::Searchable
|
||||
|
||||
private
|
||||
def clear_search_records
|
||||
Search::Record.for(id).destroy_all
|
||||
Search::Record.for(id).where(account_id: id).destroy_all
|
||||
end
|
||||
end
|
||||
|
||||
@@ -176,4 +176,45 @@ class Account::IncineratableTest < ActiveSupport::TestCase
|
||||
# Search records (sharded)
|
||||
assert_empty Search::Record.for(account_id).where(account_id: account_id)
|
||||
end
|
||||
|
||||
test "incinerating an account clears its own search records but preserves others on the same shard" do
|
||||
doomed = accounts(:initech)
|
||||
shard = Search::Record.for(doomed.id)
|
||||
|
||||
doomed_card = cards(:radio)
|
||||
doomed_record = shard.create!(
|
||||
account_id: doomed_card.account_id,
|
||||
searchable_type: "Card",
|
||||
searchable_id: doomed_card.id,
|
||||
card_id: doomed_card.id,
|
||||
board_id: doomed_card.board_id,
|
||||
title: "doomed",
|
||||
content: "should be destroyed",
|
||||
created_at: Time.current
|
||||
)
|
||||
|
||||
# Simulate a shard collision: plant a record belonging to a different
|
||||
# account directly on doomed's shard, as would happen in production when
|
||||
# two accounts' UUIDs hash to the same shard.
|
||||
foreign_card = cards(:logo)
|
||||
foreign_record = shard.create!(
|
||||
account_id: foreign_card.account_id,
|
||||
searchable_type: "Card",
|
||||
searchable_id: foreign_card.id,
|
||||
card_id: foreign_card.id,
|
||||
board_id: foreign_card.board_id,
|
||||
title: "foreign",
|
||||
content: "should survive",
|
||||
created_at: Time.current
|
||||
)
|
||||
|
||||
Current.account = doomed
|
||||
Current.session = Session.new(identity: identities(:mike))
|
||||
doomed.incinerate
|
||||
|
||||
assert_not shard.exists?(id: doomed_record.id),
|
||||
"the incinerated account's search record should be destroyed"
|
||||
assert shard.exists?(id: foreign_record.id),
|
||||
"another account's search record on the same shard should survive"
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user