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