backfill conversations_* tables
* read from `conversations`, which already has root_account_ids * copy those, which are comma-separated values in a string, to: * conversation_messages * conversation_participants * conversation_message_participants, through conversation_messages closes INTEROP-5853, INTEROP-5854, INTEROP-5855, INTEROP-5856 flag=none test plan * specs * in the UI, create a conversation chain between two users * in a rails console, note that the conversation has a root_account_ids field * note that the Conversation's `conversation_messages`, `conversation_participants`, and `conversation_message_participants` all have those root account ids as well, since there is logic to populate those on save * for each of those associations, run `association.update_all("root_account_ids=NULL")` * then run `DataFixup:PopulateRootAccountIdsOnConversationsTables.run` * note that the root_account_ids fields for all associations match the field on the conversation Change-Id: I98ac281291c2105240610b0a0690a544c7d082a7 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/241978 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Cody Cutrer <cody@instructure.com> QA-Review: Xander Moffatt <xmoffatt@instructure.com> Product-Review: Xander Moffatt <xmoffatt@instructure.com>
This commit is contained in:
parent
a27c202a63
commit
24153c85c9
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
class PopulateRootAccountIdsOnConversationsTables < ActiveRecord::Migration[5.2]
|
||||
tag :postdeploy
|
||||
|
||||
def up
|
||||
Conversation.find_ids_in_ranges(batch_size: 100_000) do |min, max|
|
||||
DataFixup::PopulateRootAccountIdsOnConversationsTables.send_later_if_production_enqueue_args(
|
||||
:run,
|
||||
{:priority => Delayed::LOWER_PRIORITY, :n_strand => ["root_account_id_backfill_strand", Shard.current.database_server.id]},
|
||||
min, max
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
module DataFixup::PopulateRootAccountIdsOnConversationsTables
|
||||
def self.run(min, max)
|
||||
Conversation.find_ids_in_ranges(start_at: min, end_at: max) do |batch_min, batch_max|
|
||||
ConversationParticipant.joins(:conversation).
|
||||
where(conversation: batch_min..batch_max).
|
||||
update_all("root_account_ids=conversations.root_account_ids")
|
||||
|
||||
messages = ConversationMessage.joins(:conversation).where(conversation: batch_min..batch_max)
|
||||
messages.update_all("root_account_ids=conversations.root_account_ids")
|
||||
|
||||
# only has FK to ConversationMessage and ConversationParticipant, not Conversation
|
||||
ConversationMessageParticipant.joins(:conversation_message).
|
||||
where(conversation_message: messages).
|
||||
update_all("root_account_ids=conversation_messages.root_account_ids")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,130 @@
|
|||
#
|
||||
# Copyright (C) 2020 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe DataFixup::PopulateRootAccountIdsOnConversationsTables do
|
||||
|
||||
def ids_to_string(*ids)
|
||||
ids.sort.join(',')
|
||||
end
|
||||
|
||||
def reset_root_account_ids(*models)
|
||||
models.each { |m| m.update_column(:root_account_ids, nil) }
|
||||
end
|
||||
|
||||
def check_root_account_ids(expected, *models)
|
||||
models.each { |m| expect(m.reload.root_account_ids).to eq expected}
|
||||
end
|
||||
|
||||
before :once do
|
||||
@root_account1 = account_model
|
||||
@root_account2 = account_model
|
||||
@user1 = user_model
|
||||
@user2 = user_model
|
||||
end
|
||||
|
||||
def check_conversation_messages(conversation, ids)
|
||||
cm1 = ConversationMessage.create!(conversation: conversation)
|
||||
cm2 = ConversationMessage.create!(conversation: conversation)
|
||||
reset_root_account_ids(cm1, cm2)
|
||||
DataFixup::PopulateRootAccountIdsOnConversationsTables.run(conversation.id, conversation.id)
|
||||
check_root_account_ids(ids, cm1, cm2)
|
||||
end
|
||||
|
||||
def check_conversation_participants(conversation, ids)
|
||||
cp1 = ConversationParticipant.create!(conversation: conversation, user: @user1)
|
||||
cp2 = ConversationParticipant.create!(conversation: conversation, user: @user2)
|
||||
reset_root_account_ids(cp1, cp2)
|
||||
DataFixup::PopulateRootAccountIdsOnConversationsTables.run(conversation.id, conversation.id)
|
||||
check_root_account_ids(ids, cp1, cp2)
|
||||
end
|
||||
|
||||
def check_conversation_message_participants(conversation, ids)
|
||||
cm1 = ConversationMessage.create!(conversation: conversation)
|
||||
cm2 = ConversationMessage.create!(conversation: conversation)
|
||||
cmp1 = ConversationMessageParticipant.create!(conversation_message: cm1, user: @user1)
|
||||
cmp2 = ConversationMessageParticipant.create!(conversation_message: cm2, user: @user2)
|
||||
reset_root_account_ids(cm1, cm2, cmp1, cmp2)
|
||||
DataFixup::PopulateRootAccountIdsOnConversationsTables.run(conversation.id, conversation.id)
|
||||
check_root_account_ids(ids, cmp1, cmp2)
|
||||
end
|
||||
|
||||
context 'single-account Conversation' do
|
||||
before :once do
|
||||
@ids = [@root_account1.id]
|
||||
@c = Conversation.create!(root_account_ids: ids_to_string(@root_account1.id))
|
||||
end
|
||||
|
||||
it 'sets root account id on all associated ConversationMessages' do
|
||||
check_conversation_messages(@c, @ids)
|
||||
end
|
||||
|
||||
it 'sets root account id on all associated ConversationParticipants' do
|
||||
check_conversation_participants(@c, @ids)
|
||||
end
|
||||
|
||||
it 'sets root account id on all ConversationMessageParticipants through ConversationMessage' do
|
||||
check_conversation_message_participants(@c, @ids)
|
||||
end
|
||||
end
|
||||
|
||||
context 'multiple-account Conversation' do
|
||||
before :once do
|
||||
@ids = [@root_account1.id, @root_account2.id]
|
||||
@c = Conversation.create!(root_account_ids: ids_to_string(@root_account1.id, @root_account2.id))
|
||||
end
|
||||
|
||||
it 'sets root account ids on all associated ConversationMessages' do
|
||||
check_conversation_messages(@c, @ids)
|
||||
end
|
||||
|
||||
it 'sets root account ids on all associated ConversationParticipants' do
|
||||
check_conversation_participants(@c, @ids)
|
||||
end
|
||||
|
||||
it 'sets root account ids on all ConversationMessageParticipants through ConversationMessage' do
|
||||
check_conversation_message_participants(@c, @ids)
|
||||
end
|
||||
end
|
||||
|
||||
context 'cross-shard Conversation' do
|
||||
specs_require_sharding
|
||||
|
||||
before :once do
|
||||
cross_shard_account = @shard1.activate do
|
||||
account_model
|
||||
end
|
||||
|
||||
@ids = [@root_account1.id, cross_shard_account.id]
|
||||
@c = Conversation.create!(root_account_ids: ids_to_string(@root_account1.id, cross_shard_account.id))
|
||||
end
|
||||
|
||||
it 'sets root account ids on all associated ConversationMessages' do
|
||||
check_conversation_messages(@c, @ids)
|
||||
end
|
||||
|
||||
it 'sets root account ids on all associated ConversationParticipants' do
|
||||
check_conversation_participants(@c, @ids)
|
||||
end
|
||||
|
||||
it 'sets root account ids on all ConversationMessageParticipants through ConversationMessage' do
|
||||
check_conversation_message_participants(@c, @ids)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue